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

Class Method 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:

  • (ArgumentError)

    if the given file does not exist



32
33
34
35
36
37
38
# File 'lib/macho/fat_file.rb', line 32

def initialize(filename)
  raise ArgumentError, "#{filename}: no such file" unless File.file?(filename)

  @filename = filename
  @raw_data = File.open(@filename, "rb", &:read)
  populate_fields
end

Instance Attribute Details

#fat_archsArray<MachO::FatArch> (readonly)

Returns an array of fat architectures.

Returns:



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

def fat_archs
  @fat_archs
end

#filenameString

Returns the filename loaded from, or nil if loaded from a binary string.

Returns:

  • (String)

    the filename loaded from, or nil if loaded from a binary string



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

def filename
  @filename
end

#headerMachO::FatHeader (readonly)

Returns the file's header.

Returns:



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

def header
  @header
end

#machosArray<MachO::MachOFile> (readonly)

Returns an array of Mach-O binaries.

Returns:



17
18
19
# File 'lib/macho/fat_file.rb', line 17

def machos
  @machos
end

Class Method Details

.new_from_bin(bin) ⇒ MachO::FatFile

Creates a new FatFile instance from a binary string.

Parameters:

  • bin (String)

    a binary string containing raw Mach-O data

Returns:



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

def self.new_from_bin(bin)
  instance = allocate
  instance.initialize_from_bin(bin)

  instance
end

Instance Method Details

#add_rpath(path, options = {}) ⇒ void

This method returns an undefined value.

Add the given runtime path to the file's Mach-Os.

Parameters:

  • path (String)

    the new runtime path

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :strict (Boolean) — default: true

    if true, fail if one slice fails. if false, fail only if all slices fail.

See Also:



230
231
232
233
234
235
236
# File 'lib/macho/fat_file.rb', line 230

def add_rpath(path, options = {})
  each_macho(options) do |macho|
    macho.add_rpath(path, options)
  end

  repopulate_raw_machos
end

#bundle?Boolean

Returns true if the file is of type MH_BUNDLE, false otherwise.

Returns:

  • (Boolean)

    true if the file is of type MH_BUNDLE, false otherwise



91
92
93
# File 'lib/macho/fat_file.rb', line 91

def bundle?
  machos.first.bundle?
end

#change_dylib_id(new_id, options = {}) ⇒ void Also known as: dylib_id=

This method returns an undefined value.

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

Examples:

file.change_dylib_id('libFoo.dylib')

Parameters:

  • new_id (String)

    the new dylib ID

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :strict (Boolean) — default: true

    if true, fail if one slice fails. if false, fail only if all slices fail.

Raises:

  • (ArgumentError)

    if new_id is not a String

See Also:



155
156
157
158
159
160
161
162
163
164
# File 'lib/macho/fat_file.rb', line 155

def change_dylib_id(new_id, options = {})
  raise ArgumentError, "argument must be a String" unless new_id.is_a?(String)
  return unless machos.all?(&:dylib?)

  each_macho(options) do |macho|
    macho.change_dylib_id(new_id, options)
  end

  repopulate_raw_machos
end

#change_install_name(old_name, new_name, options = {}) ⇒ void Also known as: change_dylib

This method returns an undefined value.

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

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :strict (Boolean) — default: true

    if true, fail if one slice fails. if false, fail only if all slices fail.

See Also:



189
190
191
192
193
194
195
# File 'lib/macho/fat_file.rb', line 189

def change_install_name(old_name, new_name, options = {})
  each_macho(options) do |macho|
    macho.change_install_name(old_name, new_name, options)
  end

  repopulate_raw_machos
end

#change_rpath(old_path, new_path, options = {}) ⇒ void

This method returns an undefined value.

Change the runtime path old_path to new_path in the file's Mach-Os.

Parameters:

  • old_path (String)

    the old runtime path

  • new_path (String)

    the new runtime path

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :strict (Boolean) — default: true

    if true, fail if one slice fails. if false, fail only if all slices fail.

See Also:



215
216
217
218
219
220
221
# File 'lib/macho/fat_file.rb', line 215

def change_rpath(old_path, new_path, options = {})
  each_macho(options) do |macho|
    macho.change_rpath(old_path, new_path, options)
  end

  repopulate_raw_machos
end

#core?Boolean

Returns true if the file is of type MH_CORE, false otherwise.

Returns:

  • (Boolean)

    true if the file is of type MH_CORE, false otherwise



71
72
73
# File 'lib/macho/fat_file.rb', line 71

def core?
  machos.first.core?
end

#delete_rpath(path, options = {}) ⇒ Object

Delete the given runtime path from the file's Mach-Os.

Parameters:

  • path (String)

    the runtime path to delete

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :strict (Boolean) — default: true

    if true, fail if one slice fails. if false, fail only if all slices fail.

Returns:

  • void

See Also:



245
246
247
248
249
250
251
# File 'lib/macho/fat_file.rb', line 245

def delete_rpath(path, options = {})
  each_macho(options) do |macho|
    macho.delete_rpath(path, options)
  end

  repopulate_raw_machos
end

#dsym?Boolean

Returns true if the file is of type MH_DSYM, false otherwise.

Returns:

  • (Boolean)

    true if the file is of type MH_DSYM, false otherwise



96
97
98
# File 'lib/macho/fat_file.rb', line 96

def dsym?
  machos.first.dsym?
end

#dylib?Boolean

Returns true if the file is of type MH_DYLIB, false otherwise.

