Class: MachO::FatFile

Inherits:
Object
  • Object
show all
Defined in:
lib/macho/fat_file.rb

Overview

Represents a “Fat” file, which contains a header, a listing of available architectures, and one or more Mach-O binaries.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename) ⇒ FatFile

Creates a new FatFile from the given filename.

Parameters:

  • filename (String)

    the fat file to load from

Raises:



20
21
22
23
24
25
26
27
28
# File 'lib/macho/fat_file.rb', line 20

def initialize(filename)
  raise ArgumentError.new("filename must be a String") unless filename.is_a? String

  @filename = filename
  @raw_data = open(@filename, "rb") { |f| f.read }
  @header = get_fat_header
  @fat_archs = get_fat_archs
  @machos = get_machos
end

Instance Attribute Details

#fat_archsArray<MachO::FatArch> (readonly)

Returns an array of fat architectures.

Returns:



11
12
13
# File 'lib/macho/fat_file.rb', line 11

def fat_archs
  @fat_archs
end

#headerMachO::FatHeader (readonly)

Returns the file’s header.

Returns:



8
9
10
# File 'lib/macho/fat_file.rb', line 8

def header
  @header
end

#machosArray<MachO::MachOFile> (readonly)

Returns an array of Mach-O binaries.

Returns:



14
15
16
# File 'lib/macho/fat_file.rb', line 14

def machos
  @machos
end

Instance Method Details

#change_install_name(old_name, new_name) ⇒ Object Also known as: change_dylib

TODO:

incomplete

Changes all dependent shared library install names from ‘old_name` to `new_name`. In a fat file, this changes install names in all internal Mach-Os.

Examples:

file.change_install_name('/usr/lib/libFoo.dylib', '/usr/lib/libBar.dylib')

Parameters:

  • old_name (String)

    the shared library name being changed

  • new_name (String)

    the new name



91
92
93
94
95
96
97
# File 'lib/macho/fat_file.rb', line 91

def change_install_name(old_name, new_name)
  machos.each do |macho|
    macho.change_install_name(old_name, new_name)
  end

  synchronize_raw_data
end

#dylib_idString

The file’s dylib ID. If the file is not a dylib, returns ‘nil`.

Examples:

file.dylib_id # => 'libBar.dylib'

Returns:

  • (String)

    the file’s dylib ID



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/macho/fat_file.rb', line 40

def dylib_id
  if !machos.all?(&:dylib?)
    return nil
  end

  ids = machos.map(&:dylib_id)

  # this should never be the case, but let's be defensive
  if !ids.uniq!.size == 1
    return nil
  end

  ids.first
end

#dylib_id=(new_id) ⇒ Object

Changes the file’s dylib ID to ‘new_id`. If the file is not a dylib, does nothing.

Examples:

file.dylib_id = 'libFoo.dylib'

Parameters:

  • new_id (String)

    the new dylib ID



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/macho/fat_file.rb', line 59

def dylib_id=(new_id)
  if !new_id.is_a?(String)
    raise ArgumentError.new("argument must be a String")
  end

  if !machos.all?(&:dylib?)
    return nil
  end

  machos.each do |macho|
    macho.dylib_id = new_id
  end

  synchronize_raw_data
end

#extract(cputype) ⇒ MachO::MachOFile?

Extract a Mach-O with the given CPU type from the file.

Examples:

file.extract("CPU_TYPE_I386") # => MachO::MachOFile

Parameters:

  • cputype (String)

    the CPU type of the Mach-O being extracted

Returns:

  • (MachO::MachOFile, nil)

    the extracted Mach-O or nil if no Mach-O has the given CPU type



106
107
108
# File 'lib/macho/fat_file.rb', line 106

def extract(cputype)
  machos.select { |macho| macho.cputype == cputype }.first
end

#linked_dylibsArray<String>

All shared libraries linked to the file’s Mach-Os.

Returns:

  • (Array<String>)

    an array of all shared libraries



77
78
79
80
81
82
# File 'lib/macho/fat_file.rb', line 77

def linked_dylibs
  dylibs = machos.map(&:linked_dylibs).flatten

  # can machos inside fat binaries have different dylibs?
  dylibs.uniq!
end

#serializeString

The file’s raw fat data.

Returns:

  • (String)

    the raw fat data



32
33
34
# File 'lib/macho/fat_file.rb', line 32

def serialize
  @raw_data
end

#write(filename) ⇒ Object

Write all (fat) data to the given filename.

Parameters:

  • filename (String)

    the file to write to



112
113
114
# File 'lib/macho/fat_file.rb', line 112

def write(filename)
  File.open(filename, "wb") { |f| f.write(@raw_data) }
end

#write!Object

Note:

Overwrites all data in the file!

Write all (fat) data to the file used to initialize the instance.



118
119
120
# File 'lib/macho/fat_file.rb', line 118

def write!
  File.open(@filename, "wb") { |f| f.write(@raw_data) }
end