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



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

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



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

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



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

def filename
  @filename
end

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

Returns:



24
25
26
# File 'lib/macho/macho_file.rb', line 24

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:



29
30
31
# File 'lib/macho/macho_file.rb', line 29

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



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

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:



36
37
38
39
40
41
# File 'lib/macho/macho_file.rb', line 36

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:



205
206
207
# File 'lib/macho/macho_file.rb', line 205

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:



397
398
399
400
401
402
# File 'lib/macho/macho_file.rb', line 397

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



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

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:



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

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:



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

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:



139
140
141
# File 'lib/macho/macho_file.rb', line 139

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



128
129
130
# File 'lib/macho/macho_file.rb', line 128

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



123
124
125
# File 'lib/macho/macho_file.rb', line 123

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



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

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:



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

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. this
  # allows us to defer (expensive) field population until the very end
  rpath_cmds.reverse_each { |cmd| delete_command(cmd, :repopulate => false) }

  populate_fields
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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



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

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:



244
245
246
# File 'lib/macho/macho_file.rb', line 244

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



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

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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:



60
61
62
63
64
65
# File 'lib/macho/macho_file.rb', line 60

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:



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

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



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

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



113
114
115
# File 'lib/macho/macho_file.rb', line 113

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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.



237
238
239
240
# File 'lib/macho/macho_file.rb', line 237

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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:



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

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



360
361
362
# File 'lib/macho/macho_file.rb', line 360

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



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

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:



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

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



69
70
71
# File 'lib/macho/macho_file.rb', line 69

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



107
108
109
110
# File 'lib/macho/macho_file.rb', line 107

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:



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

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



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

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



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

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

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