Returns:

  • (Boolean)

    true if the file is of type MH_DYLIB, false otherwise



81
82
83
# File 'lib/macho/fat_file.rb', line 81

def dylib?
  machos.first.dylib?
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, nil)

    the file's dylib ID

See Also:



141
142
143
# File 'lib/macho/fat_file.rb', line 141

def dylib_id
  machos.first.dylib_id
end

#dylib_load_commandsArray<MachO::DylibCommand>

All load commands responsible for loading dylibs in the file's Mach-O's.

Returns:



132
133
134
# File 'lib/macho/fat_file.rb', line 132

def dylib_load_commands
  machos.map(&:dylib_load_commands).flatten
end

#dylinker?Boolean

Returns true if the file is of type MH_DYLINKER, false otherwise.

Returns:

  • (Boolean)

    true if the file is of type MH_DYLINKER, false otherwise



86
87
88
# File 'lib/macho/fat_file.rb', line 86

def dylinker?
  machos.first.dylinker?
end

#executable?Boolean

Returns true if the file is of type MH_EXECUTE, false otherwise.

Returns:

  • (Boolean)

    true if the file is of type MH_EXECUTE, false otherwise



61
62
63
# File 'lib/macho/fat_file.rb', line 61

def executable?
  machos.first.executable?
end

#extract(cputype) ⇒ MachO::MachOFile?

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

Examples:

file.extract(:i386) # => MachO::MachOFile

Parameters:

  • cputype (Symbol)

    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



258
259
260
# File 'lib/macho/fat_file.rb', line 258

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

#filetypeSymbol

The file's type. Assumed to be the same for every Mach-O within.

Returns:

  • (Symbol)

    the filetype



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

def filetype
  machos.first.filetype
end

#fvmlib?Boolean

Returns true if the file is of type MH_FVMLIB, false otherwise.

Returns:

  • (Boolean)

    true if the file is of type MH_FVMLIB, false otherwise



66
67
68
# File 'lib/macho/fat_file.rb', line 66

def fvmlib?
  machos.first.fvmlib?
end

#initialize_from_bin(bin) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Initializes a new FatFile instance from a binary string.

See Also:



43
44
45
46
47
# File 'lib/macho/fat_file.rb', line 43

def initialize_from_bin(bin)
  @filename = nil
  @raw_data = bin
  populate_fields
end

#kext?Boolean

Returns true if the file is of type MH_KEXT_BUNDLE, false otherwise.

Returns:

  • (Boolean)

    true if the file is of type MH_KEXT_BUNDLE, false otherwise



101
102
103
# File 'lib/macho/fat_file.rb', line 101

def kext?
  machos.first.kext?
end

#linked_dylibsArray<String>

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

Returns:

  • (Array<String>)

    an array of all shared libraries

See Also:



171
172
173
174
175
176
# File 'lib/macho/fat_file.rb', line 171

def linked_dylibs
  # Individual architectures in a fat binary can link to different subsets
  # of libraries, but at this point we want to have the full picture, i.e.
  # the union of all libraries used by all architectures.
  machos.map(&:linked_dylibs).flatten.uniq
end

#magicFixnum

Returns the file's magic number.

Returns:

  • (Fixnum)

    the file's magic number



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

def magic
  header.magic
end

#magic_stringString

Returns a string representation of the file's magic number.

Returns:

  • (String)

    a string representation of the file's magic number



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

def magic_string
  MH_MAGICS[magic]
end

#object?Boolean

Returns true if the file is of type MH_OBJECT, false otherwise.

Returns:

  • (Boolean)

    true if the file is of type MH_OBJECT, false otherwise



56
57
58
# File 'lib/macho/fat_file.rb', line 56

def object?
  machos.first.object?
end

#populate_fieldsvoid

Note:

This method is public, but should (almost) never need to be called.

This method returns an undefined value.

Populate the instance's fields with the raw Fat Mach-O data.



124
125
126
127
128
# File 'lib/macho/fat_file.rb', line 124

def populate_fields
  @header = populate_fat_header
  @fat_archs = populate_fat_archs
  @machos = populate_machos
end

#preload?Boolean

Returns true if the file is of type MH_PRELOAD, false otherwise.

Returns:

  • (Boolean)

    true if the file is of type MH_PRELOAD, false otherwise



76
77
78
# File 'lib/macho/fat_file.rb', line 76

def preload?
  machos.first.preload?
end

#rpathsArray<String>

All runtime paths associated with the file's Mach-Os.

Returns:

  • (Array<String>)

    an array of all runtime paths

See Also:



202
203
204
205
# File 'lib/macho/fat_file.rb', line 202

def rpaths
  # Can individual architectures have different runtime paths?
  machos.map(&:rpaths).flatten.uniq
end

#serializeString

The file's raw fat data.

Returns:

  • (String)

    the raw fat data



51
52
53
# File 'lib/macho/fat_file.rb', line 51

def serialize
  @raw_data
end

#write(filename) ⇒ Object

Write all (fat) data to the given filename.

Parameters:

  • filename (String)

    the file to write to



264
265
266
# File 'lib/macho/fat_file.rb', line 264

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

#write!void

Note:

Overwrites all data in the file!

This method returns an undefined value.

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

Raises:



272
273
274
275
276
277
278
# File 'lib/macho/fat_file.rb', line 272

def write!
  if filename.nil?
    raise MachOError, "cannot write to a default file when initialized from a binary string"
  else
    File.open(@filename, "wb") { |f| f.write(@raw_data) }
  end
end