Class: MachO::MachOFile

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/macho/macho_file.rb

Overview

Represents a Mach-O file, which contains a header and load commands as well as binary executable instructions. Mach-O binaries are architecture specific.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename, **opts) ⇒ MachOFile

Creates a new instance from data read from the given filename.

Parameters:

  • filename (String)

    the Mach-O file to load from

  • opts (Hash)

    options to control the parser with

Options Hash (**opts):

  • :permissive (Boolean)

    whether to ignore unknown load commands

Raises:

  • (ArgumentError)

    if the given file does not exist



50
51
52
53
54
55
56
57
# File 'lib/macho/macho_file.rb', line 50

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

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

Instance Attribute Details

#endiannessSymbol (readonly)

Returns the endianness of the file, :big or :little.

Returns:

  • (Symbol)

    the endianness of the file, :big or :little



22
23
24
# File 'lib/macho/macho_file.rb', line 22

def endianness
  @endianness
end

#filenameString?

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

Returns:

  • (String, nil)

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



16
17
18
# File 'lib/macho/macho_file.rb', line 16

def filename
  @filename
end

#headerHeaders::MachHeader, Headers::MachHeader64 (readonly)

Returns:



26
27
28
# File 'lib/macho/macho_file.rb', line 26

def header
  @header
end

#load_commandsArray<LoadCommands::LoadCommand> (readonly)

Note:

load commands are provided in order of ascending offset.

Returns an array of the file's load commands.

Returns:



31
32
33
# File 'lib/macho/macho_file.rb', line 31

def load_commands
  @load_commands
end

#optionsHash (readonly)

Returns any parser options that the instance was created with.

Returns:

  • (Hash)

    any parser options that the instance was created with



19
20
21
# File 'lib/macho/macho_file.rb', line 19

def options
  @options
end

Class Method Details

.new_from_bin(bin, **opts) ⇒ MachOFile

Creates a new instance from a binary string.

Parameters:

  • bin (String)

    a binary string containing raw Mach-O data

  • opts (Hash)

    options to control the parser with

Options Hash (**opts):

  • :permissive (Boolean)

    whether to ignore unknown load commands

Returns:



38
39
40
41
42
43
# File 'lib/macho/macho_file.rb', line 38

def self.new_from_bin(bin, **opts)
  instance = allocate
  instance.initialize_from_bin(bin, opts)

  instance
end

Instance Method Details

#add_command(lc, options = {}) ⇒ void

Note:

This is public, but methods like #add_rpath should be preferred. Setting repopulate to false will leave the instance in an inconsistent state unless #populate_fields is called immediately afterwards.

This method returns an undefined value.

Appends a new load command to the Mach-O.

Parameters:

Options Hash (options):

  • :repopulate (Boolean) — default: true

    whether or not to repopulate the instance fields

See Also:



207
208
209
# File 'lib/macho/macho_file.rb', line 207

def add_command(lc, options = {})
  insert_command(header.class.bytesize + sizeofcmds, lc, options)
end

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

Note:

_options is currently unused and is provided for signature compatibility with FatFile#add_rpath

This method returns an undefined value.

Add the given runtime path to the Mach-O.

Examples:

file.rpaths # => ["/lib"]
file.add_rpath("/usr/lib")
file.rpaths # => ["/lib", "/usr/lib"]

Parameters:

  • path (String)

    the new runtime path

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

Raises:



399
400
401
402
403
404
# File 'lib/macho/macho_file.rb', line 399

def add_rpath(path, _options = {})
  raise RpathExistsError, path if rpaths.include?(path)

  rpath_cmd = LoadCommands::LoadCommand.create(:LC_RPATH, path)
  add_command(rpath_cmd)
end

#alignmentInteger

Returns the file's internal alignment.

Returns:

  • (Integer)

    the file's internal alignment



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#bundle?Boolean

Returns whether or not the file is of type MH_BUNDLE.

