aboutsummaryrefslogtreecommitdiffstats
path: root/Library
diff options
context:
space:
mode:
Diffstat (limited to 'Library')
-rw-r--r--Library/Homebrew/vendor/README.md4
-rw-r--r--Library/Homebrew/vendor/macho/macho.rb27
-rw-r--r--Library/Homebrew/vendor/macho/macho/exceptions.rb12
-rw-r--r--Library/Homebrew/vendor/macho/macho/fat_file.rb202
-rw-r--r--Library/Homebrew/vendor/macho/macho/headers.rb1176
-rw-r--r--Library/Homebrew/vendor/macho/macho/load_commands.rb2158
-rw-r--r--Library/Homebrew/vendor/macho/macho/macho_file.rb258
-rw-r--r--Library/Homebrew/vendor/macho/macho/open.rb25
-rw-r--r--Library/Homebrew/vendor/macho/macho/sections.rb320
-rw-r--r--Library/Homebrew/vendor/macho/macho/structure.rb2
-rw-r--r--Library/Homebrew/vendor/macho/macho/tools.rb34
-rw-r--r--Library/Homebrew/vendor/macho/macho/utils.rb35
12 files changed, 2177 insertions, 2076 deletions
diff --git a/Library/Homebrew/vendor/README.md b/Library/Homebrew/vendor/README.md
index f998d26c5..906d42918 100644
--- a/Library/Homebrew/vendor/README.md
+++ b/Library/Homebrew/vendor/README.md
@@ -3,7 +3,7 @@ Vendored Dependencies
* [plist](https://github.com/bleything/plist), version 3.1.0
-* [ruby-macho](https://github.com/Homebrew/ruby-macho), version 0.2.6
+* [ruby-macho](https://github.com/Homebrew/ruby-macho), version 1.1.0
## Licenses:
@@ -33,7 +33,7 @@ Vendored Dependencies
### ruby-macho
> The MIT License
-> Copyright (c) 2015, 2016 William Woodruff <william @ tuffbizz.com>
+> Copyright (c) 2015, 2016, 2017 William Woodruff <william @ tuffbizz.com>
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
diff --git a/Library/Homebrew/vendor/macho/macho.rb b/Library/Homebrew/vendor/macho/macho.rb
index de1d4ff43..b7f20ea19 100644
--- a/Library/Homebrew/vendor/macho/macho.rb
+++ b/Library/Homebrew/vendor/macho/macho.rb
@@ -5,7 +5,6 @@ require "#{File.dirname(__FILE__)}/macho/load_commands"
require "#{File.dirname(__FILE__)}/macho/sections"
require "#{File.dirname(__FILE__)}/macho/macho_file"
require "#{File.dirname(__FILE__)}/macho/fat_file"
-require "#{File.dirname(__FILE__)}/macho/open"
require "#{File.dirname(__FILE__)}/macho/exceptions"
require "#{File.dirname(__FILE__)}/macho/utils"
require "#{File.dirname(__FILE__)}/macho/tools"
@@ -13,5 +12,29 @@ require "#{File.dirname(__FILE__)}/macho/tools"
# The primary namespace for ruby-macho.
module MachO
# release version
- VERSION = "0.2.6".freeze
+ VERSION = "1.1.0".freeze
+
+ # Opens the given filename as a MachOFile or FatFile, depending on its magic.
+ # @param filename [String] the file being opened
+ # @return [MachOFile] if the file is a Mach-O
+ # @return [FatFile] if the file is a Fat file
+ # @raise [ArgumentError] if the given file does not exist
+ # @raise [TruncatedFileError] if the file is too small to have a valid header
+ # @raise [MagicError] if the file's magic is not valid Mach-O magic
+ def self.open(filename)
+ raise ArgumentError, "#{filename}: no such file" unless File.file?(filename)
+ raise TruncatedFileError unless File.stat(filename).size >= 4
+
+ magic = File.open(filename, "rb") { |f| f.read(4) }.unpack("N").first
+
+ if Utils.fat_magic?(magic)
+ file = FatFile.new(filename)
+ elsif Utils.magic?(magic)
+ file = MachOFile.new(filename)
+ else
+ raise MagicError, magic
+ end
+
+ file
+ end
end
diff --git a/Library/Homebrew/vendor/macho/macho/exceptions.rb b/Library/Homebrew/vendor/macho/macho/exceptions.rb
index 262c195a3..14c2c22ae 100644
--- a/Library/Homebrew/vendor/macho/macho/exceptions.rb
+++ b/Library/Homebrew/vendor/macho/macho/exceptions.rb
@@ -80,7 +80,8 @@ module MachO
# @param cputype [Fixnum] the CPU type of the unknown pair
# @param cpusubtype [Fixnum] the CPU sub-type of the unknown pair
def initialize(cputype, cpusubtype)
- super "Unrecognized CPU sub-type: 0x#{"%08x" % cpusubtype} (for CPU type: 0x#{"%08x" % cputype})"
+ super "Unrecognized CPU sub-type: 0x#{"%08x" % cpusubtype}" \
+ " (for CPU type: 0x#{"%08x" % cputype})"
end
end
@@ -108,13 +109,15 @@ module MachO
end
end
- # Raised when the number of arguments used to create a load command manually is wrong.
+ # Raised when the number of arguments used to create a load command manually
+ # is wrong.
class LoadCommandCreationArityError < MachOError
# @param cmd_sym [Symbol] the load command's symbol
# @param expected_arity [Fixnum] the number of arguments expected
# @param actual_arity [Fixnum] the number of arguments received
def initialize(cmd_sym, expected_arity, actual_arity)
- super "Expected #{expected_arity} arguments for #{cmd_sym} creation, got #{actual_arity}"
+ super "Expected #{expected_arity} arguments for #{cmd_sym} creation," \
+ " got #{actual_arity}"
end
end
@@ -130,7 +133,8 @@ module MachO
class LCStrMalformedError < MachOError
# @param lc [MachO::LoadCommand] the load command containing the string
def initialize(lc)
- super "Load command #{lc.type} at offset #{lc.view.offset} contains a malformed string"
+ super "Load command #{lc.type} at offset #{lc.view.offset} contains a" \
+ " malformed string"
end
end
diff --git a/Library/Homebrew/vendor/macho/macho/fat_file.rb b/Library/Homebrew/vendor/macho/macho/fat_file.rb
index 9f29922e6..351be5ac6 100644
--- a/Library/Homebrew/vendor/macho/macho/fat_file.rb
+++ b/Library/Homebrew/vendor/macho/macho/fat_file.rb
@@ -1,24 +1,50 @@
+require "forwardable"
+
module MachO
# Represents a "Fat" file, which contains a header, a listing of available
# architectures, and one or more Mach-O binaries.
# @see https://en.wikipedia.org/wiki/Mach-O#Multi-architecture_binaries
- # @see MachO::MachOFile
+ # @see MachOFile
class FatFile
+ extend Forwardable
+
# @return [String] the filename loaded from, or nil if loaded from a binary string
attr_accessor :filename
- # @return [MachO::FatHeader] the file's header
+ # @return [Headers::FatHeader] the file's header
attr_reader :header
- # @return [Array<MachO::FatArch>] an array of fat architectures
+ # @return [Array<Headers::FatArch>] an array of fat architectures
attr_reader :fat_archs
- # @return [Array<MachO::MachOFile>] an array of Mach-O binaries
+ # @return [Array<MachOFile>] an array of Mach-O binaries
attr_reader :machos
+ # Creates a new FatFile from the given (single-arch) Mach-Os
+ # @param machos [Array<MachOFile>] the machos to combine
+ # @return [FatFile] a new FatFile containing the give machos
+ def self.new_from_machos(*machos)
+ header = Headers::FatHeader.new(Headers::FAT_MAGIC, machos.size)
+ offset = Headers::FatHeader.bytesize + (machos.size * Headers::FatArch.bytesize)
+ fat_archs = []
+ machos.each do |macho|
+ fat_archs << Headers::FatArch.new(macho.header.cputype,
+ macho.header.cpusubtype,
+ offset, macho.serialize.bytesize,
+ macho.alignment)
+ offset += macho.serialize.bytesize
+ end
+
+ bin = header.serialize
+ bin << fat_archs.map(&:serialize).join
+ bin << machos.map(&:serialize).join
+
+ new_from_bin(bin)
+ end
+
# Creates a new FatFile instance from a binary string.
# @param bin [String] a binary string containing raw Mach-O data
- # @return [MachO::FatFile] a new FatFile
+ # @return [FatFile] a new FatFile
def self.new_from_bin(bin)
instance = allocate
instance.initialize_from_bin(bin)
@@ -38,7 +64,7 @@ module MachO
end
# Initializes a new FatFile instance from a binary string.
- # @see MachO::FatFile.new_from_bin
+ # @see new_from_bin
# @api private
def initialize_from_bin(bin)
@filename = nil
@@ -52,70 +78,41 @@ module MachO
@raw_data
end
- # @return [Boolean] true if the file is of type `MH_OBJECT`, false otherwise
- def object?
- machos.first.object?
- end
-
- # @return [Boolean] true if the file is of type `MH_EXECUTE`, false otherwise
- def executable?
- machos.first.executable?
- end
-
- # @return [Boolean] true if the file is of type `MH_FVMLIB`, false otherwise
- def fvmlib?
- machos.first.fvmlib?
- end
-
- # @return [Boolean] true if the file is of type `MH_CORE`, false otherwise
- def core?
- machos.first.core?
- end
-
- # @return [Boolean] true if the file is of type `MH_PRELOAD`, false otherwise
- def preload?
- machos.first.preload?
- end
-
- # @return [Boolean] true if the file is of type `MH_DYLIB`, false otherwise
- def dylib?
- machos.first.dylib?
- end
-
- # @return [Boolean] true if the file is of type `MH_DYLINKER`, false otherwise
- def dylinker?
- machos.first.dylinker?
- end
-
- # @return [Boolean] true if the file is of type `MH_BUNDLE`, false otherwise
- def bundle?
- machos.first.bundle?
- end
-
- # @return [Boolean] true if the file is of type `MH_DSYM`, false otherwise
- def dsym?
- machos.first.dsym?
- end
-
- # @return [Boolean] true if the file is of type `MH_KEXT_BUNDLE`, false otherwise
- def kext?
- machos.first.kext?
- end
-
- # @return [Fixnum] the file's magic number
- def magic
- header.magic
- end
+ # @!method object?
+ # @return (see MachO::MachOFile#object?)
+ # @!method executable?
+ # @return (see MachO::MachOFile#executable?)
+ # @!method fvmlib?
+ # @return (see MachO::MachOFile#fvmlib?)
+ # @!method core?
+ # @return (see MachO::MachOFile#core?)
+ # @!method preload?
+ # @return (see MachO::MachOFile#preload?)
+ # @!method dylib?
+ # @return (see MachO::MachOFile#dylib?)
+ # @!method dylinker?
+ # @return (see MachO::MachOFile#dylinker?)
+ # @!method bundle?
+ # @return (see MachO::MachOFile#bundle?)
+ # @!method dsym?
+ # @return (see MachO::MachOFile#dsym?)
+ # @!method kext?
+ # @return (see MachO::MachOFile#kext?)
+ # @!method filetype
+ # @return (see MachO::MachOFile#filetype)
+ # @!method dylib_id
+ # @return (see MachO::MachOFile#dylib_id)
+ def_delegators :canonical_macho, :object?, :executable?, :fvmlib?,
+ :core?, :preload?, :dylib?, :dylinker?, :bundle?,
+ :dsym?, :kext?, :filetype, :dylib_id
+
+ # @!method magic
+ # @return (see MachO::Headers::FatHeader#magic)
+ def_delegators :header, :magic
# @return [String] a string representation of the file's magic number
def magic_string
- MH_MAGICS[magic]
- end
-
- # The file's type. Assumed to be the same for every Mach-O within.
- # @return [Symbol] the filetype
- def filetype
- machos.first.filetype
+ Headers::MH_MAGICS[magic]
end
# Populate the instance's fields with the raw Fat Mach-O data.
@@ -128,21 +125,13 @@ module MachO
end
# All load commands responsible for loading dylibs in the file's Mach-O's.
- # @return [Array<MachO::DylibCommand>] an array of DylibCommands
+ # @return [Array<LoadCommands::DylibCommand>] an array of DylibCommands
def dylib_load_commands
machos.map(&:dylib_load_commands).flatten
end
- # The file's dylib ID. If the file is not a dylib, returns `nil`.
- # @example
- # file.dylib_id # => 'libBar.dylib'
- # @return [String, nil] the file's dylib ID
- # @see MachO::MachOFile#linked_dylibs
- def dylib_id
- machos.first.dylib_id
- end
-
- # Changes the file's dylib ID to `new_id`. If the file is not a dylib, does nothing.
+ # Changes the file's dylib ID to `new_id`. If the file is not a dylib,
+ # does nothing.
# @example
# file.change_dylib_id('libFoo.dylib')
# @param new_id [String] the new dylib ID
@@ -151,7 +140,7 @@ module MachO
# if false, fail only if all slices fail.
# @return [void]
# @raise [ArgumentError] if `new_id` is not a String
- # @see MachO::MachOFile#linked_dylibs
+ # @see MachOFile#linked_dylibs
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?)
@@ -167,7 +156,7 @@ module MachO
# All shared libraries linked to the file's Mach-Os.
# @return [Array<String>] an array of all shared libraries
- # @see MachO::MachOFile#linked_dylibs
+ # @see MachOFile#linked_dylibs
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.
@@ -175,8 +164,9 @@ module MachO
machos.map(&:linked_dylibs).flatten.uniq
end
- # 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.
+ # 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.
# @example
# file.change_install_name('/usr/lib/libFoo.dylib', '/usr/lib/libBar.dylib')
# @param old_name [String] the shared library name being changed
@@ -185,7 +175,7 @@ module MachO
# @option options [Boolean] :strict (true) if true, fail if one slice fails.
# if false, fail only if all slices fail.
# @return [void]
- # @see MachO::MachOFile#change_install_name
+ # @see MachOFile#change_install_name
def change_install_name(old_name, new_name, options = {})
each_macho(options) do |macho|
macho.change_install_name(old_name, new_name, options)
@@ -198,7 +188,7 @@ module MachO
# All runtime paths associated with the file's Mach-Os.
# @return [Array<String>] an array of all runtime paths
- # @see MachO::MachOFile#rpaths
+ # @see MachOFile#rpaths
def rpaths
# Can individual architectures have different runtime paths?
machos.map(&:rpaths).flatten.uniq
@@ -211,7 +201,7 @@ module MachO
# @option options [Boolean] :strict (true) if true, fail if one slice fails.
# if false, fail only if all slices fail.
# @return [void]
- # @see MachO::MachOFile#change_rpath
+ # @see MachOFile#change_rpath
def change_rpath(old_path, new_path, options = {})
each_macho(options) do |macho|
macho.change_rpath(old_path, new_path, options)
@@ -226,7 +216,7 @@ module MachO
# @option options [Boolean] :strict (true) if true, fail if one slice fails.
# if false, fail only if all slices fail.
# @return [void]
- # @see MachO::MachOFile#add_rpath
+ # @see MachOFile#add_rpath
def add_rpath(path, options = {})
each_macho(options) do |macho|
macho.add_rpath(path, options)
@@ -241,7 +231,7 @@ module MachO
# @option options [Boolean] :strict (true) if true, fail if one slice fails.
# if false, fail only if all slices fail.
# @return void
- # @see MachO::MachOFile#delete_rpath
+ # @see MachOFile#delete_rpath
def delete_rpath(path, options = {})
each_macho(options) do |macho|
macho.delete_rpath(path, options)
@@ -254,20 +244,21 @@ module MachO
# @example
# file.extract(:i386) # => MachO::MachOFile
# @param cputype [Symbol] the CPU type of the Mach-O being extracted
- # @return [MachO::MachOFile, nil] the extracted Mach-O or nil if no Mach-O has the given CPU type
+ # @return [MachOFile, nil] the extracted Mach-O or nil if no Mach-O has the given CPU type
def extract(cputype)
machos.select { |macho| macho.cputype == cputype }.first
end
# Write all (fat) data to the given filename.
# @param filename [String] the file to write to
+ # @return [void]
def write(filename)
File.open(filename, "wb") { |f| f.write(@raw_data) }
end
# Write all (fat) data to the file used to initialize the instance.
# @return [void]
- # @raise [MachO::MachOError] if the instance was initialized without a file
+ # @raise [MachOError] if the instance was initialized without a file
# @note Overwrites all data in the file!
def write!
if filename.nil?
@@ -280,17 +271,18 @@ module MachO
private
# Obtain the fat header from raw file data.
- # @return [MachO::FatHeader] the fat header
- # @raise [MachO::TruncatedFileError] if the file is too small to have a valid header
- # @raise [MachO::MagicError] if the magic is not valid Mach-O magic
- # @raise [MachO::MachOBinaryError] if the magic is for a non-fat Mach-O file
- # @raise [MachO::JavaClassFileError] if the file is a Java classfile
+ # @return [Headers::FatHeader] the fat header
+ # @raise [TruncatedFileError] if the file is too small to have a
+ # valid header
+ # @raise [MagicError] if the magic is not valid Mach-O magic
+ # @raise [MachOBinaryError] if the magic is for a non-fat Mach-O file
+ # @raise [JavaClassFileError] if the file is a Java classfile
# @api private
def populate_fat_header
# the smallest fat Mach-O header is 8 bytes
raise TruncatedFileError if @raw_data.size < 8
- fh = FatHeader.new_from_bin(:big, @raw_data[0, FatHeader.bytesize])
+ fh = Headers::FatHeader.new_from_bin(:big, @raw_data[0, Headers::FatHeader.bytesize])
raise MagicError, fh.magic unless Utils.magic?(fh.magic)
raise MachOBinaryError unless Utils.fat_magic?(fh.magic)
@@ -308,22 +300,22 @@ module MachO
end
# Obtain an array of fat architectures from raw file data.
- # @return [Array<MachO::FatArch>] an array of fat architectures
+ # @return [Array<Headers::FatArch>] an array of fat architectures
# @api private
def populate_fat_archs
archs = []
- fa_off = FatHeader.bytesize
- fa_len = FatArch.bytesize
+ fa_off = Headers::FatHeader.bytesize
+ fa_len = Headers::FatArch.bytesize
header.nfat_arch.times do |i|
- archs << FatArch.new_from_bin(:big, @raw_data[fa_off + (fa_len * i), fa_len])
+ archs << Headers::FatArch.new_from_bin(:big, @raw_data[fa_off + (fa_len * i), fa_len])
end
archs
end
# Obtain an array of Mach-O blobs from raw file data.
- # @return [Array<MachO::MachOFile>] an array of Mach-Os
+ # @return [Array<MachOFile>] an array of Mach-Os
# @api private
def populate_machos
machos = []
@@ -351,7 +343,7 @@ module MachO
# @option options [Boolean] :strict (true) whether or not to fail loudly
# with an exception if at least one Mach-O raises an exception. If false,
# only raises an exception if *all* Mach-Os raise exceptions.
- # @raise [MachO::RecoverableModificationError] under the conditions of
+ # @raise [RecoverableModificationError] under the conditions of
# the `:strict` option above.
# @api private
def each_macho(options = {})
@@ -373,5 +365,13 @@ module MachO
# Non-strict mode: Raise first error if *all* Mach-O slices failed.
raise errors.first if errors.size == machos.size
end
+
+ # Return a single-arch Mach-O that represents this fat Mach-O for purposes
+ # of delegation.
+ # @return [MachOFile] the Mach-O file
+ # @api private
+ def canonical_macho
+ machos.first
+ end
end
end
diff --git a/Library/Homebrew/vendor/macho/macho/headers.rb b/Library/Homebrew/vendor/macho/macho/headers.rb
index 7272503af..08a4b80c4 100644
--- a/Library/Homebrew/vendor/macho/macho/headers.rb
+++ b/Library/Homebrew/vendor/macho/macho/headers.rb
@@ -1,587 +1,665 @@
module MachO
- # big-endian fat magic
- # @api private
- FAT_MAGIC = 0xcafebabe
-
- # little-endian fat magic
- # this is defined, but should never appear in ruby-macho code because
- # fat headers are always big-endian and therefore always unpacked as such.
- # @api private
- FAT_CIGAM = 0xbebafeca
-
- # 32-bit big-endian magic
- # @api private
- MH_MAGIC = 0xfeedface
-
- # 32-bit little-endian magic
- # @api private
- MH_CIGAM = 0xcefaedfe
-
- # 64-bit big-endian magic
- # @api private
- MH_MAGIC_64 = 0xfeedfacf
-
- # 64-bit little-endian magic
- # @api private
- MH_CIGAM_64 = 0xcffaedfe
-
- # association of magic numbers to string representations
- # @api private
- MH_MAGICS = {
- FAT_MAGIC => "FAT_MAGIC",
- MH_MAGIC => "MH_MAGIC",
- MH_CIGAM => "MH_CIGAM",
- MH_MAGIC_64 => "MH_MAGIC_64",
- MH_CIGAM_64 => "MH_CIGAM_64",
- }.freeze
-
- # mask for CPUs with 64-bit architectures (when running a 64-bit ABI?)
- # @api private
- CPU_ARCH_ABI64 = 0x01000000
-
- # any CPU (unused?)
- # @api private
- CPU_TYPE_ANY = -1
-
- # m68k compatible CPUs
- # @api private
- CPU_TYPE_MC680X0 = 0x06
-
- # i386 and later compatible CPUs
- # @api private
- CPU_TYPE_I386 = 0x07
-
- # x86_64 (AMD64) compatible CPUs
- # @api private
- CPU_TYPE_X86_64 = (CPU_TYPE_I386 | CPU_ARCH_ABI64)
-
- # 32-bit ARM compatible CPUs
- # @api private
- CPU_TYPE_ARM = 0x0c
-
- # m88k compatible CPUs
- # @api private
- CPU_TYPE_MC88000 = 0xd
-
- # 64-bit ARM compatible CPUs
- # @api private
- CPU_TYPE_ARM64 = (CPU_TYPE_ARM | CPU_ARCH_ABI64)
-
- # PowerPC compatible CPUs
- # @api private
- CPU_TYPE_POWERPC = 0x12
-
- # PowerPC64 compatible CPUs
- # @api private
- CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
-
- # association of cpu types to symbol representations
- # @api private
- CPU_TYPES = {
- CPU_TYPE_ANY => :any,
- CPU_TYPE_I386 => :i386,
- CPU_TYPE_X86_64 => :x86_64,
- CPU_TYPE_ARM => :arm,
- CPU_TYPE_ARM64 => :arm64,
- CPU_TYPE_POWERPC => :ppc,
- CPU_TYPE_POWERPC64 => :ppc64,
- }.freeze
-
- # mask for CPU subtype capabilities
- # @api private
- CPU_SUBTYPE_MASK = 0xff000000
-
- # 64-bit libraries (undocumented!)
- # @see http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
- # @api private
- CPU_SUBTYPE_LIB64 = 0x80000000
-
- # the lowest common sub-type for `CPU_TYPE_I386`
- # @api private
- CPU_SUBTYPE_I386 = 3
-
- # the i486 sub-type for `CPU_TYPE_I386`
- # @api private
- CPU_SUBTYPE_486 = 4
-
- # the i486SX sub-type for `CPU_TYPE_I386`
- # @api private
- CPU_SUBTYPE_486SX = 132
-
- # the i586 (P5, Pentium) sub-type for `CPU_TYPE_I386`
- # @api private
- CPU_SUBTYPE_586 = 5
-
- # @see CPU_SUBTYPE_586
- # @api private
- CPU_SUBTYPE_PENT = CPU_SUBTYPE_586
-
- # the Pentium Pro (P6) sub-type for `CPU_TYPE_I386`
- # @api private
- CPU_SUBTYPE_PENTPRO = 22
-
- # the Pentium II (P6, M3?) sub-type for `CPU_TYPE_I386`
- # @api private
- CPU_SUBTYPE_PENTII_M3 = 54
-
- # the Pentium II (P6, M5?) sub-type for `CPU_TYPE_I386`
- # @api private
- CPU_SUBTYPE_PENTII_M5 = 86
-
- # the Pentium 4 (Netburst) sub-type for `CPU_TYPE_I386`
- # @api private
- CPU_SUBTYPE_PENTIUM_4 = 10
-
- # the lowest common sub-type for `CPU_TYPE_MC680X0`
- # @api private
- CPU_SUBTYPE_MC680X0_ALL = 1
-
- # @see CPU_SUBTYPE_MC680X0_ALL
- # @api private
- CPU_SUBTYPE_MC68030 = CPU_SUBTYPE_MC680X0_ALL
-
- # the 040 subtype for `CPU_TYPE_MC680X0`
- # @api private
- CPU_SUBTYPE_MC68040 = 2
-
- # the 030 subtype for `CPU_TYPE_MC680X0`
- # @api private
- CPU_SUBTYPE_MC68030_ONLY = 3
-
- # the lowest common sub-type for `CPU_TYPE_X86_64`
- # @api private
- CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_I386
-
- # the Haskell sub-type for `CPU_TYPE_X86_64`
- # @api private
- CPU_SUBTYPE_X86_64_H = 8
-
- # the lowest common sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_ALL = 0
-
- # the v4t sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V4T = 5
-
- # the v6 sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V6 = 6
-
- # the v5 sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V5TEJ = 7
-
- # the xscale (v5 family) sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_XSCALE = 8
-
- # the v7 sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V7 = 9
-
- # the v7f (Cortex A9) sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V7F = 10
+ # Classes and constants for parsing the headers of Mach-O binaries.
+ module Headers
+ # big-endian fat magic
+ # @api private
+ FAT_MAGIC = 0xcafebabe
- # the v7s ("Swift") sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V7S = 11
+ # little-endian fat magic
+ # this is defined, but should never appear in ruby-macho code because
+ # fat headers are always big-endian and therefore always unpacked as such.
+ # @api private
+ FAT_CIGAM = 0xbebafeca
- # the v7k ("Kirkwood40") sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V7K = 12
-
- # the v6m sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V6M = 14
-
- # the v7m sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V7M = 15
-
- # the v7em sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V7EM = 16
-
- # the v8 sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V8 = 13
-
- # the lowest common sub-type for `CPU_TYPE_ARM64`
- # @api private
- CPU_SUBTYPE_ARM64_ALL = 0
-
- # the v8 sub-type for `CPU_TYPE_ARM64`
- # @api private
- CPU_SUBTYPE_ARM64_V8 = 1
-
- # the lowest common sub-type for `CPU_TYPE_MC88000`
- # @api private
- CPU_SUBTYPE_MC88000_ALL = 0
-
- # @see CPU_SUBTYPE_MC88000_ALL
- # @api private
- CPU_SUBTYPE_MMAX_JPC = CPU_SUBTYPE_MC88000_ALL
-
- # the 100 sub-type for `CPU_TYPE_MC88000`
- # @api private
- CPU_SUBTYPE_MC88100 = 1
-
- # the 110 sub-type for `CPU_TYPE_MC88000`
- # @api private
- CPU_SUBTYPE_MC88110 = 2
-
- # the lowest common sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_ALL = 0
-
- # the 601 sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_601 = 1
-
- # the 602 sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_602 = 2
-
- # the 603 sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_603 = 3
-
- # the 603e (G2) sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_603E = 4
-
- # the 603ev sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_603EV = 5
-
- # the 604 sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_604 = 6
-
- # the 604e sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_604E = 7
-
- # the 620 sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_620 = 8
-
- # the 750 (G3) sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_750 = 9
-
- # the 7400 (G4) sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_7400 = 10
-
- # the 7450 (G4 "Voyager") sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_7450 = 11
-
- # the 970 (G5) sub-type for `CPU_TYPE_POWERPC`
- # @api private
- CPU_SUBTYPE_POWERPC_970 = 100
-
- # any CPU sub-type for CPU type `CPU_TYPE_POWERPC64`
- # @api private
- CPU_SUBTYPE_POWERPC64_ALL = CPU_SUBTYPE_POWERPC_ALL
-
- # association of CPU types/subtype pairs to symbol representations in
- # (very) roughly descending order of commonness
- # @see https://opensource.apple.com/source/cctools/cctools-877.8/libstuff/arch.c
- # @api private
- CPU_SUBTYPES = {
- CPU_TYPE_I386 => {
- CPU_SUBTYPE_I386 => :i386,
- CPU_SUBTYPE_486 => :i486,
- CPU_SUBTYPE_486SX => :i486SX,
- CPU_SUBTYPE_586 => :i586, # also "pentium" in arch(3)
- CPU_SUBTYPE_PENTPRO => :i686, # also "pentpro" in arch(3)
- CPU_SUBTYPE_PENTII_M3 => :pentIIm3,
- CPU_SUBTYPE_PENTII_M5 => :pentIIm5,
- CPU_SUBTYPE_PENTIUM_4 => :pentium4,
- }.freeze,
- CPU_TYPE_X86_64 => {
- CPU_SUBTYPE_X86_64_ALL => :x86_64,
- CPU_SUBTYPE_X86_64_H => :x86_64h,
- }.freeze,
- CPU_TYPE_ARM => {
- CPU_SUBTYPE_ARM_ALL => :arm,
- CPU_SUBTYPE_ARM_V4T => :armv4t,
- CPU_SUBTYPE_ARM_V6 => :armv6,
- CPU_SUBTYPE_ARM_V5TEJ => :armv5,
- CPU_SUBTYPE_ARM_XSCALE => :xscale,
- CPU_SUBTYPE_ARM_V7 => :armv7,
- CPU_SUBTYPE_ARM_V7F => :armv7f,
- CPU_SUBTYPE_ARM_V7S => :armv7s,
- CPU_SUBTYPE_ARM_V7K => :armv7k,
- CPU_SUBTYPE_ARM_V6M => :armv6m,
- CPU_SUBTYPE_ARM_V7M => :armv7m,
- CPU_SUBTYPE_ARM_V7EM => :armv7em,
- CPU_SUBTYPE_ARM_V8 => :armv8,
- }.freeze,
- CPU_TYPE_ARM64 => {
- CPU_SUBTYPE_ARM64_ALL => :arm64,
- CPU_SUBTYPE_ARM64_V8 => :arm64v8,
- }.freeze,
- CPU_TYPE_POWERPC => {
- CPU_SUBTYPE_POWERPC_ALL => :ppc,
- CPU_SUBTYPE_POWERPC_601 => :ppc601,
- CPU_SUBTYPE_POWERPC_603 => :ppc603,
- CPU_SUBTYPE_POWERPC_603E => :ppc603e,
- CPU_SUBTYPE_POWERPC_603EV => :ppc603ev,
- CPU_SUBTYPE_POWERPC_604 => :ppc604,
- CPU_SUBTYPE_POWERPC_604E => :ppc604e,
- CPU_SUBTYPE_POWERPC_750 => :ppc750,
- CPU_SUBTYPE_POWERPC_7400 => :ppc7400,
- CPU_SUBTYPE_POWERPC_7450 => :ppc7450,
- CPU_SUBTYPE_POWERPC_970 => :ppc970,
- }.freeze,
- CPU_TYPE_POWERPC64 => {
- CPU_SUBTYPE_POWERPC64_ALL => :ppc64,
- # apparently the only exception to the naming scheme
- CPU_SUBTYPE_POWERPC_970 => :ppc970_64,
- }.freeze,
- CPU_TYPE_MC680X0 => {
- CPU_SUBTYPE_MC680X0_ALL => :m68k,
- CPU_SUBTYPE_MC68030 => :mc68030,
- CPU_SUBTYPE_MC68040 => :mc68040,
- },
- CPU_TYPE_MC88000 => {
- CPU_SUBTYPE_MC88000_ALL => :m88k,
- },
- }.freeze
-
- # relocatable object file
- # @api private
- MH_OBJECT = 0x1
-
- # demand paged executable file
- # @api private
- MH_EXECUTE = 0x2
-
- # fixed VM shared library file
- # @api private
- MH_FVMLIB = 0x3
-
- # core dump file
- # @api private
- MH_CORE = 0x4
-
- # preloaded executable file
- # @api private
- MH_PRELOAD = 0x5
-
- # dynamically bound shared library
- # @api private
- MH_DYLIB = 0x6
-
- # dynamic link editor
- # @api private
- MH_DYLINKER = 0x7
-
- # dynamically bound bundle file
- # @api private
- MH_BUNDLE = 0x8
-
- # shared library stub for static linking only, no section contents
- # @api private
- MH_DYLIB_STUB = 0x9
-
- # companion file with only debug sections
- # @api private
- MH_DSYM = 0xa
-
- # x86_64 kexts
- # @api private
- MH_KEXT_BUNDLE = 0xb
-
- # association of filetypes to Symbol representations
- # @api private
- MH_FILETYPES = {
- MH_OBJECT => :object,
- MH_EXECUTE => :execute,
- MH_FVMLIB => :fvmlib,
- MH_CORE => :core,
- MH_PRELOAD => :preload,
- MH_DYLIB => :dylib,
- MH_DYLINKER => :dylinker,
- MH_BUNDLE => :bundle,
- MH_DYLIB_STUB => :dylib_stub,
- MH_DSYM => :dsym,
- MH_KEXT_BUNDLE => :kext_bundle,
- }.freeze
-
- # association of mach header flag symbols to values
- # @api private
- MH_FLAGS = {
- :MH_NOUNDEFS => 0x1,
- :MH_INCRLINK => 0x2,
- :MH_DYLDLINK => 0x4,
- :MH_BINDATLOAD => 0x8,
- :MH_PREBOUND => 0x10,
- :MH_SPLIT_SEGS => 0x20,
- :MH_LAZY_INIT => 0x40,
- :MH_TWOLEVEL => 0x80,
- :MH_FORCE_FLAT => 0x100,
- :MH_NOMULTIDEFS => 0x200,
- :MH_NOPREFIXBINDING => 0x400,
- :MH_PREBINDABLE => 0x800,
- :MH_ALLMODSBOUND => 0x1000,
- :MH_SUBSECTIONS_VIA_SYMBOLS => 0x2000,
- :MH_CANONICAL => 0x4000,
- :MH_WEAK_DEFINES => 0x8000,
- :MH_BINDS_TO_WEAK => 0x10000,
- :MH_ALLOW_STACK_EXECUTION => 0x20000,
- :MH_ROOT_SAFE => 0x40000,
- :MH_SETUID_SAFE => 0x80000,
- :MH_NO_REEXPORTED_DYLIBS => 0x100000,
- :MH_PIE => 0x200000,
- :MH_DEAD_STRIPPABLE_DYLIB => 0x400000,
- :MH_HAS_TLV_DESCRIPTORS => 0x800000,
- :MH_NO_HEAP_EXECUTION => 0x1000000,
- :MH_APP_EXTENSION_SAFE => 0x02000000,
- }.freeze
-
- # Fat binary header structure
- # @see MachO::FatArch
- class FatHeader < MachOStructure
- # @return [Fixnum] the magic number of the header (and file)
- attr_reader :magic
-
- # @return [Fixnum] the number of fat architecture structures following the header
- attr_reader :nfat_arch
-
- # always big-endian
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "N2".freeze
-
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 8
-
- # @api private
- def initialize(magic, nfat_arch)
- @magic = magic
- @nfat_arch = nfat_arch
- end
- end
+ # 32-bit big-endian magic
+ # @api private
+ MH_MAGIC = 0xfeedface
- # Fat binary header architecture structure. A Fat binary has one or more of
- # these, representing one or more internal Mach-O blobs.
- # @see MachO::FatHeader
- class FatArch < MachOStructure
- # @return [Fixnum] the CPU type of the Mach-O
- attr_reader :cputype
+ # 32-bit little-endian magic
+ # @api private
+ MH_CIGAM = 0xcefaedfe
- # @return [Fixnum] the CPU subtype of the Mach-O
- attr_reader :cpusubtype
+ # 64-bit big-endian magic
+ # @api private
+ MH_MAGIC_64 = 0xfeedfacf
- # @return [Fixnum] the file offset to the beginning of the Mach-O data
- attr_reader :offset
+ # 64-bit little-endian magic
+ # @api private
+ MH_CIGAM_64 = 0xcffaedfe
- # @return [Fixnum] the size, in bytes, of the Mach-O data
- attr_reader :size
+ # association of magic numbers to string representations
+ # @api private
+ MH_MAGICS = {
+ FAT_MAGIC => "FAT_MAGIC",
+ MH_MAGIC => "MH_MAGIC",
+ MH_CIGAM => "MH_CIGAM",
+ MH_MAGIC_64 => "MH_MAGIC_64",
+ MH_CIGAM_64 => "MH_CIGAM_64",
+ }.freeze
+
+ # mask for CPUs with 64-bit architectures (when running a 64-bit ABI?)
+ # @api private
+ CPU_ARCH_ABI64 = 0x01000000
- # @return [Fixnum] the alignment, as a power of 2
- attr_reader :align
+ # any CPU (unused?)
+ # @api private
+ CPU_TYPE_ANY = -1
- # always big-endian
- # @see MachOStructure::FORMAT
+ # m68k compatible CPUs
# @api private
- FORMAT = "N5".freeze
+ CPU_TYPE_MC680X0 = 0x06
- # @see MachOStructure::SIZEOF
+ # i386 and later compatible CPUs
# @api private
- SIZEOF = 20
+ CPU_TYPE_I386 = 0x07
+ # x86_64 (AMD64) compatible CPUs
# @api private
- def initialize(cputype, cpusubtype, offset, size, align)
- @cputype = cputype
- @cpusubtype = cpusubtype
- @offset = offset
- @size = size
- @align = align
- end
- end
+ CPU_TYPE_X86_64 = (CPU_TYPE_I386 | CPU_ARCH_ABI64)
- # 32-bit Mach-O file header structure
- class MachHeader < MachOStructure
- # @return [Fixnum] the magic number
- attr_reader :magic
+ # 32-bit ARM compatible CPUs
+ # @api private
+ CPU_TYPE_ARM = 0x0c
- # @return [Fixnum] the CPU type of the Mach-O
- attr_reader :cputype
+ # m88k compatible CPUs
+ # @api private
+ CPU_TYPE_MC88000 = 0xd
- # @return [Fixnum] the CPU subtype of the Mach-O
- attr_reader :cpusubtype
+ # 64-bit ARM compatible CPUs
+ # @api private
+ CPU_TYPE_ARM64 = (CPU_TYPE_ARM | CPU_ARCH_ABI64)
- # @return [Fixnum] the file type of the Mach-O
- attr_reader :filetype
+ # PowerPC compatible CPUs
+ # @api private
+ CPU_TYPE_POWERPC = 0x12
- # @return [Fixnum] the number of load commands in the Mach-O
- attr_reader :ncmds
+ # PowerPC64 compatible CPUs
+ # @api private
+ CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
- # @return [Fixnum] the size of all load commands, in bytes, in the Mach-O
- attr_reader :sizeofcmds
+ # association of cpu types to symbol representations
+ # @api private
+ CPU_TYPES = {
+ CPU_TYPE_ANY => :any,
+ CPU_TYPE_I386 => :i386,
+ CPU_TYPE_X86_64 => :x86_64,
+ CPU_TYPE_ARM => :arm,
+ CPU_TYPE_ARM64 => :arm64,
+ CPU_TYPE_POWERPC => :ppc,
+ CPU_TYPE_POWERPC64 => :ppc64,
+ }.freeze
+
+ # mask for CPU subtype capabilities
+ # @api private
+ CPU_SUBTYPE_MASK = 0xff000000
- # @return [Fixnum] the header flags associated with the Mach-O
- attr_reader :flags
+ # 64-bit libraries (undocumented!)
+ # @see http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
+ # @api private
+ CPU_SUBTYPE_LIB64 = 0x80000000
- # @see MachOStructure::FORMAT
+ # the lowest common sub-type for `CPU_TYPE_I386`
# @api private
- FORMAT = "L=7".freeze
+ CPU_SUBTYPE_I386 = 3
- # @see MachOStructure::SIZEOF
+ # the i486 sub-type for `CPU_TYPE_I386`
# @api private
- SIZEOF = 28
+ CPU_SUBTYPE_486 = 4
+ # the i486SX sub-type for `CPU_TYPE_I386`
# @api private
- def initialize(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds,
- flags)
- @magic = magic
- @cputype = cputype
- # For now we're not interested in additional capability bits also to be
- # found in the `cpusubtype` field. We only care about the CPU sub-type.
- @cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK
- @filetype = filetype
- @ncmds = ncmds
- @sizeofcmds = sizeofcmds
- @flags = flags
- end
+ CPU_SUBTYPE_486SX = 132
- # @example
- # puts "this mach-o has position-independent execution" if header.flag?(:MH_PIE)
- # @param flag [Symbol] a mach header flag symbol
- # @return [Boolean] true if `flag` is present in the header's flag section
- def flag?(flag)
- flag = MH_FLAGS[flag]
- return false if flag.nil?
- flags & flag == flag
- end
- end
+ # the i586 (P5, Pentium) sub-type for `CPU_TYPE_I386`
+ # @api private
+ CPU_SUBTYPE_586 = 5
+
+ # @see CPU_SUBTYPE_586
+ # @api private
+ CPU_SUBTYPE_PENT = CPU_SUBTYPE_586
+
+ # the Pentium Pro (P6) sub-type for `CPU_TYPE_I386`
+ # @api private
+ CPU_SUBTYPE_PENTPRO = 22
+
+ # the Pentium II (P6, M3?) sub-type for `CPU_TYPE_I386`
+ # @api private
+ CPU_SUBTYPE_PENTII_M3 = 54
+
+ # the Pentium II (P6, M5?) sub-type for `CPU_TYPE_I386`
+ # @api private
+ CPU_SUBTYPE_PENTII_M5 = 86
+
+ # the Pentium 4 (Netburst) sub-type for `CPU_TYPE_I386`
+ # @api private
+ CPU_SUBTYPE_PENTIUM_4 = 10
+
+ # the lowest common sub-type for `CPU_TYPE_MC680X0`
+ # @api private
+ CPU_SUBTYPE_MC680X0_ALL = 1
+
+ # @see CPU_SUBTYPE_MC680X0_ALL
+ # @api private
+ CPU_SUBTYPE_MC68030 = CPU_SUBTYPE_MC680X0_ALL
+
+ # the 040 subtype for `CPU_TYPE_MC680X0`
+ # @api private
+ CPU_SUBTYPE_MC68040 = 2
+
+ # the 030 subtype for `CPU_TYPE_MC680X0`
+ # @api private
+ CPU_SUBTYPE_MC68030_ONLY = 3
+
+ # the lowest common sub-type for `CPU_TYPE_X86_64`
+ # @api private
+ CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_I386
+
+ # the Haskell sub-type for `CPU_TYPE_X86_64`
+ # @api private
+ CPU_SUBTYPE_X86_64_H = 8
+
+ # the lowest common sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_ALL = 0
+
+ # the v4t sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_V4T = 5
+
+ # the v6 sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_V6 = 6
+
+ # the v5 sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_V5TEJ = 7
+
+ # the xscale (v5 family) sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_XSCALE = 8
+
+ # the v7 sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_V7 = 9
+
+ # the v7f (Cortex A9) sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_V7F = 10
+
+ # the v7s ("Swift") sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_V7S = 11
+
+ # the v7k ("Kirkwood40") sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_V7K = 12
+
+ # the v6m sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_V6M = 14
+
+ # the v7m sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_V7M = 15
- # 64-bit Mach-O file header structure
- class MachHeader64 < MachHeader
- # @return [void]
- attr_reader :reserved
+ # the v7em sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_V7EM = 16
+
+ # the v8 sub-type for `CPU_TYPE_ARM`
+ # @api private
+ CPU_SUBTYPE_ARM_V8 = 13
+
+ # the lowest common sub-type for `CPU_TYPE_ARM64`
+ # @api private
+ CPU_SUBTYPE_ARM64_ALL = 0
+
+ # the v8 sub-type for `CPU_TYPE_ARM64`
+ # @api private
+ CPU_SUBTYPE_ARM64_V8 = 1
+
+ # the lowest common sub-type for `CPU_TYPE_MC88000`
+ # @api private
+ CPU_SUBTYPE_MC88000_ALL = 0
+
+ # @see CPU_SUBTYPE_MC88000_ALL
+ # @api private
+ CPU_SUBTYPE_MMAX_JPC = CPU_SUBTYPE_MC88000_ALL
+
+ # the 100 sub-type for `CPU_TYPE_MC88000`
+ # @api private
+ CPU_SUBTYPE_MC88100 = 1
+
+ # the 110 sub-type for `CPU_TYPE_MC88000`
+ # @api private
+ CPU_SUBTYPE_MC88110 = 2
+
+ # the lowest common sub-type for `CPU_TYPE_POWERPC`
+ # @api private
+ CPU_SUBTYPE_POWERPC_ALL = 0
+
+ # the 601 sub-type for `CPU_TYPE_POWERPC`
+ # @api private
+ CPU_SUBTYPE_POWERPC_601 = 1
+
+ # the 602 sub-type for `CPU_TYPE_POWERPC`
+ # @api private
+ CPU_SUBTYPE_POWERPC_602 = 2
+
+ # the 603 sub-type for `CPU_TYPE_POWERPC`
+ # @api private
+ CPU_SUBTYPE_POWERPC_603 = 3
+
+ # the 603e (G2) sub-type for `CPU_TYPE_POWERPC`
+ # @api private
+ CPU_SUBTYPE_POWERPC_603E = 4
+
+ # the 603ev sub-type for `CPU_TYPE_POWERPC`
+ # @api private
+ CPU_SUBTYPE_POWERPC_603EV = 5
+
+ # the 604 sub-type for `CPU_TYPE_POWERPC`
+ # @api private
+ CPU_SUBTYPE_POWERPC_604 = 6
+
+ # the 604e sub-type for `CPU_TYPE_POWERPC`
+ # @api private
+ CPU_SUBTYPE_POWERPC_604E = 7
+
+ # the 620 sub-type for `CPU_TYPE_POWERPC`
+ # @api private
+ CPU_SUBTYPE_POWERPC_620 = 8
+
+ # the 750 (G3) sub-type for `CPU_TYPE_POWERPC`
+ # @api private
+ CPU_SUBTYPE_POWERPC_750 = 9
- # @see MachOStructure::FORMAT
+ # the 7400 (G4) sub-type for `CPU_TYPE_POWERPC`
# @api private
- FORMAT = "L=8".freeze
+ CPU_SUBTYPE_POWERPC_7400 = 10
- # @see MachOStructure::SIZEOF
+ # the 7450 (G4 "Voyager") sub-type for `CPU_TYPE_POWERPC`
# @api private
- SIZEOF = 32
+ CPU_SUBTYPE_POWERPC_7450 = 11
+ # the 970 (G5) sub-type for `CPU_TYPE_POWERPC`
# @api private
- def initialize(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds,
- flags, reserved)
- super(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags)
- @reserved = reserved
+ CPU_SUBTYPE_POWERPC_970 = 100
+
+ # any CPU sub-type for CPU type `CPU_TYPE_POWERPC64`
+ # @api private
+ CPU_SUBTYPE_POWERPC64_ALL = CPU_SUBTYPE_POWERPC_ALL
+
+ # association of CPU types/subtype pairs to symbol representations in
+ # (very) roughly descending order of commonness
+ # @see https://opensource.apple.com/source/cctools/cctools-877.8/libstuff/arch.c
+ # @api private
+ CPU_SUBTYPES = {
+ CPU_TYPE_I386 => {
+ CPU_SUBTYPE_I386 => :i386,
+ CPU_SUBTYPE_486 => :i486,
+ CPU_SUBTYPE_486SX => :i486SX,
+ CPU_SUBTYPE_586 => :i586, # also "pentium" in arch(3)
+ CPU_SUBTYPE_PENTPRO => :i686, # also "pentpro" in arch(3)
+ CPU_SUBTYPE_PENTII_M3 => :pentIIm3,
+ CPU_SUBTYPE_PENTII_M5 => :pentIIm5,
+ CPU_SUBTYPE_PENTIUM_4 => :pentium4,
+ }.freeze,
+ CPU_TYPE_X86_64 => {
+ CPU_SUBTYPE_X86_64_ALL => :x86_64,
+ CPU_SUBTYPE_X86_64_H => :x86_64h,
+ }.freeze,
+ CPU_TYPE_ARM => {
+ CPU_SUBTYPE_ARM_ALL => :arm,
+ CPU_SUBTYPE_ARM_V4T => :armv4t,
+ CPU_SUBTYPE_ARM_V6 => :armv6,
+ CPU_SUBTYPE_ARM_V5TEJ => :armv5,
+ CPU_SUBTYPE_ARM_XSCALE => :xscale,
+ CPU_SUBTYPE_ARM_V7 => :armv7,
+ CPU_SUBTYPE_ARM_V7F => :armv7f,
+ CPU_SUBTYPE_ARM_V7S => :armv7s,
+ CPU_SUBTYPE_ARM_V7K => :armv7k,
+ CPU_SUBTYPE_ARM_V6M => :armv6m,
+ CPU_SUBTYPE_ARM_V7M => :armv7m,
+ CPU_SUBTYPE_ARM_V7EM => :armv7em,
+ CPU_SUBTYPE_ARM_V8 => :armv8,
+ }.freeze,
+ CPU_TYPE_ARM64 => {
+ CPU_SUBTYPE_ARM64_ALL => :arm64,
+ CPU_SUBTYPE_ARM64_V8 => :arm64v8,
+ }.freeze,
+ CPU_TYPE_POWERPC => {
+ CPU_SUBTYPE_POWERPC_ALL => :ppc,
+ CPU_SUBTYPE_POWERPC_601 => :ppc601,
+ CPU_SUBTYPE_POWERPC_603 => :ppc603,
+ CPU_SUBTYPE_POWERPC_603E => :ppc603e,
+ CPU_SUBTYPE_POWERPC_603EV => :ppc603ev,
+ CPU_SUBTYPE_POWERPC_604 => :ppc604,
+ CPU_SUBTYPE_POWERPC_604E => :ppc604e,
+ CPU_SUBTYPE_POWERPC_750 => :ppc750,
+ CPU_SUBTYPE_POWERPC_7400 => :ppc7400,
+ CPU_SUBTYPE_POWERPC_7450 => :ppc7450,
+ CPU_SUBTYPE_POWERPC_970 => :ppc970,
+ }.freeze,
+ CPU_TYPE_POWERPC64 => {
+ CPU_SUBTYPE_POWERPC64_ALL => :ppc64,
+ # apparently the only exception to the naming scheme
+ CPU_SUBTYPE_POWERPC_970 => :ppc970_64,
+ }.freeze,
+ CPU_TYPE_MC680X0 => {
+ CPU_SUBTYPE_MC680X0_ALL => :m68k,
+ CPU_SUBTYPE_MC68030 => :mc68030,
+ CPU_SUBTYPE_MC68040 => :mc68040,
+ },
+ CPU_TYPE_MC88000 => {
+ CPU_SUBTYPE_MC88000_ALL => :m88k,
+ },
+ }.freeze
+
+ # relocatable object file
+ # @api private
+ MH_OBJECT = 0x1
+
+ # demand paged executable file
+ # @api private
+ MH_EXECUTE = 0x2
+
+ # fixed VM shared library file
+ # @api private
+ MH_FVMLIB = 0x3
+
+ # core dump file
+ # @api private
+ MH_CORE = 0x4
+
+ # preloaded executable file
+ # @api private
+ MH_PRELOAD = 0x5
+
+ # dynamically bound shared library
+ # @api private
+ MH_DYLIB = 0x6
+
+ # dynamic link editor
+ # @api private
+ MH_DYLINKER = 0x7
+
+ # dynamically bound bundle file
+ # @api private
+ MH_BUNDLE = 0x8
+
+ # shared library stub for static linking only, no section contents
+ # @api private
+ MH_DYLIB_STUB = 0x9
+
+ # companion file with only debug sections
+ # @api private
+ MH_DSYM = 0xa
+
+ # x86_64 kexts
+ # @api private
+ MH_KEXT_BUNDLE = 0xb
+
+ # association of filetypes to Symbol representations
+ # @api private
+ MH_FILETYPES = {
+ MH_OBJECT => :object,
+ MH_EXECUTE => :execute,
+ MH_FVMLIB => :fvmlib,
+ MH_CORE => :core,
+ MH_PRELOAD => :preload,
+ MH_DYLIB => :dylib,
+ MH_DYLINKER => :dylinker,
+ MH_BUNDLE => :bundle,
+ MH_DYLIB_STUB => :dylib_stub,
+ MH_DSYM => :dsym,
+ MH_KEXT_BUNDLE => :kext_bundle,
+ }.freeze
+
+ # association of mach header flag symbols to values
+ # @api private
+ MH_FLAGS = {
+ :MH_NOUNDEFS => 0x1,
+ :MH_INCRLINK => 0x2,
+ :MH_DYLDLINK => 0x4,
+ :MH_BINDATLOAD => 0x8,
+ :MH_PREBOUND => 0x10,
+ :MH_SPLIT_SEGS => 0x20,
+ :MH_LAZY_INIT => 0x40,
+ :MH_TWOLEVEL => 0x80,
+ :MH_FORCE_FLAT => 0x100,
+ :MH_NOMULTIDEFS => 0x200,
+ :MH_NOPREFIXBINDING => 0x400,
+ :MH_PREBINDABLE => 0x800,
+ :MH_ALLMODSBOUND => 0x1000,
+ :MH_SUBSECTIONS_VIA_SYMBOLS => 0x2000,
+ :MH_CANONICAL => 0x4000,
+ :MH_WEAK_DEFINES => 0x8000,
+ :MH_BINDS_TO_WEAK => 0x10000,
+ :MH_ALLOW_STACK_EXECUTION => 0x20000,
+ :MH_ROOT_SAFE => 0x40000,
+ :MH_SETUID_SAFE => 0x80000,
+ :MH_NO_REEXPORTED_DYLIBS => 0x100000,
+ :MH_PIE => 0x200000,
+ :MH_DEAD_STRIPPABLE_DYLIB => 0x400000,
+ :MH_HAS_TLV_DESCRIPTORS => 0x800000,
+ :MH_NO_HEAP_EXECUTION => 0x1000000,
+ :MH_APP_EXTENSION_SAFE => 0x02000000,
+ }.freeze
+
+ # Fat binary header structure
+ # @see MachO::FatArch
+ class FatHeader < MachOStructure
+ # @return [Fixnum] the magic number of the header (and file)
+ attr_reader :magic
+
+ # @return [Fixnum] the number of fat architecture structures following the header
+ attr_reader :nfat_arch
+
+ # always big-endian
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "N2".freeze
+
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 8
+
+ # @api private
+ def initialize(magic, nfat_arch)
+ @magic = magic
+ @nfat_arch = nfat_arch
+ end
+
+ # @return [String] the serialized fields of the fat header
+ def serialize
+ [magic, nfat_arch].pack(FORMAT)
+ end
+ end
+
+ # Fat binary header architecture structure. A Fat binary has one or more of
+ # these, representing one or more internal Mach-O blobs.
+ # @see MachO::Headers::FatHeader
+ class FatArch < MachOStructure
+ # @return [Fixnum] the CPU type of the Mach-O
+ attr_reader :cputype
+
+ # @return [Fixnum] the CPU subtype of the Mach-O
+ attr_reader :cpusubtype
+
+ # @return [Fixnum] the file offset to the beginning of the Mach-O data
+ attr_reader :offset
+
+ # @return [Fixnum] the size, in bytes, of the Mach-O data
+ attr_reader :size
+
+ # @return [Fixnum] the alignment, as a power of 2
+ attr_reader :align
+
+ # always big-endian
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "N5".freeze
+
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 20
+
+ # @api private
+ def initialize(cputype, cpusubtype, offset, size, align)
+ @cputype = cputype
+ @cpusubtype = cpusubtype
+ @offset = offset
+ @size = size
+ @align = align
+ end
+
+ # @return [String] the serialized fields of the fat arch
+ def serialize
+ [cputype, cpusubtype, offset, size, align].pack(FORMAT)
+ end
+ end
+
+ # 32-bit Mach-O file header structure
+ class MachHeader < MachOStructure
+ # @return [Fixnum] the magic number
+ attr_reader :magic
+
+ # @return [Fixnum] the CPU type of the Mach-O
+ attr_reader :cputype
+
+ # @return [Fixnum] the CPU subtype of the Mach-O
+ attr_reader :cpusubtype
+
+ # @return [Fixnum] the file type of the Mach-O
+ attr_reader :filetype
+
+ # @return [Fixnum] the number of load commands in the Mach-O
+ attr_reader :ncmds
+
+ # @return [Fixnum] the size of all load commands, in bytes, in the Mach-O
+ attr_reader :sizeofcmds
+
+ # @return [Fixnum] the header flags associated with the Mach-O
+ attr_reader :flags
+
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=7".freeze
+
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 28
+
+ # @api private
+ def initialize(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds,
+ flags)
+ @magic = magic
+ @cputype = cputype
+ # For now we're not interested in additional capability bits also to be
+ # found in the `cpusubtype` field. We only care about the CPU sub-type.
+ @cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK
+ @filetype = filetype
+ @ncmds = ncmds
+ @sizeofcmds = sizeofcmds
+ @flags = flags
+ end
+
+ # @example
+ # puts "this mach-o has position-independent execution" if header.flag?(:MH_PIE)
+ # @param flag [Symbol] a mach header flag symbol
+ # @return [Boolean] true if `flag` is present in the header's flag section
+ def flag?(flag)
+ flag = MH_FLAGS[flag]
+ return false if flag.nil?
+ flags & flag == flag
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_OBJECT`
+ def object?
+ filetype == Headers::MH_OBJECT
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_EXECUTE`
+ def executable?
+ filetype == Headers::MH_EXECUTE
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_FVMLIB`
+ def fvmlib?
+ filetype == Headers::MH_FVMLIB
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_CORE`
+ def core?
+ filetype == Headers::MH_CORE
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_PRELOAD`
+ def preload?
+ filetype == Headers::MH_PRELOAD
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_DYLIB`
+ def dylib?
+ filetype == Headers::MH_DYLIB
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_DYLINKER`
+ def dylinker?
+ filetype == Headers::MH_DYLINKER
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_BUNDLE`
+ def bundle?
+ filetype == Headers::MH_BUNDLE
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_DSYM`
+ def dsym?
+ filetype == Headers::MH_DSYM
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_KEXT_BUNDLE`
+ def kext?
+ filetype == Headers::MH_KEXT_BUNDLE
+ end
+
+ # @return [Boolean] true if the Mach-O has 32-bit magic, false otherwise
+ def magic32?
+ Utils.magic32?(magic)
+ end
+
+ # @return [Boolean] true if the Mach-O has 64-bit magic, false otherwise
+ def magic64?
+ Utils.magic64?(magic)
+ end
+
+ # @return [Fixnum] the file's internal alignment
+ def alignment
+ magic32? ? 4 : 8
+ end
+ end
+
+ # 64-bit Mach-O file header structure
+ class MachHeader64 < MachHeader
+ # @return [void]
+ attr_reader :reserved
+
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=8".freeze
+
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 32
+
+ # @api private
+ def initialize(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds,
+ flags, reserved)
+ super(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags)
+ @reserved = reserved
+ end
end
end
end
diff --git a/Library/Homebrew/vendor/macho/macho/load_commands.rb b/Library/Homebrew/vendor/macho/macho/load_commands.rb
index 205110801..be4319ee2 100644
--- a/Library/Homebrew/vendor/macho/macho/load_commands.rb
+++ b/Library/Homebrew/vendor/macho/macho/load_commands.rb
@@ -1,1314 +1,1350 @@
module MachO
- # load commands added after OS X 10.1 need to be bitwise ORed with
- # LC_REQ_DYLD to be recognized by the dynamic linder (dyld)
- # @api private
- LC_REQ_DYLD = 0x80000000
-
- # association of load commands to symbol representations
- # @api private
- LOAD_COMMANDS = {
- 0x1 => :LC_SEGMENT,
- 0x2 => :LC_SYMTAB,
- 0x3 => :LC_SYMSEG,
- 0x4 => :LC_THREAD,
- 0x5 => :LC_UNIXTHREAD,
- 0x6 => :LC_LOADFVMLIB,
- 0x7 => :LC_IDFVMLIB,
- 0x8 => :LC_IDENT,
- 0x9 => :LC_FVMFILE,
- 0xa => :LC_PREPAGE,
- 0xb => :LC_DYSYMTAB,
- 0xc => :LC_LOAD_DYLIB,
- 0xd => :LC_ID_DYLIB,
- 0xe => :LC_LOAD_DYLINKER,
- 0xf => :LC_ID_DYLINKER,
- 0x10 => :LC_PREBOUND_DYLIB,
- 0x11 => :LC_ROUTINES,
- 0x12 => :LC_SUB_FRAMEWORK,
- 0x13 => :LC_SUB_UMBRELLA,
- 0x14 => :LC_SUB_CLIENT,
- 0x15 => :LC_SUB_LIBRARY,
- 0x16 => :LC_TWOLEVEL_HINTS,
- 0x17 => :LC_PREBIND_CKSUM,
- (0x18 | LC_REQ_DYLD) => :LC_LOAD_WEAK_DYLIB,
- 0x19 => :LC_SEGMENT_64,
- 0x1a => :LC_ROUTINES_64,
- 0x1b => :LC_UUID,
- (0x1c | LC_REQ_DYLD) => :LC_RPATH,
- 0x1d => :LC_CODE_SIGNATURE,
- 0x1e => :LC_SEGMENT_SPLIT_INFO,
- (0x1f | LC_REQ_DYLD) => :LC_REEXPORT_DYLIB,
- 0x20 => :LC_LAZY_LOAD_DYLIB,
- 0x21 => :LC_ENCRYPTION_INFO,
- 0x22 => :LC_DYLD_INFO,
- (0x22 | LC_REQ_DYLD) => :LC_DYLD_INFO_ONLY,
- (0x23 | LC_REQ_DYLD) => :LC_LOAD_UPWARD_DYLIB,
- 0x24 => :LC_VERSION_MIN_MACOSX,
- 0x25 => :LC_VERSION_MIN_IPHONEOS,
- 0x26 => :LC_FUNCTION_STARTS,
- 0x27 => :LC_DYLD_ENVIRONMENT,
- (0x28 | LC_REQ_DYLD) => :LC_MAIN,
- 0x29 => :LC_DATA_IN_CODE,
- 0x2a => :LC_SOURCE_VERSION,
- 0x2b => :LC_DYLIB_CODE_SIGN_DRS,
- 0x2c => :LC_ENCRYPTION_INFO_64,
- 0x2d => :LC_LINKER_OPTION,
- 0x2e => :LC_LINKER_OPTIMIZATION_HINT,
- 0x2f => :LC_VERSION_MIN_TVOS,
- 0x30 => :LC_VERSION_MIN_WATCHOS,
- }.freeze
-
- # association of symbol representations to load command constants
- # @api private
- LOAD_COMMAND_CONSTANTS = LOAD_COMMANDS.invert.freeze
-
- # load commands responsible for loading dylibs
- # @api private
- DYLIB_LOAD_COMMANDS = [
- :LC_LOAD_DYLIB,
- :LC_LOAD_WEAK_DYLIB,
- :LC_REEXPORT_DYLIB,
- :LC_LAZY_LOAD_DYLIB,
- :LC_LOAD_UPWARD_DYLIB,
- ].freeze
-
- # load commands that can be created manually via {LoadCommand.create}
- # @api private
- CREATABLE_LOAD_COMMANDS = DYLIB_LOAD_COMMANDS + [
- :LC_ID_DYLIB,
- :LC_RPATH,
- :LC_LOAD_DYLINKER,
- ].freeze
-
- # association of load command symbols to string representations of classes
- # @api private
- LC_STRUCTURES = {
- :LC_SEGMENT => "SegmentCommand",
- :LC_SYMTAB => "SymtabCommand",
- :LC_SYMSEG => "SymsegCommand", # obsolete
- :LC_THREAD => "ThreadCommand", # seems obsolete, but not documented as such
- :LC_UNIXTHREAD => "ThreadCommand",
- :LC_LOADFVMLIB => "FvmlibCommand", # obsolete
- :LC_IDFVMLIB => "FvmlibCommand", # obsolete
- :LC_IDENT => "IdentCommand", # obsolete
- :LC_FVMFILE => "FvmfileCommand", # reserved for internal use only
- :LC_PREPAGE => "LoadCommand", # reserved for internal use only, no public struct
- :LC_DYSYMTAB => "DysymtabCommand",
- :LC_LOAD_DYLIB => "DylibCommand",
- :LC_ID_DYLIB => "DylibCommand",
- :LC_LOAD_DYLINKER => "DylinkerCommand",
- :LC_ID_DYLINKER => "DylinkerCommand",
- :LC_PREBOUND_DYLIB => "PreboundDylibCommand",
- :LC_ROUTINES => "RoutinesCommand",
- :LC_SUB_FRAMEWORK => "SubFrameworkCommand",
- :LC_SUB_UMBRELLA => "SubUmbrellaCommand",
- :LC_SUB_CLIENT => "SubClientCommand",
- :LC_SUB_LIBRARY => "SubLibraryCommand",
- :LC_TWOLEVEL_HINTS => "TwolevelHintsCommand",
- :LC_PREBIND_CKSUM => "PrebindCksumCommand",
- :LC_LOAD_WEAK_DYLIB => "DylibCommand",
- :LC_SEGMENT_64 => "SegmentCommand64",
- :LC_ROUTINES_64 => "RoutinesCommand64",
- :LC_UUID => "UUIDCommand",
- :LC_RPATH => "RpathCommand",
- :LC_CODE_SIGNATURE => "LinkeditDataCommand",
- :LC_SEGMENT_SPLIT_INFO => "LinkeditDataCommand",
- :LC_REEXPORT_DYLIB => "DylibCommand",
- :LC_LAZY_LOAD_DYLIB => "DylibCommand",
- :LC_ENCRYPTION_INFO => "EncryptionInfoCommand",
- :LC_DYLD_INFO => "DyldInfoCommand",
- :LC_DYLD_INFO_ONLY => "DyldInfoCommand",
- :LC_LOAD_UPWARD_DYLIB => "DylibCommand",
- :LC_VERSION_MIN_MACOSX => "VersionMinCommand",
- :LC_VERSION_MIN_IPHONEOS => "VersionMinCommand",
- :LC_FUNCTION_STARTS => "LinkeditDataCommand",
- :LC_DYLD_ENVIRONMENT => "DylinkerCommand",
- :LC_MAIN => "EntryPointCommand",
- :LC_DATA_IN_CODE => "LinkeditDataCommand",
- :LC_SOURCE_VERSION => "SourceVersionCommand",
- :LC_DYLIB_CODE_SIGN_DRS => "LinkeditDataCommand",
- :LC_ENCRYPTION_INFO_64 => "EncryptionInfoCommand64",
- :LC_LINKER_OPTION => "LinkerOptionCommand",
- :LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand",
- :LC_VERSION_MIN_TVOS => "VersionMinCommand",
- :LC_VERSION_MIN_WATCHOS => "VersionMinCommand",
- }.freeze
-
- # association of segment name symbols to names
- # @api private
- SEGMENT_NAMES = {
- :SEG_PAGEZERO => "__PAGEZERO",
- :SEG_TEXT => "__TEXT",
- :SEG_DATA => "__DATA",
- :SEG_OBJC => "__OBJC",
- :SEG_ICON => "__ICON",
- :SEG_LINKEDIT => "__LINKEDIT",
- :SEG_UNIXSTACK => "__UNIXSTACK",
- :SEG_IMPORT => "__IMPORT",
- }.freeze
-
- # association of segment flag symbols to values
- # @api private
- SEGMENT_FLAGS = {
- :SG_HIGHVM => 0x1,
- :SG_FVMLIB => 0x2,
- :SG_NORELOC => 0x4,
- :SG_PROTECTED_VERSION_1 => 0x8,
- }.freeze
-
- # Mach-O load command structure
- # This is the most generic load command - only cmd ID and size are
- # represented, and no actual data. Used when a more specific class
- # isn't available/implemented.
- class LoadCommand < MachOStructure
- # @return [MachO::MachOView] the raw view associated with the load command
- attr_reader :view
-
- # @return [Fixnum] the load command's identifying number
- attr_reader :cmd
-
- # @return [Fixnum] the size of the load command, in bytes
- attr_reader :cmdsize
-
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2".freeze
+ # Classes and constants for parsing load commands in Mach-O binaries.
+ module LoadCommands
+ # load commands added after OS X 10.1 need to be bitwise ORed with
+ # LC_REQ_DYLD to be recognized by the dynamic linker (dyld)
+ # @api private
+ LC_REQ_DYLD = 0x80000000
+
+ # association of load commands to symbol representations
+ # @api private
+ LOAD_COMMANDS = {
+ 0x1 => :LC_SEGMENT,
+ 0x2 => :LC_SYMTAB,
+ 0x3 => :LC_SYMSEG,
+ 0x4 => :LC_THREAD,
+ 0x5 => :LC_UNIXTHREAD,
+ 0x6 => :LC_LOADFVMLIB,
+ 0x7 => :LC_IDFVMLIB,
+ 0x8 => :LC_IDENT,
+ 0x9 => :LC_FVMFILE,
+ 0xa => :LC_PREPAGE,
+ 0xb => :LC_DYSYMTAB,
+ 0xc => :LC_LOAD_DYLIB,
+ 0xd => :LC_ID_DYLIB,
+ 0xe => :LC_LOAD_DYLINKER,
+ 0xf => :LC_ID_DYLINKER,
+ 0x10 => :LC_PREBOUND_DYLIB,
+ 0x11 => :LC_ROUTINES,
+ 0x12 => :LC_SUB_FRAMEWORK,
+ 0x13 => :LC_SUB_UMBRELLA,
+ 0x14 => :LC_SUB_CLIENT,
+ 0x15 => :LC_SUB_LIBRARY,
+ 0x16 => :LC_TWOLEVEL_HINTS,
+ 0x17 => :LC_PREBIND_CKSUM,
+ (0x18 | LC_REQ_DYLD) => :LC_LOAD_WEAK_DYLIB,
+ 0x19 => :LC_SEGMENT_64,
+ 0x1a => :LC_ROUTINES_64,
+ 0x1b => :LC_UUID,
+ (0x1c | LC_REQ_DYLD) => :LC_RPATH,
+ 0x1d => :LC_CODE_SIGNATURE,
+ 0x1e => :LC_SEGMENT_SPLIT_INFO,
+ (0x1f | LC_REQ_DYLD) => :LC_REEXPORT_DYLIB,
+ 0x20 => :LC_LAZY_LOAD_DYLIB,
+ 0x21 => :LC_ENCRYPTION_INFO,
+ 0x22 => :LC_DYLD_INFO,
+ (0x22 | LC_REQ_DYLD) => :LC_DYLD_INFO_ONLY,
+ (0x23 | LC_REQ_DYLD) => :LC_LOAD_UPWARD_DYLIB,
+ 0x24 => :LC_VERSION_MIN_MACOSX,
+ 0x25 => :LC_VERSION_MIN_IPHONEOS,
+ 0x26 => :LC_FUNCTION_STARTS,
+ 0x27 => :LC_DYLD_ENVIRONMENT,
+ (0x28 | LC_REQ_DYLD) => :LC_MAIN,
+ 0x29 => :LC_DATA_IN_CODE,
+ 0x2a => :LC_SOURCE_VERSION,
+ 0x2b => :LC_DYLIB_CODE_SIGN_DRS,
+ 0x2c => :LC_ENCRYPTION_INFO_64,
+ 0x2d => :LC_LINKER_OPTION,
+ 0x2e => :LC_LINKER_OPTIMIZATION_HINT,
+ 0x2f => :LC_VERSION_MIN_TVOS,
+ 0x30 => :LC_VERSION_MIN_WATCHOS,
+ }.freeze
+
+ # association of symbol representations to load command constants
+ # @api private
+ LOAD_COMMAND_CONSTANTS = LOAD_COMMANDS.invert.freeze
+
+ # load commands responsible for loading dylibs
+ # @api private
+ DYLIB_LOAD_COMMANDS = [
+ :LC_LOAD_DYLIB,
+ :LC_LOAD_WEAK_DYLIB,
+ :LC_REEXPORT_DYLIB,
+ :LC_LAZY_LOAD_DYLIB,
+ :LC_LOAD_UPWARD_DYLIB,
+ ].freeze
+
+ # load commands that can be created manually via {LoadCommand.create}
+ # @api private
+ CREATABLE_LOAD_COMMANDS = DYLIB_LOAD_COMMANDS + [
+ :LC_ID_DYLIB,
+ :LC_RPATH,
+ :LC_LOAD_DYLINKER,
+ ].freeze
+
+ # association of load command symbols to string representations of classes
+ # @api private
+ LC_STRUCTURES = {
+ :LC_SEGMENT => "SegmentCommand",
+ :LC_SYMTAB => "SymtabCommand",
+ # "obsolete"
+ :LC_SYMSEG => "SymsegCommand",
+ # seems obsolete, but not documented as such
+ :LC_THREAD => "ThreadCommand",
+ :LC_UNIXTHREAD => "ThreadCommand",
+ # "obsolete"
+ :LC_LOADFVMLIB => "FvmlibCommand",
+ # "obsolete"
+ :LC_IDFVMLIB => "FvmlibCommand",
+ # "obsolete"
+ :LC_IDENT => "IdentCommand",
+ # "reserved for internal use only"
+ :LC_FVMFILE => "FvmfileCommand",
+ # "reserved for internal use only", no public struct
+ :LC_PREPAGE => "LoadCommand",
+ :LC_DYSYMTAB => "DysymtabCommand",
+ :LC_LOAD_DYLIB => "DylibCommand",
+ :LC_ID_DYLIB => "DylibCommand",
+ :LC_LOAD_DYLINKER => "DylinkerCommand",
+ :LC_ID_DYLINKER => "DylinkerCommand",
+ :LC_PREBOUND_DYLIB => "PreboundDylibCommand",
+ :LC_ROUTINES => "RoutinesCommand",
+ :LC_SUB_FRAMEWORK => "SubFrameworkCommand",
+ :LC_SUB_UMBRELLA => "SubUmbrellaCommand",
+ :LC_SUB_CLIENT => "SubClientCommand",
+ :LC_SUB_LIBRARY => "SubLibraryCommand",
+ :LC_TWOLEVEL_HINTS => "TwolevelHintsCommand",
+ :LC_PREBIND_CKSUM => "PrebindCksumCommand",
+ :LC_LOAD_WEAK_DYLIB => "DylibCommand",
+ :LC_SEGMENT_64 => "SegmentCommand64",
+ :LC_ROUTINES_64 => "RoutinesCommand64",
+ :LC_UUID => "UUIDCommand",
+ :LC_RPATH => "RpathCommand",
+ :LC_CODE_SIGNATURE => "LinkeditDataCommand",
+ :LC_SEGMENT_SPLIT_INFO => "LinkeditDataCommand",
+ :LC_REEXPORT_DYLIB => "DylibCommand",
+ :LC_LAZY_LOAD_DYLIB => "DylibCommand",
+ :LC_ENCRYPTION_INFO => "EncryptionInfoCommand",
+ :LC_DYLD_INFO => "DyldInfoCommand",
+ :LC_DYLD_INFO_ONLY => "DyldInfoCommand",
+ :LC_LOAD_UPWARD_DYLIB => "DylibCommand",
+ :LC_VERSION_MIN_MACOSX => "VersionMinCommand",
+ :LC_VERSION_MIN_IPHONEOS => "VersionMinCommand",
+ :LC_FUNCTION_STARTS => "LinkeditDataCommand",
+ :LC_DYLD_ENVIRONMENT => "DylinkerCommand",
+ :LC_MAIN => "EntryPointCommand",
+ :LC_DATA_IN_CODE => "LinkeditDataCommand",
+ :LC_SOURCE_VERSION => "SourceVersionCommand",
+ :LC_DYLIB_CODE_SIGN_DRS => "LinkeditDataCommand",
+ :LC_ENCRYPTION_INFO_64 => "EncryptionInfoCommand64",
+ :LC_LINKER_OPTION => "LinkerOptionCommand",
+ :LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand",
+ :LC_VERSION_MIN_TVOS => "VersionMinCommand",
+ :LC_VERSION_MIN_WATCHOS => "VersionMinCommand",
+ }.freeze
+
+ # association of segment name symbols to names
+ # @api private
+ SEGMENT_NAMES = {
+ :SEG_PAGEZERO => "__PAGEZERO",
+ :SEG_TEXT => "__TEXT",
+ :SEG_DATA => "__DATA",
+ :SEG_OBJC => "__OBJC",
+ :SEG_ICON => "__ICON",
+ :SEG_LINKEDIT => "__LINKEDIT",
+ :SEG_UNIXSTACK => "__UNIXSTACK",
+ :SEG_IMPORT => "__IMPORT",
+ }.freeze
+
+ # association of segment flag symbols to values
+ # @api private
+ SEGMENT_FLAGS = {
+ :SG_HIGHVM => 0x1,
+ :SG_FVMLIB => 0x2,
+ :SG_NORELOC => 0x4,
+ :SG_PROTECTED_VERSION_1 => 0x8,
+ }.freeze
+
+ # Mach-O load command structure
+ # This is the most generic load command - only cmd ID and size are
+ # represented, and no actual data. Used when a more specific class
+ # isn't available/implemented.
+ class LoadCommand < MachOStructure
+ # @return [MachO::MachOView] the raw view associated with the load command
+ attr_reader :view
+
+ # @return [Fixnum] the load command's identifying number
+ attr_reader :cmd
+
+ # @return [Fixnum] the size of the load command, in bytes
+ attr_reader :cmdsize
+
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 8
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 8
- # Instantiates a new LoadCommand given a view into its origin Mach-O
- # @param view [MachO::MachOView] the load command's raw view
- # @return [MachO::LoadCommand] the new load command
- # @api private
- def self.new_from_bin(view)
- bin = view.raw_data.slice(view.offset, bytesize)
- format = Utils.specialize_format(self::FORMAT, view.endianness)
+ # Instantiates a new LoadCommand given a view into its origin Mach-O
+ # @param view [MachO::MachOView] the load command's raw view
+ # @return [LoadCommand] the new load command
+ # @api private
+ def self.new_from_bin(view)
+ bin = view.raw_data.slice(view.offset, bytesize)
+ format = Utils.specialize_format(self::FORMAT, view.endianness)
- new(view, *bin.unpack(format))
- end
+ new(view, *bin.unpack(format))
+ end
- # Creates a new (viewless) command corresponding to the symbol provided
- # @param cmd_sym [Symbol] the symbol of the load command being created
- # @param args [Array] the arguments for the load command being created
- def self.create(cmd_sym, *args)
- raise LoadCommandNotCreatableError, cmd_sym unless CREATABLE_LOAD_COMMANDS.include?(cmd_sym)
+ # Creates a new (viewless) command corresponding to the symbol provided
+ # @param cmd_sym [Symbol] the symbol of the load command being created
+ # @param args [Array] the arguments for the load command being created
+ def self.create(cmd_sym, *args)
+ raise LoadCommandNotCreatableError, cmd_sym unless CREATABLE_LOAD_COMMANDS.include?(cmd_sym)
- klass = MachO.const_get LC_STRUCTURES[cmd_sym]
- cmd = LOAD_COMMAND_CONSTANTS[cmd_sym]
+ klass = LoadCommands.const_get LC_STRUCTURES[cmd_sym]
+ cmd = LOAD_COMMAND_CONSTANTS[cmd_sym]
- # cmd will be filled in, view and cmdsize will be left unpopulated
- klass_arity = klass.instance_method(:initialize).arity - 3
+ # cmd will be filled in, view and cmdsize will be left unpopulated
+ klass_arity = klass.instance_method(:initialize).arity - 3
- raise LoadCommandCreationArityError.new(cmd_sym, klass_arity, args.size) if klass_arity != args.size
+ raise LoadCommandCreationArityError.new(cmd_sym, klass_arity, args.size) if klass_arity != args.size
- klass.new(nil, cmd, nil, *args)
- end
+ klass.new(nil, cmd, nil, *args)
+ end
- # @param view [MachO::MachOView] the load command's raw view
- # @param cmd [Fixnum] the load command's identifying number
- # @param cmdsize [Fixnum] the size of the load command in bytes
- # @api private
- def initialize(view, cmd, cmdsize)
- @view = view
- @cmd = cmd
- @cmdsize = cmdsize
- end
+ # @param view [MachO::MachOView] the load command's raw view
+ # @param cmd [Fixnum] the load command's identifying number
+ # @param cmdsize [Fixnum] the size of the load command in bytes
+ # @api private
+ def initialize(view, cmd, cmdsize)
+ @view = view
+ @cmd = cmd
+ @cmdsize = cmdsize
+ end
- # @return [Boolean] true if the load command can be serialized, false otherwise
- def serializable?
- CREATABLE_LOAD_COMMANDS.include?(LOAD_COMMANDS[cmd])
- end
+ # @return [Boolean] whether the load command can be serialized
+ def serializable?
+ CREATABLE_LOAD_COMMANDS.include?(LOAD_COMMANDS[cmd])
+ end
- # @param context [MachO::LoadCommand::SerializationContext] the context
- # to serialize into
- # @return [String, nil] the serialized fields of the load command, or nil
- # if the load command can't be serialized
- # @api private
- def serialize(context)
- raise LoadCommandNotSerializableError, LOAD_COMMANDS[cmd] unless serializable?
- format = Utils.specialize_format(FORMAT, context.endianness)
- [cmd, SIZEOF].pack(format)
- end
+ # @param context [SerializationContext] the context
+ # to serialize into
+ # @return [String, nil] the serialized fields of the load command, or nil
+ # if the load command can't be serialized
+ # @api private
+ def serialize(context)
+ raise LoadCommandNotSerializableError, LOAD_COMMANDS[cmd] unless serializable?
+ format = Utils.specialize_format(FORMAT, context.endianness)
+ [cmd, SIZEOF].pack(format)
+ end
- # @return [Fixnum] the load command's offset in the source file
- # @deprecated use {#view} instead
- def offset
- view.offset
- end
+ # @return [Fixnum] the load command's offset in the source file
+ # @deprecated use {#view} instead
+ def offset
+ view.offset
+ end
- # @return [Symbol] a symbol representation of the load command's identifying number
- def type
- LOAD_COMMANDS[cmd]
- end
+ # @return [Symbol] a symbol representation of the load command's
+ # identifying number
+ def type
+ LOAD_COMMANDS[cmd]
+ end
- alias to_sym type
+ alias to_sym type
- # @return [String] a string representation of the load command's identifying number
- def to_s
- type.to_s
- end
+ # @return [String] a string representation of the load command's
+ # identifying number
+ def to_s
+ type.to_s
+ end
- # Represents a Load Command string. A rough analogue to the lc_str
- # struct used internally by OS X. This class allows ruby-macho to
- # pretend that strings stored in LCs are immediately available without
- # explicit operations on the raw Mach-O data.
- class LCStr
- # @param lc [MachO::LoadCommand] the load command
- # @param lc_str [Fixnum, String] the offset to the beginning of the string,
- # or the string itself if not being initialized with a view.
- # @raise [MachO::LCStrMalformedError] if the string is malformed
- # @todo devise a solution such that the `lc_str` parameter is not
- # interpreted differently depending on `lc.view`. The current behavior
- # is a hack to allow viewless load command creation.
- # @api private
- def initialize(lc, lc_str)
- view = lc.view
-
- if view
- lc_str_abs = view.offset + lc_str
- lc_end = view.offset + lc.cmdsize - 1
- raw_string = view.raw_data.slice(lc_str_abs..lc_end)
- @string, null_byte, _padding = raw_string.partition("\x00")
- raise LCStrMalformedError, lc if null_byte.empty?
- @string_offset = lc_str
- else
- @string = lc_str
- @string_offset = 0
+ # Represents a Load Command string. A rough analogue to the lc_str
+ # struct used internally by OS X. This class allows ruby-macho to
+ # pretend that strings stored in LCs are immediately available without
+ # explicit operations on the raw Mach-O data.
+ class LCStr
+ # @param lc [LoadCommand] the load command
+ # @param lc_str [Fixnum, String] the offset to the beginning of the
+ # string, or the string itself if not being initialized with a view.
+ # @raise [MachO::LCStrMalformedError] if the string is malformed
+ # @todo devise a solution such that the `lc_str` parameter is not
+ # interpreted differently depending on `lc.view`. The current behavior
+ # is a hack to allow viewless load command creation.
+ # @api private
+ def initialize(lc, lc_str)
+ view = lc.view
+
+ if view
+ lc_str_abs = view.offset + lc_str
+ lc_end = view.offset + lc.cmdsize - 1
+ raw_string = view.raw_data.slice(lc_str_abs..lc_end)
+ @string, null_byte, _padding = raw_string.partition("\x00")
+ raise LCStrMalformedError, lc if null_byte.empty?
+ @string_offset = lc_str
+ else
+ @string = lc_str
+ @string_offset = 0
+ end
end
- end
- # @return [String] a string representation of the LCStr
- def to_s
- @string
+ # @return [String] a string representation of the LCStr
+ def to_s
+ @string
+ end
+
+ # @return [Fixnum] the offset to the beginning of the string in the
+ # load command
+ def to_i
+ @string_offset
+ end
end
- # @return [Fixnum] the offset to the beginning of the string in the load command
- def to_i
- @string_offset
+ # Represents the contextual information needed by a load command to
+ # serialize itself correctly into a binary string.
+ class SerializationContext
+ # @return [Symbol] the endianness of the serialized load command
+ attr_reader :endianness
+
+ # @return [Fixnum] the constant alignment value used to pad the
+ # serialized load command
+ attr_reader :alignment
+
+ # @param macho [MachO::MachOFile] the file to contextualize
+ # @return [SerializationContext] the
+ # resulting context
+ def self.context_for(macho)
+ new(macho.endianness, macho.alignment)
+ end
+
+ # @param endianness [Symbol] the endianness of the context
+ # @param alignment [Fixnum] the alignment of the context
+ # @api private
+ def initialize(endianness, alignment)
+ @endianness = endianness
+ @alignment = alignment
+ end
end
end
- # Represents the contextual information needed by a load command to
- # serialize itself correctly into a binary string.
- class SerializationContext
- # @return [Symbol] the endianness of the serialized load command
- attr_reader :endianness
+ # A load command containing a single 128-bit unique random number
+ # identifying an object produced by static link editor. Corresponds to
+ # LC_UUID.
+ class UUIDCommand < LoadCommand
+ # @return [Array<Fixnum>] the UUID
+ attr_reader :uuid
- # @return [Fixnum] the constant alignment value used to pad the serialized load command
- attr_reader :alignment
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2a16".freeze
- # @param macho [MachO::MachOFile] the file to contextualize
- # @return [MachO::LoadCommand::SerializationContext] the resulting context
- def self.context_for(macho)
- new(macho.endianness, macho.alignment)
- end
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 24
- # @param endianness [Symbol] the endianness of the context
- # @param alignment [Fixnum] the alignment of the context
# @api private
- def initialize(endianness, alignment)
- @endianness = endianness
- @alignment = alignment
+ def initialize(view, cmd, cmdsize, uuid)
+ super(view, cmd, cmdsize)
+ @uuid = uuid.unpack("C16") # re-unpack for the actual UUID array
end
- end
- end
-
- # A load command containing a single 128-bit unique random number identifying
- # an object produced by static link editor. Corresponds to LC_UUID.
- class UUIDCommand < LoadCommand
- # @return [Array<Fixnum>] the UUID
- attr_reader :uuid
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2a16".freeze
-
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 24
+ # @return [String] a string representation of the UUID
+ def uuid_string
+ hexes = uuid.map { |e| "%02x" % e }
+ segs = [
+ hexes[0..3].join, hexes[4..5].join, hexes[6..7].join,
+ hexes[8..9].join, hexes[10..15].join
+ ]
- # @api private
- def initialize(view, cmd, cmdsize, uuid)
- super(view, cmd, cmdsize)
- @uuid = uuid.unpack("C16") # re-unpack for the actual UUID array
+ segs.join("-")
+ end
end
- # @return [String] a string representation of the UUID
- def uuid_string
- hexes = uuid.map { |e| "%02x" % e }
- segs = [
- hexes[0..3].join, hexes[4..5].join, hexes[6..7].join,
- hexes[8..9].join, hexes[10..15].join
- ]
+ # A load command indicating that part of this file is to be mapped into
+ # the task's address space. Corresponds to LC_SEGMENT.
+ class SegmentCommand < LoadCommand
+ # @return [String] the name of the segment
+ attr_reader :segname
- segs.join("-")
- end
- end
+ # @return [Fixnum] the memory address of the segment
+ attr_reader :vmaddr
- # A load command indicating that part of this file is to be mapped into
- # the task's address space. Corresponds to LC_SEGMENT.
- class SegmentCommand < LoadCommand
- # @return [String] the name of the segment
- attr_reader :segname
+ # @return [Fixnum] the memory size of the segment
+ attr_reader :vmsize
- # @return [Fixnum] the memory address of the segment
- attr_reader :vmaddr
+ # @return [Fixnum] the file offset of the segment
+ attr_reader :fileoff
- # @return [Fixnum] the memory size of the segment
- attr_reader :vmsize
+ # @return [Fixnum] the amount to map from the file
+ attr_reader :filesize
- # @return [Fixnum] the file offset of the segment
- attr_reader :fileoff
+ # @return [Fixnum] the maximum VM protection
+ attr_reader :maxprot
- # @return [Fixnum] the amount to map from the file
- attr_reader :filesize
+ # @return [Fixnum] the initial VM protection
+ attr_reader :initprot
- # @return [Fixnum] the maximum VM protection
- attr_reader :maxprot
+ # @return [Fixnum] the number of sections in the segment
+ attr_reader :nsects
- # @return [Fixnum] the initial VM protection
- attr_reader :initprot
+ # @return [Fixnum] any flags associated with the segment
+ attr_reader :flags
- # @return [Fixnum] the number of sections in the segment
- attr_reader :nsects
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2a16L=4l=2L=2".freeze
- # @return [Fixnum] any flags associated with the segment
- attr_reader :flags
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 56
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2a16L=4l=2L=2".freeze
+ # @api private
+ def initialize(view, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
+ filesize, maxprot, initprot, nsects, flags)
+ super(view, cmd, cmdsize)
+ @segname = segname.delete("\x00")
+ @vmaddr = vmaddr
+ @vmsize = vmsize
+ @fileoff = fileoff
+ @filesize = filesize
+ @maxprot = maxprot
+ @initprot = initprot
+ @nsects = nsects
+ @flags = flags
+ end
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 56
+ # All sections referenced within this segment.
+ # @return [Array<MachO::Sections::Section>] if the Mach-O is 32-bit
+ # @return [Array<MachO::Sections::Section64>] if the Mach-O is 64-bit
+ def sections
+ klass = case self
+ when SegmentCommand64
+ MachO::Sections::Section64
+ when SegmentCommand
+ MachO::Sections::Section
+ end
- # @api private
- def initialize(view, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
- filesize, maxprot, initprot, nsects, flags)
- super(view, cmd, cmdsize)
- @segname = segname.delete("\x00")
- @vmaddr = vmaddr
- @vmsize = vmsize
- @fileoff = fileoff
- @filesize = filesize
- @maxprot = maxprot
- @initprot = initprot
- @nsects = nsects
- @flags = flags
- end
+ offset = view.offset + self.class.bytesize
+ length = nsects * klass.bytesize
- # All sections referenced within this segment.
- # @return [Array<MachO::Section>] if the Mach-O is 32-bit
- # @return [Array<MachO::Section64>] if the Mach-O is 64-bit
- def sections
- klass = case self
- when MachO::SegmentCommand64
- MachO::Section64
- when MachO::SegmentCommand
- MachO::Section
+ bins = view.raw_data[offset, length]
+ bins.unpack("a#{klass.bytesize}" * nsects).map do |bin|
+ klass.new_from_bin(view.endianness, bin)
+ end
end
- bins = view.raw_data[view.offset + self.class.bytesize, nsects * klass.bytesize]
- bins.unpack("a#{klass.bytesize}" * nsects).map do |bin|
- klass.new_from_bin(view.endianness, bin)
+ # @example
+ # puts "this segment relocated in/to it" if sect.flag?(:SG_NORELOC)
+ # @param flag [Symbol] a segment flag symbol
+ # @return [Boolean] true if `flag` is present in the segment's flag field
+ def flag?(flag)
+ flag = SEGMENT_FLAGS[flag]
+ return false if flag.nil?
+ flags & flag == flag
end
end
- # @example
- # puts "this segment relocated in/to it" if sect.flag?(:SG_NORELOC)
- # @param flag [Symbol] a segment flag symbol
- # @return [Boolean] true if `flag` is present in the segment's flag field
- def flag?(flag)
- flag = SEGMENT_FLAGS[flag]
- return false if flag.nil?
- flags & flag == flag
- end
- end
-
- # A load command indicating that part of this file is to be mapped into
- # the task's address space. Corresponds to LC_SEGMENT_64.
- class SegmentCommand64 < SegmentCommand
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2a16Q=4l=2L=2".freeze
+ # A load command indicating that part of this file is to be mapped into
+ # the task's address space. Corresponds to LC_SEGMENT_64.
+ class SegmentCommand64 < SegmentCommand
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2a16Q=4l=2L=2".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 72
- end
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 72
+ end
- # A load command representing some aspect of shared libraries, depending
- # on filetype. Corresponds to LC_ID_DYLIB, LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB,
- # and LC_REEXPORT_DYLIB.
- class DylibCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the library's path name as an LCStr
- attr_reader :name
+ # A load command representing some aspect of shared libraries, depending
+ # on filetype. Corresponds to LC_ID_DYLIB, LC_LOAD_DYLIB,
+ # LC_LOAD_WEAK_DYLIB, and LC_REEXPORT_DYLIB.
+ class DylibCommand < LoadCommand
+ # @return [LCStr] the library's path
+ # name as an LCStr
+ attr_reader :name
- # @return [Fixnum] the library's build time stamp
- attr_reader :timestamp
+ # @return [Fixnum] the library's build time stamp
+ attr_reader :timestamp
- # @return [Fixnum] the library's current version number
- attr_reader :current_version
+ # @return [Fixnum] the library's current version number
+ attr_reader :current_version
- # @return [Fixnum] the library's compatibility version number
- attr_reader :compatibility_version
+ # @return [Fixnum] the library's compatibility version number
+ attr_reader :compatibility_version
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=6".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=6".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 24
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 24
- # @api private
- def initialize(view, cmd, cmdsize, name, timestamp, current_version, compatibility_version)
- super(view, cmd, cmdsize)
- @name = LCStr.new(self, name)
- @timestamp = timestamp
- @current_version = current_version
- @compatibility_version = compatibility_version
- end
+ # @api private
+ def initialize(view, cmd, cmdsize, name, timestamp, current_version,
+ compatibility_version)
+ super(view, cmd, cmdsize)
+ @name = LCStr.new(self, name)
+ @timestamp = timestamp
+ @current_version = current_version
+ @compatibility_version = compatibility_version
+ end
- # @param context [MachO::LoadCcommand::SerializationContext] the context
- # @return [String] the serialized fields of the load command
- # @api private
- def serialize(context)
- format = Utils.specialize_format(FORMAT, context.endianness)
- string_payload, string_offsets = Utils.pack_strings(SIZEOF, context.alignment, :name => name.to_s)
- cmdsize = SIZEOF + string_payload.bytesize
- [cmd, cmdsize, string_offsets[:name], timestamp, current_version,
- compatibility_version].pack(format) + string_payload
+ # @param context [SerializationContext]
+ # the context
+ # @return [String] the serialized fields of the load command
+ # @api private
+ def serialize(context)
+ format = Utils.specialize_format(FORMAT, context.endianness)
+ string_payload, string_offsets = Utils.pack_strings(SIZEOF,
+ context.alignment,
+ :name => name.to_s)
+ cmdsize = SIZEOF + string_payload.bytesize
+ [cmd, cmdsize, string_offsets[:name], timestamp, current_version,
+ compatibility_version].pack(format) + string_payload
+ end
end
- end
- # A load command representing some aspect of the dynamic linker, depending
- # on filetype. Corresponds to LC_ID_DYLINKER, LC_LOAD_DYLINKER, and
- # LC_DYLD_ENVIRONMENT.
- class DylinkerCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the dynamic linker's path name as an LCStr
- attr_reader :name
+ # A load command representing some aspect of the dynamic linker, depending
+ # on filetype. Corresponds to LC_ID_DYLINKER, LC_LOAD_DYLINKER, and
+ # LC_DYLD_ENVIRONMENT.
+ class DylinkerCommand < LoadCommand
+ # @return [LCStr] the dynamic linker's
+ # path name as an LCStr
+ attr_reader :name
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, name)
- super(view, cmd, cmdsize)
- @name = LCStr.new(self, name)
- end
+ # @api private
+ def initialize(view, cmd, cmdsize, name)
+ super(view, cmd, cmdsize)
+ @name = LCStr.new(self, name)
+ end
- # @param context [MachO::LoadCcommand::SerializationContext] the context
- # @return [String] the serialized fields of the load command
- # @api private
- def serialize(context)
- format = Utils.specialize_format(FORMAT, context.endianness)
- string_payload, string_offsets = Utils.pack_strings(SIZEOF, context.alignment, :name => name.to_s)
- cmdsize = SIZEOF + string_payload.bytesize
- [cmd, cmdsize, string_offsets[:name]].pack(format) + string_payload
+ # @param context [SerializationContext]
+ # the context
+ # @return [String] the serialized fields of the load command
+ # @api private
+ def serialize(context)
+ format = Utils.specialize_format(FORMAT, context.endianness)
+ string_payload, string_offsets = Utils.pack_strings(SIZEOF,
+ context.alignment,
+ :name => name.to_s)
+ cmdsize = SIZEOF + string_payload.bytesize
+ [cmd, cmdsize, string_offsets[:name]].pack(format) + string_payload
+ end
end
- end
- # A load command used to indicate dynamic libraries used in prebinding.
- # Corresponds to LC_PREBOUND_DYLIB.
- class PreboundDylibCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the library's path name as an LCStr
- attr_reader :name
+ # A load command used to indicate dynamic libraries used in prebinding.
+ # Corresponds to LC_PREBOUND_DYLIB.
+ class PreboundDylibCommand < LoadCommand
+ # @return [LCStr] the library's path
+ # name as an LCStr
+ attr_reader :name
- # @return [Fixnum] the number of modules in the library
- attr_reader :nmodules
+ # @return [Fixnum] the number of modules in the library
+ attr_reader :nmodules
- # @return [Fixnum] a bit vector of linked modules
- attr_reader :linked_modules
+ # @return [Fixnum] a bit vector of linked modules
+ attr_reader :linked_modules
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=5".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=5".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 20
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 20
- # @api private
- def initialize(view, cmd, cmdsize, name, nmodules, linked_modules)
- super(view, cmd, cmdsize)
- @name = LCStr.new(self, name)
- @nmodules = nmodules
- @linked_modules = linked_modules
+ # @api private
+ def initialize(view, cmd, cmdsize, name, nmodules, linked_modules)
+ super(view, cmd, cmdsize)
+ @name = LCStr.new(self, name)
+ @nmodules = nmodules
+ @linked_modules = linked_modules
+ end
end
- end
- # A load command used to represent threads.
- # @note cctools-870 has all fields of thread_command commented out except common ones (cmd, cmdsize)
- class ThreadCommand < LoadCommand
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2".freeze
+ # A load command used to represent threads.
+ # @note cctools-870 and onwards have all fields of thread_command commented
+ # out except the common ones (cmd, cmdsize)
+ class ThreadCommand < LoadCommand
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 8
- end
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 8
+ end
- # A load command containing the address of the dynamic shared library
- # initialization routine and an index into the module table for the module
- # that defines the routine. Corresponds to LC_ROUTINES.
- class RoutinesCommand < LoadCommand
- # @return [Fixnum] the address of the initialization routine
- attr_reader :init_address
+ # A load command containing the address of the dynamic shared library
+ # initialization routine and an index into the module table for the module
+ # that defines the routine. Corresponds to LC_ROUTINES.
+ class RoutinesCommand < LoadCommand
+ # @return [Fixnum] the address of the initialization routine
+ attr_reader :init_address
- # @return [Fixnum] the index into the module table that the init routine is defined in
- attr_reader :init_module
+ # @return [Fixnum] the index into the module table that the init routine
+ # is defined in
+ attr_reader :init_module
- # @return [void]
- attr_reader :reserved1
+ # @return [void]
+ attr_reader :reserved1
- # @return [void]
- attr_reader :reserved2
+ # @return [void]
+ attr_reader :reserved2
- # @return [void]
- attr_reader :reserved3
+ # @return [void]
+ attr_reader :reserved3
- # @return [void]
- attr_reader :reserved4
+ # @return [void]
+ attr_reader :reserved4
- # @return [void]
- attr_reader :reserved5
+ # @return [void]
+ attr_reader :reserved5
- # @return [void]
- attr_reader :reserved6
+ # @return [void]
+ attr_reader :reserved6
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=10".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=10".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 40
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 40
- # @api private
- def initialize(view, cmd, cmdsize, init_address, init_module, reserved1,
- reserved2, reserved3, reserved4, reserved5, reserved6)
- super(view, cmd, cmdsize)
- @init_address = init_address
- @init_module = init_module
- @reserved1 = reserved1
- @reserved2 = reserved2
- @reserved3 = reserved3
- @reserved4 = reserved4
- @reserved5 = reserved5
- @reserved6 = reserved6
+ # @api private
+ def initialize(view, cmd, cmdsize, init_address, init_module, reserved1,
+ reserved2, reserved3, reserved4, reserved5, reserved6)
+ super(view, cmd, cmdsize)
+ @init_address = init_address
+ @init_module = init_module
+ @reserved1 = reserved1
+ @reserved2 = reserved2
+ @reserved3 = reserved3
+ @reserved4 = reserved4
+ @reserved5 = reserved5
+ @reserved6 = reserved6
+ end
end
- end
- # A load command containing the address of the dynamic shared library
- # initialization routine and an index into the module table for the module
- # that defines the routine. Corresponds to LC_ROUTINES_64.
- class RoutinesCommand64 < RoutinesCommand
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2Q=8".freeze
+ # A load command containing the address of the dynamic shared library
+ # initialization routine and an index into the module table for the module
+ # that defines the routine. Corresponds to LC_ROUTINES_64.
+ class RoutinesCommand64 < RoutinesCommand
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2Q=8".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 72
- end
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 72
+ end
- # A load command signifying membership of a subframework containing the name
- # of an umbrella framework. Corresponds to LC_SUB_FRAMEWORK.
- class SubFrameworkCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the umbrella framework name as an LCStr
- attr_reader :umbrella
+ # A load command signifying membership of a subframework containing the name
+ # of an umbrella framework. Corresponds to LC_SUB_FRAMEWORK.
+ class SubFrameworkCommand < LoadCommand
+ # @return [LCStr] the umbrella framework name as an LCStr
+ attr_reader :umbrella
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, umbrella)
- super(view, cmd, cmdsize)
- @umbrella = LCStr.new(self, umbrella)
+ # @api private
+ def initialize(view, cmd, cmdsize, umbrella)
+ super(view, cmd, cmdsize)
+ @umbrella = LCStr.new(self, umbrella)
+ end
end
- end
- # A load command signifying membership of a subumbrella containing the name
- # of an umbrella framework. Corresponds to LC_SUB_UMBRELLA.
- class SubUmbrellaCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the subumbrella framework name as an LCStr
- attr_reader :sub_umbrella
+ # A load command signifying membership of a subumbrella containing the name
+ # of an umbrella framework. Corresponds to LC_SUB_UMBRELLA.
+ class SubUmbrellaCommand < LoadCommand
+ # @return [LCStr] the subumbrella framework name as an LCStr
+ attr_reader :sub_umbrella
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, sub_umbrella)
- super(view, cmd, cmdsize)
- @sub_umbrella = LCStr.new(self, sub_umbrella)
+ # @api private
+ def initialize(view, cmd, cmdsize, sub_umbrella)
+ super(view, cmd, cmdsize)
+ @sub_umbrella = LCStr.new(self, sub_umbrella)
+ end
end
- end
- # A load command signifying a sublibrary of a shared library. Corresponds
- # to LC_SUB_LIBRARY.
- class SubLibraryCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the sublibrary name as an LCStr
- attr_reader :sub_library
+ # A load command signifying a sublibrary of a shared library. Corresponds
+ # to LC_SUB_LIBRARY.
+ class SubLibraryCommand < LoadCommand
+ # @return [LCStr] the sublibrary name as an LCStr
+ attr_reader :sub_library
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, sub_library)
- super(view, cmd, cmdsize)
- @sub_library = LCStr.new(self, sub_library)
+ # @api private
+ def initialize(view, cmd, cmdsize, sub_library)
+ super(view, cmd, cmdsize)
+ @sub_library = LCStr.new(self, sub_library)
+ end
end
- end
- # A load command signifying a shared library that is a subframework of
- # an umbrella framework. Corresponds to LC_SUB_CLIENT.
- class SubClientCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the subclient name as an LCStr
- attr_reader :sub_client
+ # A load command signifying a shared library that is a subframework of
+ # an umbrella framework. Corresponds to LC_SUB_CLIENT.
+ class SubClientCommand < LoadCommand
+ # @return [LCStr] the subclient name as an LCStr
+ attr_reader :sub_client
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, sub_client)
- super(view, cmd, cmdsize)
- @sub_client = LCStr.new(self, sub_client)
+ # @api private
+ def initialize(view, cmd, cmdsize, sub_client)
+ super(view, cmd, cmdsize)
+ @sub_client = LCStr.new(self, sub_client)
+ end
end
- end
- # A load command containing the offsets and sizes of the link-edit 4.3BSD
- # "stab" style symbol table information. Corresponds to LC_SYMTAB.
- class SymtabCommand < LoadCommand
- # @return [Fixnum] the symbol table's offset
- attr_reader :symoff
+ # A load command containing the offsets and sizes of the link-edit 4.3BSD
+ # "stab" style symbol table information. Corresponds to LC_SYMTAB.
+ class SymtabCommand < LoadCommand
+ # @return [Fixnum] the symbol table's offset
+ attr_reader :symoff
- # @return [Fixnum] the number of symbol table entries
- attr_reader :nsyms
+ # @return [Fixnum] the number of symbol table entries
+ attr_reader :nsyms
- # @return the string table's offset
- attr_reader :stroff
+ # @return the string table's offset
+ attr_reader :stroff
- # @return the string table size in bytes
- attr_reader :strsize
+ # @return the string table size in bytes
+ attr_reader :strsize
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=6".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=6".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 24
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 24
- # @api private
- def initialize(view, cmd, cmdsize, symoff, nsyms, stroff, strsize)
- super(view, cmd, cmdsize)
- @symoff = symoff
- @nsyms = nsyms
- @stroff = stroff
- @strsize = strsize
+ # @api private
+ def initialize(view, cmd, cmdsize, symoff, nsyms, stroff, strsize)
+ super(view, cmd, cmdsize)
+ @symoff = symoff
+ @nsyms = nsyms
+ @stroff = stroff
+ @strsize = strsize
+ end
end
- end
- # A load command containing symbolic information needed to support data
- # structures used by the dynamic link editor. Corresponds to LC_DYSYMTAB.
- class DysymtabCommand < LoadCommand
- # @return [Fixnum] the index to local symbols
- attr_reader :ilocalsym
+ # A load command containing symbolic information needed to support data
+ # structures used by the dynamic link editor. Corresponds to LC_DYSYMTAB.
+ class DysymtabCommand < LoadCommand
+ # @return [Fixnum] the index to local symbols
+ attr_reader :ilocalsym
- # @return [Fixnum] the number of local symbols
- attr_reader :nlocalsym
+ # @return [Fixnum] the number of local symbols
+ attr_reader :nlocalsym
- # @return [Fixnum] the index to externally defined symbols
- attr_reader :iextdefsym
+ # @return [Fixnum] the index to externally defined symbols
+ attr_reader :iextdefsym
- # @return [Fixnum] the number of externally defined symbols
- attr_reader :nextdefsym
+ # @return [Fixnum] the number of externally defined symbols
+ attr_reader :nextdefsym
- # @return [Fixnum] the index to undefined symbols
- attr_reader :iundefsym
+ # @return [Fixnum] the index to undefined symbols
+ attr_reader :iundefsym
- # @return [Fixnum] the number of undefined symbols
- attr_reader :nundefsym
+ # @return [Fixnum] the number of undefined symbols
+ attr_reader :nundefsym
- # @return [Fixnum] the file offset to the table of contents
- attr_reader :tocoff
+ # @return [Fixnum] the file offset to the table of contents
+ attr_reader :tocoff
- # @return [Fixnum] the number of entries in the table of contents
- attr_reader :ntoc
+ # @return [Fixnum] the number of entries in the table of contents
+ attr_reader :ntoc
- # @return [Fixnum] the file offset to the module table
- attr_reader :modtaboff
+ # @return [Fixnum] the file offset to the module table
+ attr_reader :modtaboff
- # @return [Fixnum] the number of entries in the module table
- attr_reader :nmodtab
+ # @return [Fixnum] the number of entries in the module table
+ attr_reader :nmodtab
- # @return [Fixnum] the file offset to the referenced symbol table
- attr_reader :extrefsymoff
+ # @return [Fixnum] the file offset to the referenced symbol table
+ attr_reader :extrefsymoff
- # @return [Fixnum] the number of entries in the referenced symbol table
- attr_reader :nextrefsyms
+ # @return [Fixnum] the number of entries in the referenced symbol table
+ attr_reader :nextrefsyms
- # @return [Fixnum] the file offset to the indirect symbol table
- attr_reader :indirectsymoff
+ # @return [Fixnum] the file offset to the indirect symbol table
+ attr_reader :indirectsymoff
- # @return [Fixnum] the number of entries in the indirect symbol table
- attr_reader :nindirectsyms
+ # @return [Fixnum] the number of entries in the indirect symbol table
+ attr_reader :nindirectsyms
- # @return [Fixnum] the file offset to the external relocation entries
- attr_reader :extreloff
+ # @return [Fixnum] the file offset to the external relocation entries
+ attr_reader :extreloff
- # @return [Fixnum] the number of external relocation entries
- attr_reader :nextrel
+ # @return [Fixnum] the number of external relocation entries
+ attr_reader :nextrel
- # @return [Fixnum] the file offset to the local relocation entries
- attr_reader :locreloff
+ # @return [Fixnum] the file offset to the local relocation entries
+ attr_reader :locreloff
- # @return [Fixnum] the number of local relocation entries
- attr_reader :nlocrel
+ # @return [Fixnum] the number of local relocation entries
+ attr_reader :nlocrel
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=20".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=20".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 80
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 80
- # ugh
- # @api private
- def initialize(view, cmd, cmdsize, ilocalsym, nlocalsym, iextdefsym,
- nextdefsym, iundefsym, nundefsym, tocoff, ntoc, modtaboff,
- nmodtab, extrefsymoff, nextrefsyms, indirectsymoff,
- nindirectsyms, extreloff, nextrel, locreloff, nlocrel)
- super(view, cmd, cmdsize)
- @ilocalsym = ilocalsym
- @nlocalsym = nlocalsym
- @iextdefsym = iextdefsym
- @nextdefsym = nextdefsym
- @iundefsym = iundefsym
- @nundefsym = nundefsym
- @tocoff = tocoff
- @ntoc = ntoc
- @modtaboff = modtaboff
- @nmodtab = nmodtab
- @extrefsymoff = extrefsymoff
- @nextrefsyms = nextrefsyms
- @indirectsymoff = indirectsymoff
- @nindirectsyms = nindirectsyms
- @extreloff = extreloff
- @nextrel = nextrel
- @locreloff = locreloff
- @nlocrel = nlocrel
+ # ugh
+ # @api private
+ def initialize(view, cmd, cmdsize, ilocalsym, nlocalsym, iextdefsym,
+ nextdefsym, iundefsym, nundefsym, tocoff, ntoc, modtaboff,
+ nmodtab, extrefsymoff, nextrefsyms, indirectsymoff,
+ nindirectsyms, extreloff, nextrel, locreloff, nlocrel)
+ super(view, cmd, cmdsize)
+ @ilocalsym = ilocalsym
+ @nlocalsym = nlocalsym
+ @iextdefsym = iextdefsym
+ @nextdefsym = nextdefsym
+ @iundefsym = iundefsym
+ @nundefsym = nundefsym
+ @tocoff = tocoff
+ @ntoc = ntoc
+ @modtaboff = modtaboff
+ @nmodtab = nmodtab
+ @extrefsymoff = extrefsymoff
+ @nextrefsyms = nextrefsyms
+ @indirectsymoff = indirectsymoff
+ @nindirectsyms = nindirectsyms
+ @extreloff = extreloff
+ @nextrel = nextrel
+ @locreloff = locreloff
+ @nlocrel = nlocrel
+ end
end
- end
- # A load command containing the offset and number of hints in the two-level
- # namespace lookup hints table. Corresponds to LC_TWOLEVEL_HINTS.
- class TwolevelHintsCommand < LoadCommand
- # @return [Fixnum] the offset to the hint table
- attr_reader :htoffset
+ # A load command containing the offset and number of hints in the two-level
+ # namespace lookup hints table. Corresponds to LC_TWOLEVEL_HINTS.
+ class TwolevelHintsCommand < LoadCommand
+ # @return [Fixnum] the offset to the hint table
+ attr_reader :htoffset
- # @return [Fixnum] the number of hints in the hint table
- attr_reader :nhints
+ # @return [Fixnum] the number of hints in the hint table
+ attr_reader :nhints
- # @return [MachO::TwolevelHintsCommand::TwolevelHintTable] the hint table
- attr_reader :table
+ # @return [TwolevelHintsTable]
+ # the hint table
+ attr_reader :table
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=4".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=4".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 16
- # @api private
- def initialize(view, cmd, cmdsize, htoffset, nhints)
- super(view, cmd, cmdsize)
- @htoffset = htoffset
- @nhints = nhints
- @table = TwolevelHintsTable.new(view, htoffset, nhints)
- end
+ # @api private
+ def initialize(view, cmd, cmdsize, htoffset, nhints)
+ super(view, cmd, cmdsize)
+ @htoffset = htoffset
+ @nhints = nhints
+ @table = TwolevelHintsTable.new(view, htoffset, nhints)
+ end
- # A representation of the two-level namespace lookup hints table exposed
- # by a {TwolevelHintsCommand} (`LC_TWOLEVEL_HINTS`).
- class TwolevelHintsTable
- # @return [Array<MachO::TwoLevelHintsTable::TwoLevelHint>] all hints in the table
- attr_reader :hints
+ # A representation of the two-level namespace lookup hints table exposed
+ # by a {TwolevelHintsCommand} (`LC_TWOLEVEL_HINTS`).
+ class TwolevelHintsTable
+ # @return [Array<TwolevelHint>] all hints in the table
+ attr_reader :hints
- # @param view [MachO::MachOView] the view into the current Mach-O
- # @param htoffset [Fixnum] the offset of the hints table
- # @param nhints [Fixnum] the number of two-level hints in the table
- # @api private
- def initialize(view, htoffset, nhints)
- format = Utils.specialize_format("L=#{nhints}", view.endianness)
- raw_table = view.raw_data[htoffset, nhints * 4]
- blobs = raw_table.unpack(format)
+ # @param view [MachO::MachOView] the view into the current Mach-O
+ # @param htoffset [Fixnum] the offset of the hints table
+ # @param nhints [Fixnum] the number of two-level hints in the table
+ # @api private
+ def initialize(view, htoffset, nhints)
+ format = Utils.specialize_format("L=#{nhints}", view.endianness)
+ raw_table = view.raw_data[htoffset, nhints * 4]
+ blobs = raw_table.unpack(format)
- @hints = blobs.map { |b| TwolevelHint.new(b) }
- end
+ @hints = blobs.map { |b| TwolevelHint.new(b) }
+ end
- # An individual two-level namespace lookup hint.
- class TwolevelHint
- # @return [Fixnum] the index into the sub-images
- attr_reader :isub_image
+ # An individual two-level namespace lookup hint.
+ class TwolevelHint
+ # @return [Fixnum] the index into the sub-images
+ attr_reader :isub_image
- # @return [Fixnum] the index into the table of contents
- attr_reader :itoc
+ # @return [Fixnum] the index into the table of contents
+ attr_reader :itoc
- # @param blob [Fixnum] the 32-bit number containing the lookup hint
- # @api private
- def initialize(blob)
- @isub_image = blob >> 24
- @itoc = blob & 0x00FFFFFF
+ # @param blob [Fixnum] the 32-bit number containing the lookup hint
+ # @api private
+ def initialize(blob)
+ @isub_image = blob >> 24
+ @itoc = blob & 0x00FFFFFF
+ end
end
end
end
- end
- # A load command containing the value of the original checksum for prebound
- # files, or zero. Corresponds to LC_PREBIND_CKSUM.
- class PrebindCksumCommand < LoadCommand
- # @return [Fixnum] the checksum or 0
- attr_reader :cksum
+ # A load command containing the value of the original checksum for prebound
+ # files, or zero. Corresponds to LC_PREBIND_CKSUM.
+ class PrebindCksumCommand < LoadCommand
+ # @return [Fixnum] the checksum or 0
+ attr_reader :cksum
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, cksum)
- super(view, cmd, cmdsize)
- @cksum = cksum
+ # @api private
+ def initialize(view, cmd, cmdsize, cksum)
+ super(view, cmd, cmdsize)
+ @cksum = cksum
+ end
end
- end
- # A load command representing an rpath, which specifies a path that should
- # be added to the current run path used to find @rpath prefixed dylibs.
- # Corresponds to LC_RPATH.
- class RpathCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the path to add to the run path as an LCStr
- attr_reader :path
+ # A load command representing an rpath, which specifies a path that should
+ # be added to the current run path used to find @rpath prefixed dylibs.
+ # Corresponds to LC_RPATH.
+ class RpathCommand < LoadCommand
+ # @return [LCStr] the path to add to the run path as an LCStr
+ attr_reader :path
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, path)
- super(view, cmd, cmdsize)
- @path = LCStr.new(self, path)
- end
+ # @api private
+ def initialize(view, cmd, cmdsize, path)
+ super(view, cmd, cmdsize)
+ @path = LCStr.new(self, path)
+ end
- # @param context [MachO::LoadCcommand::SerializationContext] the context
- # @return [String] the serialized fields of the load command
- # @api private
- def serialize(context)
- format = Utils.specialize_format(FORMAT, context.endianness)
- string_payload, string_offsets = Utils.pack_strings(SIZEOF, context.alignment, :path => path.to_s)
- cmdsize = SIZEOF + string_payload.bytesize
- [cmd, cmdsize, string_offsets[:path]].pack(format) + string_payload
+ # @param context [SerializationContext] the context
+ # @return [String] the serialized fields of the load command
+ # @api private
+ def serialize(context)
+ format = Utils.specialize_format(FORMAT, context.endianness)
+ string_payload, string_offsets = Utils.pack_strings(SIZEOF,
+ context.alignment,
+ :path => path.to_s)
+ cmdsize = SIZEOF + string_payload.bytesize
+ [cmd, cmdsize, string_offsets[:path]].pack(format) + string_payload
+ end
end
- end
- # A load command representing the offsets and sizes of a blob of data in
- # the __LINKEDIT segment. Corresponds to LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO,
- # LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS, and LC_LINKER_OPTIMIZATION_HINT.
- class LinkeditDataCommand < LoadCommand
- # @return [Fixnum] offset to the data in the __LINKEDIT segment
- attr_reader :dataoff
+ # A load command representing the offsets and sizes of a blob of data in
+ # the __LINKEDIT segment. Corresponds to LC_CODE_SIGNATURE,
+ # LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE,
+ # LC_DYLIB_CODE_SIGN_DRS, and LC_LINKER_OPTIMIZATION_HINT.
+ class LinkeditDataCommand < LoadCommand
+ # @return [Fixnum] offset to the data in the __LINKEDIT segment
+ attr_reader :dataoff
- # @return [Fixnum] size of the data in the __LINKEDIT segment
- attr_reader :datasize
+ # @return [Fixnum] size of the data in the __LINKEDIT segment
+ attr_reader :datasize
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=4".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=4".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 16
- # @api private
- def initialize(view, cmd, cmdsize, dataoff, datasize)
- super(view, cmd, cmdsize)
- @dataoff = dataoff
- @datasize = datasize
+ # @api private
+ def initialize(view, cmd, cmdsize, dataoff, datasize)
+ super(view, cmd, cmdsize)
+ @dataoff = dataoff
+ @datasize = datasize
+ end
end
- end
- # A load command representing the offset to and size of an encrypted
- # segment. Corresponds to LC_ENCRYPTION_INFO.
- class EncryptionInfoCommand < LoadCommand
- # @return [Fixnum] the offset to the encrypted segment
- attr_reader :cryptoff
+ # A load command representing the offset to and size of an encrypted
+ # segment. Corresponds to LC_ENCRYPTION_INFO.
+ class EncryptionInfoCommand < LoadCommand
+ # @return [Fixnum] the offset to the encrypted segment
+ attr_reader :cryptoff
- # @return [Fixnum] the size of the encrypted segment
- attr_reader :cryptsize
+ # @return [Fixnum] the size of the encrypted segment
+ attr_reader :cryptsize
- # @return [Fixnum] the encryption system, or 0 if not encrypted yet
- attr_reader :cryptid
+ # @return [Fixnum] the encryption system, or 0 if not encrypted yet
+ attr_reader :cryptid
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=5".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=5".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 20
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 20
- # @api private
- def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid)
- super(view, cmd, cmdsize)
- @cryptoff = cryptoff
- @cryptsize = cryptsize
- @cryptid = cryptid
+ # @api private
+ def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid)
+ super(view, cmd, cmdsize)
+ @cryptoff = cryptoff
+ @cryptsize = cryptsize
+ @cryptid = cryptid
+ end
end
- end
- # A load command representing the offset to and size of an encrypted
- # segment. Corresponds to LC_ENCRYPTION_INFO_64.
- class EncryptionInfoCommand64 < LoadCommand
- # @return [Fixnum] the offset to the encrypted segment
- attr_reader :cryptoff
+ # A load command representing the offset to and size of an encrypted
+ # segment. Corresponds to LC_ENCRYPTION_INFO_64.
+ class EncryptionInfoCommand64 < LoadCommand
+ # @return [Fixnum] the offset to the encrypted segment
+ attr_reader :cryptoff
- # @return [Fixnum] the size of the encrypted segment
- attr_reader :cryptsize
+ # @return [Fixnum] the size of the encrypted segment
+ attr_reader :cryptsize
- # @return [Fixnum] the encryption system, or 0 if not encrypted yet
- attr_reader :cryptid
+ # @return [Fixnum] the encryption system, or 0 if not encrypted yet
+ attr_reader :cryptid
- # @return [Fixnum] 64-bit padding value
- attr_reader :pad
+ # @return [Fixnum] 64-bit padding value
+ attr_reader :pad
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=6".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=6".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 24
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 24
- # @api private
- def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid, pad)
- super(view, cmd, cmdsize)
- @cryptoff = cryptoff
- @cryptsize = cryptsize
- @cryptid = cryptid
- @pad = pad
+ # @api private
+ def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid, pad)
+ super(view, cmd, cmdsize)
+ @cryptoff = cryptoff
+ @cryptsize = cryptsize
+ @cryptid = cryptid
+ @pad = pad
+ end
end
- end
- # A load command containing the minimum OS version on which the binary
- # was built to run. Corresponds to LC_VERSION_MIN_MACOSX and LC_VERSION_MIN_IPHONEOS.
- class VersionMinCommand < LoadCommand
- # @return [Fixnum] the version X.Y.Z packed as x16.y8.z8
- attr_reader :version
+ # A load command containing the minimum OS version on which the binary
+ # was built to run. Corresponds to LC_VERSION_MIN_MACOSX and
+ # LC_VERSION_MIN_IPHONEOS.
+ class VersionMinCommand < LoadCommand
+ # @return [Fixnum] the version X.Y.Z packed as x16.y8.z8
+ attr_reader :version
- # @return [Fixnum] the SDK version X.Y.Z packed as x16.y8.z8
- attr_reader :sdk
+ # @return [Fixnum] the SDK version X.Y.Z packed as x16.y8.z8
+ attr_reader :sdk
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=4".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=4".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 16
- # @api private
- def initialize(view, cmd, cmdsize, version, sdk)
- super(view, cmd, cmdsize)
- @version = version
- @sdk = sdk
- end
+ # @api private
+ def initialize(view, cmd, cmdsize, version, sdk)
+ super(view, cmd, cmdsize)
+ @version = version
+ @sdk = sdk
+ end
- # A string representation of the binary's minimum OS version.
- # @return [String] a string representing the minimum OS version.
- def version_string
- binary = "%032b" % version
- segs = [
- binary[0..15], binary[16..23], binary[24..31]
- ].map { |s| s.to_i(2) }
+ # A string representation of the binary's minimum OS version.
+ # @return [String] a string representing the minimum OS version.
+ def version_string
+ binary = "%032b" % version
+ segs = [
+ binary[0..15], binary[16..23], binary[24..31]
+ ].map { |s| s.to_i(2) }
- segs.join(".")
- end
+ segs.join(".")
+ end
- # A string representation of the binary's SDK version.
- # @return [String] a string representing the SDK version.
- def sdk_string
- binary = "%032b" % sdk
- segs = [
- binary[0..15], binary[16..23], binary[24..31]
- ].map { |s| s.to_i(2) }
+ # A string representation of the binary's SDK version.
+ # @return [String] a string representing the SDK version.
+ def sdk_string
+ binary = "%032b" % sdk
+ segs = [
+ binary[0..15], binary[16..23], binary[24..31]
+ ].map { |s| s.to_i(2) }
- segs.join(".")
+ segs.join(".")
+ end
end
- end
- # A load command containing the file offsets and sizes of the new
- # compressed form of the information dyld needs to load the image.
- # Corresponds to LC_DYLD_INFO and LC_DYLD_INFO_ONLY.
- class DyldInfoCommand < LoadCommand
- # @return [Fixnum] the file offset to the rebase information
- attr_reader :rebase_off
+ # A load command containing the file offsets and sizes of the new
+ # compressed form of the information dyld needs to load the image.
+ # Corresponds to LC_DYLD_INFO and LC_DYLD_INFO_ONLY.
+ class DyldInfoCommand < LoadCommand
+ # @return [Fixnum] the file offset to the rebase information
+ attr_reader :rebase_off
- # @return [Fixnum] the size of the rebase information
- attr_reader :rebase_size
+ # @return [Fixnum] the size of the rebase information
+ attr_reader :rebase_size
- # @return [Fixnum] the file offset to the binding information
- attr_reader :bind_off
+ # @return [Fixnum] the file offset to the binding information
+ attr_reader :bind_off
- # @return [Fixnum] the size of the binding information
- attr_reader :bind_size
+ # @return [Fixnum] the size of the binding information
+ attr_reader :bind_size
- # @return [Fixnum] the file offset to the weak binding information
- attr_reader :weak_bind_off
+ # @return [Fixnum] the file offset to the weak binding information
+ attr_reader :weak_bind_off
- # @return [Fixnum] the size of the weak binding information
- attr_reader :weak_bind_size
+ # @return [Fixnum] the size of the weak binding information
+ attr_reader :weak_bind_size
- # @return [Fixnum] the file offset to the lazy binding information
- attr_reader :lazy_bind_off
+ # @return [Fixnum] the file offset to the lazy binding information
+ attr_reader :lazy_bind_off
- # @return [Fixnum] the size of the lazy binding information
- attr_reader :lazy_bind_size
+ # @return [Fixnum] the size of the lazy binding information
+ attr_reader :lazy_bind_size
- # @return [Fixnum] the file offset to the export information
- attr_reader :export_off
+ # @return [Fixnum] the file offset to the export information
+ attr_reader :export_off
- # @return [Fixnum] the size of the export information
- attr_reader :export_size
+ # @return [Fixnum] the size of the export information
+ attr_reader :export_size
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=12".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=12".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 48
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 48
- # @api private
- def initialize(view, cmd, cmdsize, rebase_off, rebase_size, bind_off,
- bind_size, weak_bind_off, weak_bind_size, lazy_bind_off,
- lazy_bind_size, export_off, export_size)
- super(view, cmd, cmdsize)
- @rebase_off = rebase_off
- @rebase_size = rebase_size
- @bind_off = bind_off
- @bind_size = bind_size
- @weak_bind_off = weak_bind_off
- @weak_bind_size = weak_bind_size
- @lazy_bind_off = lazy_bind_off
- @lazy_bind_size = lazy_bind_size
- @export_off = export_off
- @export_size = export_size
+ # @api private
+ def initialize(view, cmd, cmdsize, rebase_off, rebase_size, bind_off,
+ bind_size, weak_bind_off, weak_bind_size, lazy_bind_off,
+ lazy_bind_size, export_off, export_size)
+ super(view, cmd, cmdsize)
+ @rebase_off = rebase_off
+ @rebase_size = rebase_size
+ @bind_off = bind_off
+ @bind_size = bind_size
+ @weak_bind_off = weak_bind_off
+ @weak_bind_size = weak_bind_size
+ @lazy_bind_off = lazy_bind_off
+ @lazy_bind_size = lazy_bind_size
+ @export_off = export_off
+ @export_size = export_size
+ end
end
- end
- # A load command containing linker options embedded in object files.
- # Corresponds to LC_LINKER_OPTION.
- class LinkerOptionCommand < LoadCommand
- # @return [Fixnum] the number of strings
- attr_reader :count
+ # A load command containing linker options embedded in object files.
+ # Corresponds to LC_LINKER_OPTION.
+ class LinkerOptionCommand < LoadCommand
+ # @return [Fixnum] the number of strings
+ attr_reader :count
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, count)
- super(view, cmd, cmdsize)
- @count = count
+ # @api private
+ def initialize(view, cmd, cmdsize, count)
+ super(view, cmd, cmdsize)
+ @count = count
+ end
end
- end
- # A load command specifying the offset of main(). Corresponds to LC_MAIN.
- class EntryPointCommand < LoadCommand
- # @return [Fixnum] the file (__TEXT) offset of main()
- attr_reader :entryoff
+ # A load command specifying the offset of main(). Corresponds to LC_MAIN.
+ class EntryPointCommand < LoadCommand
+ # @return [Fixnum] the file (__TEXT) offset of main()
+ attr_reader :entryoff
- # @return [Fixnum] if not 0, the initial stack size.
- attr_reader :stacksize
+ # @return [Fixnum] if not 0, the initial stack size.
+ attr_reader :stacksize
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2Q=2".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2Q=2".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 24
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 24
- # @api private
- def initialize(view, cmd, cmdsize, entryoff, stacksize)
- super(view, cmd, cmdsize)
- @entryoff = entryoff
- @stacksize = stacksize
+ # @api private
+ def initialize(view, cmd, cmdsize, entryoff, stacksize)
+ super(view, cmd, cmdsize)
+ @entryoff = entryoff
+ @stacksize = stacksize
+ end
end
- end
- # A load command specifying the version of the sources used to build the
- # binary. Corresponds to LC_SOURCE_VERSION.
- class SourceVersionCommand < LoadCommand
- # @return [Fixnum] the version packed as a24.b10.c10.d10.e10
- attr_reader :version
+ # A load command specifying the version of the sources used to build the
+ # binary. Corresponds to LC_SOURCE_VERSION.
+ class SourceVersionCommand < LoadCommand
+ # @return [Fixnum] the version packed as a24.b10.c10.d10.e10
+ attr_reader :version
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2Q=1".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2Q=1".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 16
- # @api private
- def initialize(view, cmd, cmdsize, version)
- super(view, cmd, cmdsize)
- @version = version
- end
+ # @api private
+ def initialize(view, cmd, cmdsize, version)
+ super(view, cmd, cmdsize)
+ @version = version
+ end
- # A string representation of the sources used to build the binary.
- # @return [String] a string representation of the version
- def version_string
- binary = "%064b" % version
- segs = [
- binary[0..23], binary[24..33], binary[34..43], binary[44..53],
- binary[54..63]
- ].map { |s| s.to_i(2) }
+ # A string representation of the sources used to build the binary.
+ # @return [String] a string representation of the version
+ def version_string
+ binary = "%064b" % version
+ segs = [
+ binary[0..23], binary[24..33], binary[34..43], binary[44..53],
+ binary[54..63]
+ ].map { |s| s.to_i(2) }
- segs.join(".")
+ segs.join(".")
+ end
end
- end
- # An obsolete load command containing the offset and size of the (GNU style)
- # symbol table information. Corresponds to LC_SYMSEG.
- class SymsegCommand < LoadCommand
- # @return [Fixnum] the offset to the symbol segment
- attr_reader :offset
+ # An obsolete load command containing the offset and size of the (GNU style)
+ # symbol table information. Corresponds to LC_SYMSEG.
+ class SymsegCommand < LoadCommand
+ # @return [Fixnum] the offset to the symbol segment
+ attr_reader :offset
- # @return [Fixnum] the size of the symbol segment in bytes
- attr_reader :size
+ # @return [Fixnum] the size of the symbol segment in bytes
+ attr_reader :size
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=4".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=4".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 16
- # @api private
- def initialize(view, cmd, cmdsize, offset, size)
- super(view, cmd, cmdsize)
- @offset = offset
- @size = size
+ # @api private
+ def initialize(view, cmd, cmdsize, offset, size)
+ super(view, cmd, cmdsize)
+ @offset = offset
+ @size = size
+ end
end
- end
- # An obsolete load command containing a free format string table. Each string
- # is null-terminated and the command is zero-padded to a multiple of 4.
- # Corresponds to LC_IDENT.
- class IdentCommand < LoadCommand
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2".freeze
+ # An obsolete load command containing a free format string table. Each
+ # string is null-terminated and the command is zero-padded to a multiple of
+ # 4. Corresponds to LC_IDENT.
+ class IdentCommand < LoadCommand
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 8
- end
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 8
+ end
- # An obsolete load command containing the path to a file to be loaded into
- # memory. Corresponds to LC_FVMFILE.
- class FvmfileCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the pathname of the file being loaded
- attr_reader :name
+ # An obsolete load command containing the path to a file to be loaded into
+ # memory. Corresponds to LC_FVMFILE.
+ class FvmfileCommand < LoadCommand
+ # @return [LCStr] the pathname of the file being loaded
+ attr_reader :name
- # @return [Fixnum] the virtual address being loaded at
- attr_reader :header_addr
+ # @return [Fixnum] the virtual address being loaded at
+ attr_reader :header_addr
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=4".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=4".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 16
- def initialize(view, cmd, cmdsize, name, header_addr)
- super(view, cmd, cmdsize)
- @name = LCStr.new(self, name)
- @header_addr = header_addr
+ def initialize(view, cmd, cmdsize, name, header_addr)
+ super(view, cmd, cmdsize)
+ @name = LCStr.new(self, name)
+ @header_addr = header_addr
+ end
end
- end
- # An obsolete load command containing the path to a library to be loaded into
- # memory. Corresponds to LC_LOADFVMLIB and LC_IDFVMLIB.
- class FvmlibCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the library's target pathname
- attr_reader :name
+ # An obsolete load command containing the path to a library to be loaded
+ # into memory. Corresponds to LC_LOADFVMLIB and LC_IDFVMLIB.
+ class FvmlibCommand < LoadCommand
+ # @return [LCStr] the library's target pathname
+ attr_reader :name
- # @return [Fixnum] the library's minor version number
- attr_reader :minor_version
+ # @return [Fixnum] the library's minor version number
+ attr_reader :minor_version
- # @return [Fixnum] the library's header address
- attr_reader :header_addr
+ # @return [Fixnum] the library's header address
+ attr_reader :header_addr
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=5".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=5".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 20
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 20
- def initialize(view, cmd, cmdsize, name, minor_version, header_addr)
- super(view, cmd, cmdsize)
- @name = LCStr.new(self, name)
- @minor_version = minor_version
- @header_addr = header_addr
+ def initialize(view, cmd, cmdsize, name, minor_version, header_addr)
+ super(view, cmd, cmdsize)
+ @name = LCStr.new(self, name)
+ @minor_version = minor_version
+ @header_addr = header_addr
+ end
end
end
end
diff --git a/Library/Homebrew/vendor/macho/macho/macho_file.rb b/Library/Homebrew/vendor/macho/macho/macho_file.rb
index 8ece62672..7693ab0dd 100644
--- a/Library/Homebrew/vendor/macho/macho/macho_file.rb
+++ b/Library/Homebrew/vendor/macho/macho/macho_file.rb
@@ -1,27 +1,33 @@
+require "forwardable"
+
module MachO
# Represents a Mach-O file, which contains a header and load commands
# as well as binary executable instructions. Mach-O binaries are
# architecture specific.
# @see https://en.wikipedia.org/wiki/Mach-O
- # @see MachO::FatFile
+ # @see FatFile
class MachOFile
- # @return [String] the filename loaded from, or nil if loaded from a binary string
+ extend Forwardable
+
+ # @return [String] the filename loaded from, or nil if loaded from a binary
+ # string
attr_accessor :filename
# @return [Symbol] the endianness of the file, :big or :little
attr_reader :endianness
- # @return [MachO::MachHeader] if the Mach-O is 32-bit
- # @return [MachO::MachHeader64] if the Mach-O is 64-bit
+ # @return [Headers::MachHeader] if the Mach-O is 32-bit
+ # @return [Headers::MachHeader64] if the Mach-O is 64-bit
attr_reader :header
- # @return [Array<MachO::LoadCommand>] an array of the file's load commands
+ # @return [Array<LoadCommands::LoadCommand>] an array of the file's load
+ # commands
# @note load commands are provided in order of ascending offset.
attr_reader :load_commands
# Creates a new MachOFile instance from a binary string.
# @param bin [String] a binary string containing raw Mach-O data
- # @return [MachO::MachOFile] a new MachOFile
+ # @return [MachOFile] a new MachOFile
def self.new_from_bin(bin)
instance = allocate
instance.initialize_from_bin(bin)
@@ -55,109 +61,63 @@ module MachO
@raw_data
end
- # @return [Boolean] true if the Mach-O has 32-bit magic, false otherwise
- def magic32?
- Utils.magic32?(header.magic)
- end
-
- # @return [Boolean] true if the Mach-O has 64-bit magic, false otherwise
- def magic64?
- Utils.magic64?(header.magic)
- end
-
- # @return [Fixnum] the file's internal alignment
- def alignment
- magic32? ? 4 : 8
- end
-
- # @return [Boolean] true if the file is of type `MH_OBJECT`, false otherwise
- def object?
- header.filetype == MH_OBJECT
- end
-
- # @return [Boolean] true if the file is of type `MH_EXECUTE`, false otherwise
- def executable?
- header.filetype == MH_EXECUTE
- end
-
- # @return [Boolean] true if the file is of type `MH_FVMLIB`, false otherwise
- def fvmlib?
- header.filetype == MH_FVMLIB
- end
-
- # @return [Boolean] true if the file is of type `MH_CORE`, false otherwise
- def core?
- header.filetype == MH_CORE
- end
-
- # @return [Boolean] true if the file is of type `MH_PRELOAD`, false otherwise
- def preload?
- header.filetype == MH_PRELOAD
- end
-
- # @return [Boolean] true if the file is of type `MH_DYLIB`, false otherwise
- def dylib?
- header.filetype == MH_DYLIB
- end
-
- # @return [Boolean] true if the file is of type `MH_DYLINKER`, false otherwise
- def dylinker?
- header.filetype == MH_DYLINKER
- end
-
- # @return [Boolean] true if the file is of type `MH_BUNDLE`, false otherwise
- def bundle?
- header.filetype == MH_BUNDLE
- end
-
- # @return [Boolean] true if the file is of type `MH_DSYM`, false otherwise
- def dsym?
- header.filetype == MH_DSYM
- end
-
- # @return [Boolean] true if the file is of type `MH_KEXT_BUNDLE`, false otherwise
- def kext?
- header.filetype == MH_KEXT_BUNDLE
- end
-
- # @return [Fixnum] the file's magic number
- def magic
- header.magic
- end
+ # @!method magic
+ # @return (see MachO::Headers::MachHeader#magic)
+ # @!method ncmds
+ # @return (see MachO::Headers::MachHeader#ncmds)
+ # @!method sizeofcmds
+ # @return (see MachO::Headers::MachHeader#sizeofcmds)
+ # @!method flags
+ # @return (see MachO::Headers::MachHeader#flags)
+ # @!method object?
+ # @return (see MachO::Headers::MachHeader#object?)
+ # @!method executable?
+ # @return (see MachO::Headers::MachHeader#executable?)
+ # @!method fvmlib?
+ # @return (see MachO::Headers::MachHeader#fvmlib?)
+ # @!method core?
+ # @return (see MachO::Headers::MachHeader#core?)
+ # @!method preload?
+ # @return (see MachO::Headers::MachHeader#preload?)
+ # @!method dylib?
+ # @return (see MachO::Headers::MachHeader#dylib?)
+ # @!method dylinker?
+ # @return (see MachO::Headers::MachHeader#dylinker?)
+ # @!method bundle?
+ # @return (see MachO::Headers::MachHeader#bundle?)
+ # @!method dsym?
+ # @return (see MachO::Headers::MachHeader#dsym?)
+ # @!method kext?
+ # @return (see MachO::Headers::MachHeader#kext?)
+ # @!method magic32?
+ # @return (see MachO::Headers::MachHeader#magic32?)
+ # @!method magic64?
+ # @return (see MachO::Headers::MachHeader#magic64?)
+ # @!method alignment
+ # @return (see MachO::Headers::MachHeader#alignment)
+ def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
+ :executable?, :fvmlib?, :core?, :preload?, :dylib?,
+ :dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
+ :alignment
# @return [String] a string representation of the file's magic number
def magic_string
- MH_MAGICS[magic]
+ Headers::MH_MAGICS[magic]
end
# @return [Symbol] a string representation of the Mach-O's filetype
def filetype
- MH_FILETYPES[header.filetype]
+ Headers::MH_FILETYPES[header.filetype]
end
# @return [Symbol] a symbol representation of the Mach-O's CPU type
def cputype
- CPU_TYPES[header.cputype]
+ Headers::CPU_TYPES[header.cputype]
end
# @return [Symbol] a symbol representation of the Mach-O's CPU subtype
def cpusubtype
- CPU_SUBTYPES[header.cputype][header.cpusubtype]
- end
-
- # @return [Fixnum] the number of load commands in the Mach-O's header
- def ncmds
- header.ncmds
- end
-
- # @return [Fixnum] the size of all load commands, in bytes
- def sizeofcmds
- header.sizeofcmds
- end
-
- # @return [Fixnum] execution flags set by the linker
- def flags
- header.flags
+ Headers::CPU_SUBTYPES[header.cputype][header.cpusubtype]
end
# All load commands of a given name.
@@ -165,7 +125,8 @@ module MachO
# file.command("LC_LOAD_DYLIB")
# file[:LC_LOAD_DYLIB]
# @param [String, Symbol] name the load command ID
- # @return [Array<MachO::LoadCommand>] an array of LoadCommands corresponding to `name`
+ # @return [Array<LoadCommands::LoadCommand>] an array of load commands
+ # corresponding to `name`
def command(name)
load_commands.select { |lc| lc.type == name.to_sym }
end
@@ -174,16 +135,16 @@ module MachO
# Inserts a load command at the given offset.
# @param offset [Fixnum] the offset to insert at
- # @param lc [MachO::LoadCommand] the load command to insert
+ # @param lc [LoadCommands::LoadCommand] the load command to insert
# @param options [Hash]
# @option options [Boolean] :repopulate (true) whether or not to repopulate
# the instance fields
- # @raise [MachO::OffsetInsertionError] if the offset is not in the load command region
- # @raise [MachO::HeaderPadError] if the new command exceeds the header pad buffer
+ # @raise [OffsetInsertionError] if the offset is not in the load command region
+ # @raise [HeaderPadError] if the new command exceeds the header pad buffer
# @note Calling this method with an arbitrary offset in the load command
# region **will leave the object in an inconsistent state**.
def insert_command(offset, lc, options = {})
- context = LoadCommand::SerializationContext.context_for(self)
+ context = LoadCommands::LoadCommand::SerializationContext.context_for(self)
cmd_raw = lc.serialize(context)
if offset < header.class.bytesize || offset + cmd_raw.bytesize > low_fileoff
@@ -207,14 +168,14 @@ module MachO
end
# Replace a load command with another command in the Mach-O, preserving location.
- # @param old_lc [MachO::LoadCommand] the load command being replaced
- # @param new_lc [MachO::LoadCommand] the load command being added
+ # @param old_lc [LoadCommands::LoadCommand] the load command being replaced
+ # @param new_lc [LoadCommands::LoadCommand] the load command being added
# @return [void]
- # @raise [MachO::HeaderPadError] if the new command exceeds the header pad buffer
- # @see {#insert_command}
+ # @raise [HeaderPadError] if the new command exceeds the header pad buffer
+ # @see #insert_command
# @note This is public, but methods like {#dylib_id=} should be preferred.
def replace_command(old_lc, new_lc)
- context = LoadCommand::SerializationContext.context_for(self)
+ context = LoadCommands::LoadCommand::SerializationContext.context_for(self)
cmd_raw = new_lc.serialize(context)
new_sizeofcmds = sizeofcmds + cmd_raw.bytesize - old_lc.cmdsize
if header.class.bytesize + new_sizeofcmds > low_fileoff
@@ -226,12 +187,12 @@ module MachO
end
# Appends a new load command to the Mach-O.
- # @param lc [MachO::LoadCommand] the load command being added
+ # @param lc [LoadCommands::LoadCommand] the load command being added
# @param options [Hash]
# @option options [Boolean] :repopulate (true) whether or not to repopulate
# the instance fields
# @return [void]
- # @see {#insert_command}
+ # @see #insert_command
# @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**
@@ -241,7 +202,7 @@ module MachO
end
# Delete a load command from the Mach-O.
- # @param lc [MachO::LoadCommand] the load command being deleted
+ # @param lc [LoadCommands::LoadCommand] the load command being deleted
# @param options [Hash]
# @option options [Boolean] :repopulate (true) whether or not to repopulate
# the instance fields
@@ -275,14 +236,14 @@ module MachO
end
# All load commands responsible for loading dylibs.
- # @return [Array<MachO::DylibCommand>] an array of DylibCommands
+ # @return [Array<LoadCommands::DylibCommand>] an array of DylibCommands
def dylib_load_commands
- load_commands.select { |lc| DYLIB_LOAD_COMMANDS.include?(lc.type) }
+ load_commands.select { |lc| LoadCommands::DYLIB_LOAD_COMMANDS.include?(lc.type) }
end
# All segment load commands in the Mach-O.
- # @return [Array<MachO::SegmentCommand>] if the Mach-O is 32-bit
- # @return [Array<MachO::SegmentCommand64>] if the Mach-O is 64-bit
+ # @return [Array<LoadCommands::SegmentCommand>] if the Mach-O is 32-bit
+ # @return [Array<LoadCommands::SegmentCommand64>] if the Mach-O is 64-bit
def segments
if magic32?
command(:LC_SEGMENT)
@@ -319,10 +280,10 @@ module MachO
old_lc = command(:LC_ID_DYLIB).first
raise DylibIdMissingError unless old_lc
- new_lc = LoadCommand.create(:LC_ID_DYLIB, new_id,
- old_lc.timestamp,
- old_lc.current_version,
- old_lc.compatibility_version)
+ 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
@@ -341,22 +302,22 @@ module MachO
# Changes the shared library `old_name` to `new_name`
# @example
- # file.change_install_name("/usr/lib/libWhatever.dylib", "/usr/local/lib/libWhatever2.dylib")
+ # file.change_install_name("abc.dylib", "def.dylib")
# @param old_name [String] the shared library's old name
# @param new_name [String] the shared library's new name
# @param _options [Hash]
# @return [void]
- # @raise [MachO::DylibUnknownError] if no shared library has the old name
+ # @raise [DylibUnknownError] if no shared library has the old name
# @note `_options` is currently unused and is provided for signature
# compatibility with {MachO::FatFile#change_install_name}
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 = LoadCommand.create(old_lc.type, new_name,
- old_lc.timestamp,
- old_lc.current_version,
- old_lc.compatibility_version)
+ 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
@@ -376,8 +337,8 @@ module MachO
# @param new_path [String] the new runtime path
# @param _options [Hash]
# @return [void]
- # @raise [MachO::RpathUnknownError] if no such old runtime path exists
- # @raise [MachO::RpathExistsError] if the new runtime path already exists
+ # @raise [RpathUnknownError] if no such old runtime path exists
+ # @raise [RpathExistsError] if the new runtime path already exists
# @note `_options` is currently unused and is provided for signature
# compatibility with {MachO::FatFile#change_rpath}
def change_rpath(old_path, new_path, _options = {})
@@ -385,7 +346,7 @@ module MachO
raise RpathUnknownError, old_path if old_lc.nil?
raise RpathExistsError, new_path if rpaths.include?(new_path)
- new_lc = LoadCommand.create(:LC_RPATH, new_path)
+ new_lc = LoadCommands::LoadCommand.create(:LC_RPATH, new_path)
delete_rpath(old_path)
insert_command(old_lc.view.offset, new_lc)
@@ -399,13 +360,13 @@ module MachO
# @param path [String] the new runtime path
# @param _options [Hash]
# @return [void]
- # @raise [MachO::RpathExistsError] if the runtime path already exists
+ # @raise [RpathExistsError] if the runtime path already exists
# @note `_options` is currently unused and is provided for signature
# compatibility with {MachO::FatFile#add_rpath}
def add_rpath(path, _options = {})
raise RpathExistsError, path if rpaths.include?(path)
- rpath_cmd = LoadCommand.create(:LC_RPATH, path)
+ rpath_cmd = LoadCommands::LoadCommand.create(:LC_RPATH, path)
add_command(rpath_cmd)
end
@@ -417,7 +378,7 @@ module MachO
# @param path [String] the runtime path to delete
# @param _options [Hash]
# @return void
- # @raise [MachO::RpathUnknownError] if no such runtime path exists
+ # @raise [RpathUnknownError] if no such runtime path exists
# @note `_options` is currently unused and is provided for signature
# compatibility with {MachO::FatFile#delete_rpath}
def delete_rpath(path, _options = {})
@@ -431,15 +392,6 @@ module MachO
populate_fields
end
- # All sections of the segment `segment`.
- # @param segment [MachO::SegmentCommand, MachO::SegmentCommand64] the segment being inspected
- # @return [Array<MachO::Section>] if the Mach-O is 32-bit
- # @return [Array<MachO::Section64>] if the Mach-O is 64-bit
- # @deprecated use {MachO::SegmentCommand#sections} instead
- def sections(segment)
- segment.sections
- end
-
# Write all Mach-O data to the given filename.
# @param filename [String] the file to write to
# @return [void]
@@ -449,7 +401,7 @@ module MachO
# Write all Mach-O data to the file used to initialize the instance.
# @return [void]
- # @raise [MachO::MachOError] if the instance was initialized without a file
+ # @raise [MachOError] if the instance was initialized without a file
# @note Overwrites all data in the file!
def write!
if @filename.nil?
@@ -462,16 +414,16 @@ module MachO
private
# The file's Mach-O header structure.
- # @return [MachO::MachHeader] if the Mach-O is 32-bit
- # @return [MachO::MachHeader64] if the Mach-O is 64-bit
- # @raise [MachO::TruncatedFileError] if the file is too small to have a valid header
+ # @return [Headers::MachHeader] if the Mach-O is 32-bit
+ # @return [Headers::MachHeader64] if the Mach-O is 64-bit
+ # @raise [TruncatedFileError] if the file is too small to have a valid header
# @api private
def populate_mach_header
# the smallest Mach-O header is 28 bytes
raise TruncatedFileError if @raw_data.size < 28
magic = populate_and_check_magic
- mh_klass = Utils.magic32?(magic) ? MachHeader : MachHeader64
+ mh_klass = Utils.magic32?(magic) ? Headers::MachHeader : Headers::MachHeader64
mh = mh_klass.new_from_bin(endianness, @raw_data[0, mh_klass.bytesize])
check_cputype(mh.cputype)
@@ -483,8 +435,8 @@ module MachO
# Read just the file's magic number and check its validity.
# @return [Fixnum] the magic
- # @raise [MachO::MagicError] if the magic is not valid Mach-O magic
- # @raise [MachO::FatBinaryError] if the magic is for a Fat file
+ # @raise [MagicError] if the magic is not valid Mach-O magic
+ # @raise [FatBinaryError] if the magic is for a Fat file
# @api private
def populate_and_check_magic
magic = @raw_data[0..3].unpack("N").first
@@ -499,32 +451,32 @@ module MachO
# Check the file's CPU type.
# @param cputype [Fixnum] the CPU type
- # @raise [MachO::CPUTypeError] if the CPU type is unknown
+ # @raise [CPUTypeError] if the CPU type is unknown
# @api private
def check_cputype(cputype)
- raise CPUTypeError, cputype unless CPU_TYPES.key?(cputype)
+ raise CPUTypeError, cputype unless Headers::CPU_TYPES.key?(cputype)
end
# Check the file's CPU type/subtype pair.
# @param cpusubtype [Fixnum] the CPU subtype
- # @raise [MachO::CPUSubtypeError] if the CPU sub-type is unknown
+ # @raise [CPUSubtypeError] if the CPU sub-type is unknown
# @api private
def check_cpusubtype(cputype, cpusubtype)
# Only check sub-type w/o capability bits (see `populate_mach_header`).
- raise CPUSubtypeError.new(cputype, cpusubtype) unless CPU_SUBTYPES[cputype].key?(cpusubtype)
+ raise CPUSubtypeError.new(cputype, cpusubtype) unless Headers::CPU_SUBTYPES[cputype].key?(cpusubtype)
end
# Check the file's type.
# @param filetype [Fixnum] the file type
- # @raise [MachO::FiletypeError] if the file type is unknown
+ # @raise [FiletypeError] if the file type is unknown
# @api private
def check_filetype(filetype)
- raise FiletypeError, filetype unless MH_FILETYPES.key?(filetype)
+ raise FiletypeError, filetype unless Headers::MH_FILETYPES.key?(filetype)
end
# All load commands in the file.
- # @return [Array<MachO::LoadCommand>] an array of load commands
- # @raise [MachO::LoadCommandError] if an unknown load command is encountered
+ # @return [Array<LoadCommands::LoadCommand>] an array of load commands
+ # @raise [LoadCommandError] if an unknown load command is encountered
# @api private
def populate_load_commands
offset = header.class.bytesize
@@ -533,13 +485,13 @@ module MachO
header.ncmds.times do
fmt = Utils.specialize_format("L=", endianness)
cmd = @raw_data.slice(offset, 4).unpack(fmt).first
- cmd_sym = LOAD_COMMANDS[cmd]
+ cmd_sym = LoadCommands::LOAD_COMMANDS[cmd]
raise LoadCommandError, cmd if cmd_sym.nil?
# why do I do this? i don't like declaring constants below
# classes, and i need them to resolve...
- klass = MachO.const_get LC_STRUCTURES[cmd_sym]
+ klass = LoadCommands.const_get LoadCommands::LC_STRUCTURES[cmd_sym]
view = MachOView.new(@raw_data, endianness, offset)
command = klass.new_from_bin(view)
diff --git a/Library/Homebrew/vendor/macho/macho/open.rb b/Library/Homebrew/vendor/macho/macho/open.rb
deleted file mode 100644
index 103f61741..000000000
--- a/Library/Homebrew/vendor/macho/macho/open.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module MachO
- # Opens the given filename as a MachOFile or FatFile, depending on its magic.
- # @param filename [String] the file being opened
- # @return [MachO::MachOFile] if the file is a Mach-O
- # @return [MachO::FatFile] if the file is a Fat file
- # @raise [ArgumentError] if the given file does not exist
- # @raise [MachO::TruncatedFileError] if the file is too small to have a valid header
- # @raise [MachO::MagicError] if the file's magic is not valid Mach-O magic
- def self.open(filename)
- raise ArgumentError, "#{filename}: no such file" unless File.file?(filename)
- raise TruncatedFileError unless File.stat(filename).size >= 4
-
- magic = File.open(filename, "rb") { |f| f.read(4) }.unpack("N").first
-
- if Utils.fat_magic?(magic)
- file = FatFile.new(filename)
- elsif Utils.magic?(magic)
- file = MachOFile.new(filename)
- else
- raise MagicError, magic
- end
-
- file
- end
-end
diff --git a/Library/Homebrew/vendor/macho/macho/sections.rb b/Library/Homebrew/vendor/macho/macho/sections.rb
index bd6218bb5..1e69e0b61 100644
--- a/Library/Homebrew/vendor/macho/macho/sections.rb
+++ b/Library/Homebrew/vendor/macho/macho/sections.rb
@@ -1,170 +1,176 @@
module MachO
- # type mask
- SECTION_TYPE = 0x000000ff
-
- # attributes mask
- SECTION_ATTRIBUTES = 0xffffff00
-
- # user settable attributes mask
- SECTION_ATTRIBUTES_USR = 0xff000000
-
- # system settable attributes mask
- SECTION_ATTRIBUTES_SYS = 0x00ffff00
-
- # association of section flag symbols to values
- # @api private
- SECTION_FLAGS = {
- :S_REGULAR => 0x0,
- :S_ZEROFILL => 0x1,
- :S_CSTRING_LITERALS => 0x2,
- :S_4BYTE_LITERALS => 0x3,
- :S_8BYTE_LITERALS => 0x4,
- :S_LITERAL_POINTERS => 0x5,
- :S_NON_LAZY_SYMBOL_POINTERS => 0x6,
- :S_LAZY_SYMBOL_POINTERS => 0x7,
- :S_SYMBOL_STUBS => 0x8,
- :S_MOD_INIT_FUNC_POINTERS => 0x9,
- :S_MOD_TERM_FUNC_POINTERS => 0xa,
- :S_COALESCED => 0xb,
- :S_GB_ZEROFILE => 0xc,
- :S_INTERPOSING => 0xd,
- :S_16BYTE_LITERALS => 0xe,
- :S_DTRACE_DOF => 0xf,
- :S_LAZY_DYLIB_SYMBOL_POINTERS => 0x10,
- :S_THREAD_LOCAL_REGULAR => 0x11,
- :S_THREAD_LOCAL_ZEROFILL => 0x12,
- :S_THREAD_LOCAL_VARIABLES => 0x13,
- :S_THREAD_LOCAL_VARIABLE_POINTERS => 0x14,
- :S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => 0x15,
- :S_ATTR_PURE_INSTRUCTIONS => 0x80000000,
- :S_ATTR_NO_TOC => 0x40000000,
- :S_ATTR_STRIP_STATIC_SYMS => 0x20000000,
- :S_ATTR_NO_DEAD_STRIP => 0x10000000,
- :S_ATTR_LIVE_SUPPORT => 0x08000000,
- :S_ATTR_SELF_MODIFYING_CODE => 0x04000000,
- :S_ATTR_DEBUG => 0x02000000,
- :S_ATTR_SOME_INSTRUCTIONS => 0x00000400,
- :S_ATTR_EXT_RELOC => 0x00000200,
- :S_ATTR_LOC_RELOC => 0x00000100,
- }.freeze
-
- # association of section name symbols to names
- # @api private
- SECTION_NAMES = {
- :SECT_TEXT => "__text",
- :SECT_FVMLIB_INIT0 => "__fvmlib_init0",
- :SECT_FVMLIB_INIT1 => "__fvmlib_init1",
- :SECT_DATA => "__data",
- :SECT_BSS => "__bss",
- :SECT_COMMON => "__common",
- :SECT_OBJC_SYMBOLS => "__symbol_table",
- :SECT_OBJC_MODULES => "__module_info",
- :SECT_OBJC_STRINGS => "__selector_strs",
- :SECT_OBJC_REFS => "__selector_refs",
- :SECT_ICON_HEADER => "__header",
- :SECT_ICON_TIFF => "__tiff",
- }.freeze
-
- # Represents a section of a segment for 32-bit architectures.
- class Section < MachOStructure
- # @return [String] the name of the section, including null pad bytes
- attr_reader :sectname
-
- # @return [String] the name of the segment's section, including null pad bytes
- attr_reader :segname
-
- # @return [Fixnum] the memory address of the section
- attr_reader :addr
-
- # @return [Fixnum] the size, in bytes, of the section
- attr_reader :size
-
- # @return [Fixnum] the file offset of the section
- attr_reader :offset
-
- # @return [Fixnum] the section alignment (power of 2) of the section
- attr_reader :align
-
- # @return [Fixnum] the file offset of the section's relocation entries
- attr_reader :reloff
-
- # @return [Fixnum] the number of relocation entries
- attr_reader :nreloc
-
- # @return [Fixnum] flags for type and attributes of the section
- attr_reader :flags
-
- # @return [void] reserved (for offset or index)
- attr_reader :reserved1
-
- # @return [void] reserved (for count or sizeof)
- attr_reader :reserved2
-
- # @see MachOStructure::FORMAT
- FORMAT = "a16a16L=9".freeze
-
- # @see MachOStructure::SIZEOF
- SIZEOF = 68
+ # Classes and constants for parsing sections in Mach-O binaries.
+ module Sections
+ # type mask
+ SECTION_TYPE = 0x000000ff
- # @api private
- def initialize(sectname, segname, addr, size, offset, align, reloff,
- nreloc, flags, reserved1, reserved2)
- @sectname = sectname
- @segname = segname
- @addr = addr
- @size = size
- @offset = offset
- @align = align
- @reloff = reloff
- @nreloc = nreloc
- @flags = flags
- @reserved1 = reserved1
- @reserved2 = reserved2
- end
+ # attributes mask
+ SECTION_ATTRIBUTES = 0xffffff00
- # @return [String] the section's name, with any trailing NULL characters removed
- def section_name
- sectname.delete("\x00")
- end
-
- # @return [String] the parent segment's name, with any trailing NULL characters removed
- def segment_name
- segname.delete("\x00")
- end
+ # user settable attributes mask
+ SECTION_ATTRIBUTES_USR = 0xff000000
- # @return [Boolean] true if the section has no contents (i.e, `size` is 0)
- def empty?
- size.zero?
- end
+ # system settable attributes mask
+ SECTION_ATTRIBUTES_SYS = 0x00ffff00
- # @example
- # puts "this section is regular" if sect.flag?(:S_REGULAR)
- # @param flag [Symbol] a section flag symbol
- # @return [Boolean] true if `flag` is present in the section's flag field
- def flag?(flag)
- flag = SECTION_FLAGS[flag]
- return false if flag.nil?
- flags & flag == flag
+ # association of section flag symbols to values
+ # @api private
+ SECTION_FLAGS = {
+ :S_REGULAR => 0x0,
+ :S_ZEROFILL => 0x1,
+ :S_CSTRING_LITERALS => 0x2,
+ :S_4BYTE_LITERALS => 0x3,
+ :S_8BYTE_LITERALS => 0x4,
+ :S_LITERAL_POINTERS => 0x5,
+ :S_NON_LAZY_SYMBOL_POINTERS => 0x6,
+ :S_LAZY_SYMBOL_POINTERS => 0x7,
+ :S_SYMBOL_STUBS => 0x8,
+ :S_MOD_INIT_FUNC_POINTERS => 0x9,
+ :S_MOD_TERM_FUNC_POINTERS => 0xa,
+ :S_COALESCED => 0xb,
+ :S_GB_ZEROFILE => 0xc,
+ :S_INTERPOSING => 0xd,
+ :S_16BYTE_LITERALS => 0xe,
+ :S_DTRACE_DOF => 0xf,
+ :S_LAZY_DYLIB_SYMBOL_POINTERS => 0x10,
+ :S_THREAD_LOCAL_REGULAR => 0x11,
+ :S_THREAD_LOCAL_ZEROFILL => 0x12,
+ :S_THREAD_LOCAL_VARIABLES => 0x13,
+ :S_THREAD_LOCAL_VARIABLE_POINTERS => 0x14,
+ :S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => 0x15,
+ :S_ATTR_PURE_INSTRUCTIONS => 0x80000000,
+ :S_ATTR_NO_TOC => 0x40000000,
+ :S_ATTR_STRIP_STATIC_SYMS => 0x20000000,
+ :S_ATTR_NO_DEAD_STRIP => 0x10000000,
+ :S_ATTR_LIVE_SUPPORT => 0x08000000,
+ :S_ATTR_SELF_MODIFYING_CODE => 0x04000000,
+ :S_ATTR_DEBUG => 0x02000000,
+ :S_ATTR_SOME_INSTRUCTIONS => 0x00000400,
+ :S_ATTR_EXT_RELOC => 0x00000200,
+ :S_ATTR_LOC_RELOC => 0x00000100,
+ }.freeze
+
+ # association of section name symbols to names
+ # @api private
+ SECTION_NAMES = {
+ :SECT_TEXT => "__text",
+ :SECT_FVMLIB_INIT0 => "__fvmlib_init0",
+ :SECT_FVMLIB_INIT1 => "__fvmlib_init1",
+ :SECT_DATA => "__data",
+ :SECT_BSS => "__bss",
+ :SECT_COMMON => "__common",
+ :SECT_OBJC_SYMBOLS => "__symbol_table",
+ :SECT_OBJC_MODULES => "__module_info",
+ :SECT_OBJC_STRINGS => "__selector_strs",
+ :SECT_OBJC_REFS => "__selector_refs",
+ :SECT_ICON_HEADER => "__header",
+ :SECT_ICON_TIFF => "__tiff",
+ }.freeze
+
+ # Represents a section of a segment for 32-bit architectures.
+ class Section < MachOStructure
+ # @return [String] the name of the section, including null pad bytes
+ attr_reader :sectname
+
+ # @return [String] the name of the segment's section, including null
+ # pad bytes
+ attr_reader :segname
+
+ # @return [Fixnum] the memory address of the section
+ attr_reader :addr
+
+ # @return [Fixnum] the size, in bytes, of the section
+ attr_reader :size
+
+ # @return [Fixnum] the file offset of the section
+ attr_reader :offset
+
+ # @return [Fixnum] the section alignment (power of 2) of the section
+ attr_reader :align
+
+ # @return [Fixnum] the file offset of the section's relocation entries
+ attr_reader :reloff
+
+ # @return [Fixnum] the number of relocation entries
+ attr_reader :nreloc
+
+ # @return [Fixnum] flags for type and attributes of the section
+ attr_reader :flags
+
+ # @return [void] reserved (for offset or index)
+ attr_reader :reserved1
+
+ # @return [void] reserved (for count or sizeof)
+ attr_reader :reserved2
+
+ # @see MachOStructure::FORMAT
+ FORMAT = "a16a16L=9".freeze
+
+ # @see MachOStructure::SIZEOF
+ SIZEOF = 68
+
+ # @api private
+ def initialize(sectname, segname, addr, size, offset, align, reloff,
+ nreloc, flags, reserved1, reserved2)
+ @sectname = sectname
+ @segname = segname
+ @addr = addr
+ @size = size
+ @offset = offset
+ @align = align
+ @reloff = reloff
+ @nreloc = nreloc
+ @flags = flags
+ @reserved1 = reserved1
+ @reserved2 = reserved2
+ end
+
+ # @return [String] the section's name, with any trailing NULL characters
+ # removed
+ def section_name
+ sectname.delete("\x00")
+ end
+
+ # @return [String] the parent segment's name, with any trailing NULL
+ # characters removed
+ def segment_name
+ segname.delete("\x00")
+ end
+
+ # @return [Boolean] whether the section is empty (i.e, {size} is 0)
+ def empty?
+ size.zero?
+ end
+
+ # @example
+ # puts "this section is regular" if sect.flag?(:S_REGULAR)
+ # @param flag [Symbol] a section flag symbol
+ # @return [Boolean] whether the flag is present in the section's {flags}
+ def flag?(flag)
+ flag = SECTION_FLAGS[flag]
+ return false if flag.nil?
+ flags & flag == flag
+ end
end
- end
- # Represents a section of a segment for 64-bit architectures.
- class Section64 < Section
- # @return [void] reserved
- attr_reader :reserved3
+ # Represents a section of a segment for 64-bit architectures.
+ class Section64 < Section
+ # @return [void] reserved
+ attr_reader :reserved3
- # @see MachOStructure::FORMAT
- FORMAT = "a16a16Q=2L=8".freeze
+ # @see MachOStructure::FORMAT
+ FORMAT = "a16a16Q=2L=8".freeze
- # @see MachOStructure::SIZEOF
- SIZEOF = 80
+ # @see MachOStructure::SIZEOF
+ SIZEOF = 80
- # @api private
- def initialize(sectname, segname, addr, size, offset, align, reloff,
- nreloc, flags, reserved1, reserved2, reserved3)
- super(sectname, segname, addr, size, offset, align, reloff,
- nreloc, flags, reserved1, reserved2)
- @reserved3 = reserved3
+ # @api private
+ def initialize(sectname, segname, addr, size, offset, align, reloff,
+ nreloc, flags, reserved1, reserved2, reserved3)
+ super(sectname, segname, addr, size, offset, align, reloff,
+ nreloc, flags, reserved1, reserved2)
+ @reserved3 = reserved3
+ end
end
end
end
diff --git a/Library/Homebrew/vendor/macho/macho/structure.rb b/Library/Homebrew/vendor/macho/macho/structure.rb
index 43f7bc84e..bac5342d4 100644
--- a/Library/Homebrew/vendor/macho/macho/structure.rb
+++ b/Library/Homebrew/vendor/macho/macho/structure.rb
@@ -19,7 +19,7 @@ module MachO
# @param endianness [Symbol] either `:big` or `:little`
# @param bin [String] the string to be unpacked into the new structure
- # @return [MachO::MachOStructure] a new MachOStructure initialized with `bin`
+ # @return [MachO::MachOStructure] the resulting structure
# @api private
def self.new_from_bin(endianness, bin)
format = Utils.specialize_format(self::FORMAT, endianness)
diff --git a/Library/Homebrew/vendor/macho/macho/tools.rb b/Library/Homebrew/vendor/macho/macho/tools.rb
index f34d75dc1..b49626d9d 100644
--- a/Library/Homebrew/vendor/macho/macho/tools.rb
+++ b/Library/Homebrew/vendor/macho/macho/tools.rb
@@ -1,5 +1,6 @@
module MachO
- # A collection of convenient methods for common operations on Mach-O and Fat binaries.
+ # A collection of convenient methods for common operations on Mach-O and Fat
+ # binaries.
module Tools
# @param filename [String] the Mach-O or Fat binary being read
# @return [Array<String>] an array of all dylibs linked to the binary
@@ -9,7 +10,8 @@ module MachO
file.linked_dylibs
end
- # Changes the dylib ID of a Mach-O or Fat binary, overwriting the source file.
+ # Changes the dylib ID of a Mach-O or Fat binary, overwriting the source
+ # file.
# @param filename [String] the Mach-O or Fat binary being modified
# @param new_id [String] the new dylib ID for the binary
# @param options [Hash]
@@ -23,7 +25,8 @@ module MachO
file.write!
end
- # Changes a shared library install name in a Mach-O or Fat binary, overwriting the source file.
+ # Changes a shared library install name in a Mach-O or Fat binary,
+ # overwriting the source file.
# @param filename [String] the Mach-O or Fat binary being modified
# @param old_name [String] the old shared library name
# @param new_name [String] the new shared library name
@@ -38,7 +41,8 @@ module MachO
file.write!
end
- # Changes a runtime path in a Mach-O or Fat binary, overwriting the source file.
+ # Changes a runtime path in a Mach-O or Fat binary, overwriting the source
+ # file.
# @param filename [String] the Mach-O or Fat binary being modified
# @param old_path [String] the old runtime path
# @param new_path [String] the new runtime path
@@ -67,7 +71,8 @@ module MachO
file.write!
end
- # Delete a runtime path from a Mach-O or Fat binary, overwriting the source file.
+ # Delete a runtime path from a Mach-O or Fat binary, overwriting the source
+ # file.
# @param filename [String] the Mach-O or Fat binary being modified
# @param old_path [String] the old runtime path
# @param options [Hash]
@@ -80,5 +85,24 @@ module MachO
file.delete_rpath(old_path, options)
file.write!
end
+
+ # Merge multiple Mach-Os into one universal (Fat) binary.
+ # @param filename [String] the fat binary to create
+ # @param files [Array<MachO::MachOFile, MachO::FatFile>] the files to merge
+ # @return [void]
+ def self.merge_machos(filename, *files)
+ machos = files.map do |file|
+ macho = MachO.open(file)
+ case macho
+ when MachO::MachOFile
+ macho
+ else
+ macho.machos
+ end
+ end.flatten
+
+ fat_macho = MachO::FatFile.new_from_machos(*machos)
+ fat_macho.write(filename)
+ end
end
end
diff --git a/Library/Homebrew/vendor/macho/macho/utils.rb b/Library/Homebrew/vendor/macho/macho/utils.rb
index cedd0bc1c..ecfc8390b 100644
--- a/Library/Homebrew/vendor/macho/macho/utils.rb
+++ b/Library/Homebrew/vendor/macho/macho/utils.rb
@@ -5,7 +5,7 @@ module MachO
# @param value [Fixnum] the number being rounded
# @param round [Fixnum] the number being rounded with
# @return [Fixnum] the rounded value
- # @see https://www.opensource.apple.com/source/cctools/cctools-870/libstuff/rnd.c
+ # @see http://www.opensource.apple.com/source/cctools/cctools-870/libstuff/rnd.c
def self.round(value, round)
round -= 1
value += round
@@ -13,7 +13,8 @@ module MachO
value
end
- # Returns the number of bytes needed to pad the given size to the given alignment.
+ # Returns the number of bytes needed to pad the given size to the given
+ # alignment.
# @param size [Fixnum] the unpadded size
# @param alignment [Fixnum] the number to alignment the size with
# @return [Fixnum] the number of pad bytes required
@@ -21,7 +22,8 @@ module MachO
round(size, alignment) - size
end
- # Converts an abstract (native-endian) String#unpack format to big or little.
+ # Converts an abstract (native-endian) String#unpack format to big or
+ # little.
# @param format [String] the format string being converted
# @param endianness [Symbol] either `:big` or `:little`
# @return [String] the converted string
@@ -31,7 +33,8 @@ module MachO
end
# Packs tagged strings into an aligned payload.
- # @param fixed_offset [Fixnum] the baseline offset for the first packed string
+ # @param fixed_offset [Fixnum] the baseline offset for the first packed
+ # string
# @param alignment [Fixnum] the alignment value to use for packing
# @param strings [Hash] the labeled strings to pack
# @return [Array<String, Hash>] the packed string and labeled offsets
@@ -53,44 +56,44 @@ module MachO
# Compares the given number to valid Mach-O magic numbers.
# @param num [Fixnum] the number being checked
- # @return [Boolean] true if `num` is a valid Mach-O magic number, false otherwise
+ # @return [Boolean] whether `num` is a valid Mach-O magic number
def self.magic?(num)
- MH_MAGICS.key?(num)
+ Headers::MH_MAGICS.key?(num)
end
# Compares the given number to valid Fat magic numbers.
# @param num [Fixnum] the number being checked
- # @return [Boolean] true if `num` is a valid Fat magic number, false otherwise
+ # @return [Boolean] whether `num` is a valid Fat magic number
def self.fat_magic?(num)
- num == FAT_MAGIC
+ num == Headers::FAT_MAGIC
end
# Compares the given number to valid 32-bit Mach-O magic numbers.
# @param num [Fixnum] the number being checked
- # @return [Boolean] true if `num` is a valid 32-bit magic number, false otherwise
+ # @return [Boolean] whether `num` is a valid 32-bit magic number
def self.magic32?(num)
- num == MH_MAGIC || num == MH_CIGAM
+ num == Headers::MH_MAGIC || num == Headers::MH_CIGAM
end
# Compares the given number to valid 64-bit Mach-O magic numbers.
# @param num [Fixnum] the number being checked
- # @return [Boolean] true if `num` is a valid 64-bit magic number, false otherwise
+ # @return [Boolean] whether `num` is a valid 64-bit magic number
def self.magic64?(num)
- num == MH_MAGIC_64 || num == MH_CIGAM_64
+ num == Headers::MH_MAGIC_64 || num == Headers::MH_CIGAM_64
end
# Compares the given number to valid little-endian magic numbers.
# @param num [Fixnum] the number being checked
- # @return [Boolean] true if `num` is a valid little-endian magic number, false otherwise
+ # @return [Boolean] whether `num` is a valid little-endian magic number
def self.little_magic?(num)
- num == MH_CIGAM || num == MH_CIGAM_64
+ num == Headers::MH_CIGAM || num == Headers::MH_CIGAM_64
end
# Compares the given number to valid big-endian magic numbers.
# @param num [Fixnum] the number being checked
- # @return [Boolean] true if `num` is a valid big-endian magic number, false otherwise
+ # @return [Boolean] whether `num` is a valid big-endian magic number
def self.big_magic?(num)
- num == MH_CIGAM || num == MH_CIGAM_64
+ num == Headers::MH_CIGAM || num == Headers::MH_CIGAM_64
end
end
end