Returns:

  • (Boolean)

    whether or not the file is of type MH_BUNDLE



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

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

Note:

_options is currently unused and is provided for signature compatibility with FatFile#change_dylib_id

This method returns an undefined value.

Changes the Mach-O's dylib ID to new_id. Does nothing if not a dylib.

Examples:

file.change_dylib_id("libFoo.dylib")

Parameters:

  • new_id (String)

    the dylib's new ID

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

Raises:

  • (ArgumentError)

    if new_id is not a String



309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/macho/macho_file.rb', line 309

def change_dylib_id(new_id, _options = {})
  raise ArgumentError, "new ID must be a String" unless new_id.is_a?(String)
  return unless dylib?

  old_lc = command(:LC_ID_DYLIB).first
  raise DylibIdMissingError unless old_lc

  new_lc = LoadCommands::LoadCommand.create(:LC_ID_DYLIB, new_id,
                                            old_lc.timestamp,
                                            old_lc.current_version,
                                            old_lc.compatibility_version)

  replace_command(old_lc, new_lc)
end

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

Note:

_options is currently unused and is provided for signature compatibility with FatFile#change_install_name

This method returns an undefined value.

Changes the shared library old_name to new_name

Examples:

file.change_install_name("abc.dylib", "def.dylib")

Parameters:

  • old_name (String)

    the shared library's old name

  • new_name (String)

    the shared library's new name

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

Raises:



346
347
348
349
350
351
352
353
354
355
356
# File 'lib/macho/macho_file.rb', line 346

def change_install_name(old_name, new_name, _options = {})
  old_lc = dylib_load_commands.find { |d| d.name.to_s == old_name }
  raise DylibUnknownError, old_name if old_lc.nil?

  new_lc = LoadCommands::LoadCommand.create(old_lc.type, new_name,
                                            old_lc.timestamp,
                                            old_lc.current_version,
                                            old_lc.compatibility_version)

  replace_command(old_lc, new_lc)
end

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

Note:

_options is currently unused and is provided for signature compatibility with FatFile#change_rpath

This method returns an undefined value.

Changes the runtime path old_path to new_path

Examples:

file.change_rpath("/usr/lib", "/usr/local/lib")

Parameters:

  • old_path (String)

    the old runtime path

  • new_path (String)

    the new runtime path

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

Raises:



377
378
379
380
381
382
383
384
385
386
# File 'lib/macho/macho_file.rb', line 377

def change_rpath(old_path, new_path, _options = {})
  old_lc = command(:LC_RPATH).find { |r| r.path.to_s == old_path }
  raise RpathUnknownError, old_path if old_lc.nil?
  raise RpathExistsError, new_path if rpaths.include?(new_path)

  new_lc = LoadCommands::LoadCommand.create(:LC_RPATH, new_path)

  delete_rpath(old_path)
  insert_command(old_lc.view.offset, new_lc)
end

#command(name) ⇒ Array<LoadCommands::LoadCommand> Also known as: []

All load commands of a given name.

Examples:

file.command("LC_LOAD_DYLIB")
file[:LC_LOAD_DYLIB]

Parameters:

  • name (String, Symbol)

    the load command ID

Returns:



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

def command(name)
  load_commands.select { |lc| lc.type == name.to_sym }
end

#core?Boolean

Returns whether or not the file is of type MH_CORE.

Returns:

  • (Boolean)

    whether or not the file is of type MH_CORE



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#cpusubtypeSymbol

Returns a symbol representation of the Mach-O's CPU subtype.

Returns:

  • (Symbol)

    a symbol representation of the Mach-O's CPU subtype



130
131
132
# File 'lib/macho/macho_file.rb', line 130

def cpusubtype
  Headers::CPU_SUBTYPES[header.cputype][header.cpusubtype]
end

#cputypeSymbol

Returns a symbol representation of the Mach-O's CPU type.

Returns:

  • (Symbol)

    a symbol representation of the Mach-O's CPU type



125
126
127
# File 'lib/macho/macho_file.rb', line 125

def cputype
  Headers::CPU_TYPES[header.cputype]
end

#delete_command(lc, options = {}) ⇒ void

Note:

This is public, but methods like #delete_rpath should be preferred. Setting repopulate to false will leave the instance in an inconsistent state unless #populate_fields is called immediately afterwards.

This method returns an undefined value.

Delete a load command from the Mach-O.

Parameters:

Options Hash (options):

  • :repopulate (Boolean) — default: true

    whether or not to repopulate the instance fields



221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/macho/macho_file.rb', line 221

def delete_command(lc, options = {})
  @raw_data.slice!(lc.view.offset, lc.cmdsize)

  # update Mach-O header fields to account for deleted load command
  update_ncmds(ncmds - 1)
  update_sizeofcmds(sizeofcmds - lc.cmdsize)

  # pad the space after the load commands to preserve offsets
  @raw_data.insert(header.class.bytesize + sizeofcmds - lc.cmdsize, Utils.nullpad(lc.cmdsize))

  populate_fields if options.fetch(:repopulate, true)
end

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

Note:

_options is currently unused and is provided for signature compatibility with FatFile#delete_rpath

Delete the given runtime path from the Mach-O.

Examples:

file.rpaths # => ["/lib"]
file.delete_rpath("/lib")
file.rpaths # => []

Parameters:

  • path (String)

    the runtime path to delete

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

Returns:

  • void

Raises:



417
418
419
420
421
422
423
# File 'lib/macho/macho_file.rb', line 417

def delete_rpath(path, _options = {})
  rpath_cmds = command(:LC_RPATH).select { |r| r.path.to_s == path }
  raise RpathUnknownError, path if rpath_cmds.empty?

  # delete the commands in reverse order, offset descending.
  rpath_cmds.reverse_each { |cmd| delete_command(cmd) }
end

#dsym?Boolean

Returns whether or not the file is of type MH_DSYM.

Returns:

  • (Boolean)

    whether or not the file is of type MH_DSYM



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#dylib?Boolean

Returns whether or not the file is of type MH_DYLIB.

Returns:

  • (Boolean)

    whether or not the file is of type MH_DYLIB



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#dylib_idString?

The Mach-O's dylib ID, or nil if not a dylib.

Examples:

file.dylib_id # => 'libBar.dylib'

Returns:

  • (String, nil)

    the Mach-O's dylib ID



292
293
294
295
296
297
298
# File 'lib/macho/macho_file.rb', line 292

def dylib_id
  return unless dylib?

  dylib_id_cmd = command(:LC_ID_DYLIB).first

  dylib_id_cmd.name.to_s
end

#dylib_load_commandsArray<LoadCommands::DylibCommand>

All load commands responsible for loading dylibs.

Returns:



246
247
248
# File 'lib/macho/macho_file.rb', line 246

def dylib_load_commands
  load_commands.select { |lc| LoadCommands::DYLIB_LOAD_COMMANDS.include?(lc.type) }
end

#dylinker?Boolean

Returns whether or not the file is of type MH_DYLINKER.

Returns:

  • (Boolean)

    whether or not the file is of type MH_DYLINKER



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#executable?Boolean

Returns whether or not the file is of type MH_EXECUTE.

Returns:

  • (Boolean)

    whether or not the file is of type MH_EXECUTE



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#filetypeSymbol

Returns a string representation of the Mach-O's filetype.

Returns:

  • (Symbol)

    a string representation of the Mach-O's filetype



120
121
122
# File 'lib/macho/macho_file.rb', line 120

def filetype
  Headers::MH_FILETYPES[header.filetype]
end

#flagsInteger

Returns the header flags associated with the Mach-O.

Returns:

  • (Integer)

    the header flags associated with the Mach-O



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#fvmlib?Boolean

Returns whether or not the file is of type MH_FVMLIB.

Returns:

  • (Boolean)

    whether or not the file is of type MH_FVMLIB



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#initialize_from_bin(bin, opts) ⇒ 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 MachOFile instance from a binary string with the given options.

See Also:



62
63
64
65
66
67
# File 'lib/macho/macho_file.rb', line 62

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

#insert_command(offset, lc, options = {}) ⇒ Object

Note:

Calling this method with an arbitrary offset in the load command region will leave the object in an inconsistent state.

Inserts a load command at the given offset.

Parameters:

  • offset (Integer)

    the offset to insert at

  • lc (LoadCommands::LoadCommand)

    the load command to insert

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

Options Hash (options):

  • :repopulate (Boolean) — default: true

    whether or not to repopulate the instance fields

Raises:



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/macho/macho_file.rb', line 157

def insert_command(offset, lc, options = {})
  context = LoadCommands::LoadCommand::SerializationContext.context_for(self)
  cmd_raw = lc.serialize(context)
  fileoff = offset + cmd_raw.bytesize

  raise OffsetInsertionError, offset if offset < header.class.bytesize || fileoff > low_fileoff

  new_sizeofcmds = sizeofcmds + cmd_raw.bytesize

  raise HeaderPadError, @filename if header.class.bytesize + new_sizeofcmds > low_fileoff

  # update Mach-O header fields to account for inserted load command
  update_ncmds(ncmds + 1)
  update_sizeofcmds(new_sizeofcmds)

  @raw_data.insert(offset, cmd_raw)
  @raw_data.slice!(header.class.bytesize + new_sizeofcmds, cmd_raw.bytesize)

  populate_fields if options.fetch(:repopulate, true)
end

#kext?Boolean

Returns whether or not the file is of type MH_KEXT_BUNDLE.

Returns:

  • (Boolean)

    whether or not the file is of type MH_KEXT_BUNDLE



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#linked_dylibsArray<String>

All shared libraries linked to the Mach-O.

Returns:

  • (Array<String>)

    an array of all shared libraries



328
329
330
331
332
333
334
# File 'lib/macho/macho_file.rb', line 328

def linked_dylibs
  # Some linkers produce multiple `LC_LOAD_DYLIB` load commands for the same
  # library, but at this point we're really only interested in a list of
  # unique libraries this Mach-O file links to, thus: `uniq`. (This is also
  # for consistency with `FatFile` that merges this list across all archs.)
  dylib_load_commands.map(&:name).map(&:to_s).uniq
end

#magicInteger

Returns the magic number.

Returns:

  • (Integer)

    the magic number



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#magic32?Boolean

Returns true if the Mach-O has 32-bit magic, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O has 32-bit magic, false otherwise



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#magic64?Boolean

Returns true if the Mach-O has 64-bit magic, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O has 64-bit magic, false otherwise



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#magic_stringString

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

Returns:

  • (String)

    a string representation of the file's magic number



115
116
117
# File 'lib/macho/macho_file.rb', line 115

def magic_string
  Headers::MH_MAGICS[magic]
end

#ncmdsInteger

Returns the number of load commands in the Mach-O.

Returns:

  • (Integer)

    the number of load commands in the Mach-O



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#object?Boolean

Returns whether or not the file is of type MH_OBJECT.

Returns:

  • (Boolean)

    whether or not the file is of type MH_OBJECT



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#populate_fieldsvoid

Note:

This method is public, but should (almost) never need to be called. The exception to this rule is when methods like #add_command and #delete_command have been called with repopulate = false.

This method returns an undefined value.

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



239
240
241
242
# File 'lib/macho/macho_file.rb', line 239

def populate_fields
  @header = populate_mach_header
  @load_commands = populate_load_commands
end

#preload?Boolean

Returns whether or not the file is of type MH_PRELOAD.

Returns:

  • (Boolean)

    whether or not the file is of type MH_PRELOAD



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#replace_command(old_lc, new_lc) ⇒ void

Note:

This is public, but methods like #dylib_id= should be preferred.

This method returns an undefined value.

Replace a load command with another command in the Mach-O, preserving location.

Parameters:

Raises:

  • (HeaderPadError)

    if the new command exceeds the header pad buffer

See Also:



185
186
187
188
189
190
191
192
193
194
# File 'lib/macho/macho_file.rb', line 185

def replace_command(old_lc, new_lc)
  context = LoadCommands::LoadCommand::SerializationContext.context_for(self)
  cmd_raw = new_lc.serialize(context)
  new_sizeofcmds = sizeofcmds + cmd_raw.bytesize - old_lc.cmdsize

  raise HeaderPadError, @filename if header.class.bytesize + new_sizeofcmds > low_fileoff

  delete_command(old_lc)
  insert_command(old_lc.view.offset, new_lc)
end

#rpathsArray<String>

All runtime paths searched by the dynamic linker for the Mach-O.

Returns:

  • (Array<String>)

    an array of all runtime paths



362
363
364
# File 'lib/macho/macho_file.rb', line 362

def rpaths
  command(:LC_RPATH).map(&:path).map(&:to_s)
end

#segment_alignmentInteger

Note:

This is not the same as #alignment!

Note:

See get_align and get_align_64 in cctools/misc/lipo.c

The segment alignment for the Mach-O. Guesses conservatively.

Returns:

  • (Integer)

    the alignment, as a power of 2



265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/macho/macho_file.rb', line 265

def segment_alignment
  # special cases: 12 for x86/64/PPC/PP64, 14 for ARM/ARM64
  return 12 if %i[i386 x86_64 ppc ppc64].include?(cputype)
  return 14 if %i[arm arm64].include?(cputype)

  cur_align = Sections::MAX_SECT_ALIGN

  segments.each do |segment|
    if filetype == :object
      # start with the smallest alignment, and work our way up
      align = magic32? ? 2 : 3
      segment.sections.each do |section|
        align = section.align unless section.align <= align
      end
    else
      align = segment.guess_align
    end
    cur_align = align if align < cur_align
  end

  cur_align
end

#segmentsArray<LoadCommands::SegmentCommand>, Array<LoadCommands::SegmentCommand64>

All segment load commands in the Mach-O.

Returns:



253
254
255
256
257
258
259
# File 'lib/macho/macho_file.rb', line 253

def segments
  if magic32?
    command(:LC_SEGMENT)
  else
    command(:LC_SEGMENT_64)
  end
end

#serializeString

The file's raw Mach-O data.

Returns:

  • (String)

    the raw Mach-O data



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

def serialize
  @raw_data
end

#sizeofcmdsInteger

Returns the size of all load commands, in bytes, in the Mach-O.

Returns:

  • (Integer)

    the size of all load commands, in bytes, in the Mach-O



109
110
111
112
# File 'lib/macho/macho_file.rb', line 109

def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
:executable?, :fvmlib?, :core?, :preload?, :dylib?,
:dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
:alignment

#to_hHash

Returns a hash representation of this MachO::MachOFile.

Returns:



443
444
445
446
447
448
# File 'lib/macho/macho_file.rb', line 443

def to_h
  {
    "header" => header.to_h,
    "load_commands" => load_commands.map(&:to_h),
  }
end

#write(filename) ⇒ void

This method returns an undefined value.

Write all Mach-O data to the given filename.

Parameters:

  • filename (String)

    the file to write to



428
429
430
# File 'lib/macho/macho_file.rb', line 428

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 Mach-O data to the file used to initialize the instance.

Raises:

  • (MachOError)

    if the instance was initialized without a file



436
437
438
439
440
# File 'lib/macho/macho_file.rb', line 436

def write!
  raise MachOError, "no initial file to write to" if @filename.nil?

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