ruby-macho 0.0.9 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/macho.rb +1 -0
- data/lib/macho/exceptions.rb +17 -10
- data/lib/macho/fat_file.rb +2 -1
- data/lib/macho/headers.rb +132 -28
- data/lib/macho/load_commands.rb +313 -21
- data/lib/macho/macho_file.rb +40 -0
- data/lib/macho/sections.rb +16 -0
- data/lib/macho/structure.rb +5 -2
- data/lib/macho/utils.rb +12 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2197be0a734893a06de0c2a50c78a125e1e0f7b
|
4
|
+
data.tar.gz: 6333cb31cc35794f81b35c1e5f5a3e5d8f63d509
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2965997a877ab4c4d675f7e51b8b8ddb7fa82dda776e6b2fe5bb10bcfbf27845809723dc072257076a87c351fe03321839d669dd517ec36e0f57453a7831bef5
|
7
|
+
data.tar.gz: 326050eb144d5e9c415dcf58d10fb3da1c565044fae5bb3d1482fe9f15124c64490f95b2e595748b8f567e69db1cc8e5797cf0917c855150ae034bb9094b456c
|
data/lib/macho.rb
CHANGED
@@ -9,6 +9,7 @@ require "#{File.dirname(__FILE__)}/macho/exceptions"
|
|
9
9
|
require "#{File.dirname(__FILE__)}/macho/utils"
|
10
10
|
require "#{File.dirname(__FILE__)}/macho/tools"
|
11
11
|
|
12
|
+
# The primary namespace for ruby-macho.
|
12
13
|
module MachO
|
13
14
|
# Opens the given filename as a MachOFile or FatFile, depending on its magic.
|
14
15
|
# @param filename [String] the file being opened
|
data/lib/macho/exceptions.rb
CHANGED
@@ -1,59 +1,65 @@
|
|
1
1
|
module MachO
|
2
|
-
# generic
|
2
|
+
# A generic Mach-O error in execution.
|
3
3
|
class MachOError < RuntimeError
|
4
4
|
end
|
5
5
|
|
6
|
-
#
|
6
|
+
# Raised when a file's magic bytes are not valid Mach-O magic.
|
7
7
|
class MagicError < MachOError
|
8
|
+
# @param num [Fixnum] the unknown number
|
8
9
|
def initialize(num)
|
9
10
|
super "Unrecognized Mach-O magic: 0x#{"%02x" % num}"
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
13
|
-
#
|
14
|
+
# Raised when a fat binary is loaded with MachOFile.
|
14
15
|
class FatBinaryError < MachOError
|
15
16
|
def initialize
|
16
17
|
super "Fat binaries must be loaded with MachO::FatFile"
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
|
-
#
|
21
|
+
# Raised when a Mach-O is loaded with FatFile.
|
21
22
|
class MachOBinaryError < MachOError
|
22
23
|
def initialize
|
23
24
|
super "Normal binaries must be loaded with MachO::MachOFile"
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
|
-
#
|
28
|
+
# Raised when the CPU type is unknown.
|
28
29
|
class CPUTypeError < MachOError
|
30
|
+
# @param num [Fixnum] the unknown number
|
29
31
|
def initialize(num)
|
30
32
|
super "Unrecognized CPU type: 0x#{"%02x" % num}"
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
#
|
36
|
+
# Raised when the CPU subtype is unknown.
|
35
37
|
class CPUSubtypeError < MachOError
|
38
|
+
# @param num [Fixnum] the unknown number
|
36
39
|
def initialize(num)
|
37
40
|
super "Unrecognized CPU sub-type: 0x#{"%02x" % num}"
|
38
41
|
end
|
39
42
|
end
|
40
43
|
|
41
|
-
#
|
44
|
+
# Raised when a mach-o file's filetype field is unknown.
|
42
45
|
class FiletypeError < MachOError
|
46
|
+
# @param num [Fixnum] the unknown number
|
43
47
|
def initialize(num)
|
44
48
|
super "Unrecognized Mach-O filetype code: 0x#{"%02x" % num}"
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
48
|
-
#
|
52
|
+
# Raised when an unknown load command is encountered.
|
49
53
|
class LoadCommandError < MachOError
|
54
|
+
# @param num [Fixnum] the unknown number
|
50
55
|
def initialize(num)
|
51
56
|
super "Unrecognized Mach-O load command: 0x#{"%02x" % num}"
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
55
|
-
#
|
60
|
+
# Raised when load commands are too large to fit in the current file.
|
56
61
|
class HeaderPadError < MachOError
|
62
|
+
# @param filename [String] the filename
|
57
63
|
def initialize(filename)
|
58
64
|
super "Updated load commands do not fit in the header of " +
|
59
65
|
"#{filename}. #{filename} needs to be relinked, possibly with " +
|
@@ -61,8 +67,9 @@ module MachO
|
|
61
67
|
end
|
62
68
|
end
|
63
69
|
|
64
|
-
#
|
70
|
+
# Raised when attempting to change a dylib name that doesn't exist.
|
65
71
|
class DylibUnknownError < MachOError
|
72
|
+
# @param dylib [String] the unknown shared library name
|
66
73
|
def initialize(dylib)
|
67
74
|
super "No such dylib name: #{dylib}"
|
68
75
|
end
|
data/lib/macho/fat_file.rb
CHANGED
@@ -105,7 +105,7 @@ module MachO
|
|
105
105
|
end
|
106
106
|
|
107
107
|
# Write all (fat) data to the file used to initialize the instance.
|
108
|
-
#
|
108
|
+
# @note Overwrites all data in the file!
|
109
109
|
def write!
|
110
110
|
File.open(@filename, "wb") { |f| f.write(@raw_data) }
|
111
111
|
end
|
@@ -158,6 +158,7 @@ module MachO
|
|
158
158
|
|
159
159
|
# @todo this needs to be redesigned. arch[:offset] and arch[:size] are
|
160
160
|
# already out-of-date, and the header needs to be synchronized as well.
|
161
|
+
# @private
|
161
162
|
def synchronize_raw_data
|
162
163
|
machos.each_with_index do |macho, i|
|
163
164
|
arch = fat_archs[i]
|
data/lib/macho/headers.rb
CHANGED
@@ -1,12 +1,23 @@
|
|
1
1
|
module MachO
|
2
|
-
#
|
3
|
-
FAT_MAGIC = 0xcafebabe
|
4
|
-
FAT_CIGAM = 0xbebafeca # little-endian fat magic
|
5
|
-
MH_MAGIC = 0xfeedface # 32-bit big-endian magic
|
6
|
-
MH_CIGAM = 0xcefaedfe # 32-bit little-endian magic
|
7
|
-
MH_MAGIC_64 = 0xfeedfacf # 64-bit big-endian magic
|
8
|
-
MH_CIGAM_64 = 0xcffaedfe # 64-bit little-endian magic
|
2
|
+
# big-endian fat magic
|
3
|
+
FAT_MAGIC = 0xcafebabe
|
9
4
|
|
5
|
+
# little-endian fat magic
|
6
|
+
FAT_CIGAM = 0xbebafeca
|
7
|
+
|
8
|
+
# 32-bit big-endian magic
|
9
|
+
MH_MAGIC = 0xfeedface
|
10
|
+
|
11
|
+
# 32-bit little-endian magic
|
12
|
+
MH_CIGAM = 0xcefaedfe
|
13
|
+
|
14
|
+
# 64-bit big-endian magic
|
15
|
+
MH_MAGIC_64 = 0xfeedfacf
|
16
|
+
|
17
|
+
# 64-bit little-endian magic
|
18
|
+
MH_CIGAM_64 = 0xcffaedfe
|
19
|
+
|
20
|
+
# association of magic numbers to string representations
|
10
21
|
MH_MAGICS = {
|
11
22
|
FAT_MAGIC => "FAT_MAGIC",
|
12
23
|
FAT_CIGAM => "FAT_CIGAM",
|
@@ -16,18 +27,28 @@ module MachO
|
|
16
27
|
MH_CIGAM_64 => "MH_CIGAM_64"
|
17
28
|
}
|
18
29
|
|
19
|
-
#
|
20
|
-
CPU_ARCH_MASK = 0xff000000
|
30
|
+
# mask for CPUs with 64-bit architectures (when running a 64-bit ABI?)
|
21
31
|
CPU_ARCH_ABI64 = 0x01000000
|
22
32
|
|
23
|
-
# (
|
33
|
+
# any CPU (unused?)
|
24
34
|
CPU_TYPE_ANY = -1
|
35
|
+
|
36
|
+
# x86 compatible CPUs
|
25
37
|
CPU_TYPE_X86 = 0x07
|
38
|
+
|
39
|
+
# i386 and later compatible CPUs
|
26
40
|
CPU_TYPE_I386 = CPU_TYPE_X86
|
41
|
+
|
42
|
+
# x86_64 (AMD64) compatible CPUs
|
27
43
|
CPU_TYPE_X86_64 = (CPU_TYPE_X86 | CPU_ARCH_ABI64)
|
44
|
+
|
45
|
+
# PowerPC compatible CPUs (7400 series?)
|
28
46
|
CPU_TYPE_POWERPC = 0x24
|
47
|
+
|
48
|
+
# PowerPC64 compatible CPUs (970 series?)
|
29
49
|
CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
|
30
50
|
|
51
|
+
# association of cpu types to string representations
|
31
52
|
CPU_TYPES = {
|
32
53
|
CPU_TYPE_ANY => "CPU_TYPE_ANY",
|
33
54
|
CPU_TYPE_X86 => "CPU_TYPE_X86",
|
@@ -37,34 +58,59 @@ module MachO
|
|
37
58
|
CPU_TYPE_POWERPC64 => "CPU_TYPE_POWERPC64"
|
38
59
|
}
|
39
60
|
|
40
|
-
#
|
41
|
-
# http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
|
61
|
+
# mask for CPU subtype capabilities
|
42
62
|
CPU_SUBTYPE_MASK = 0xff000000
|
63
|
+
|
64
|
+
# 64-bit libraries (undocumented!)
|
65
|
+
# @see http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
|
43
66
|
CPU_SUBTYPE_LIB64 = 0x80000000
|
44
67
|
|
45
|
-
#
|
68
|
+
# all x86-type CPUs
|
46
69
|
CPU_SUBTYPE_X86_ALL = 3
|
70
|
+
|
71
|
+
# all x86-type CPUs (what makes this different from CPU_SUBTYPE_X86_ALL?)
|
47
72
|
CPU_SUBTYPE_X86_ARCH1 = 4
|
48
73
|
|
74
|
+
# association of cpu subtypes to string representations
|
49
75
|
CPU_SUBTYPES = {
|
50
76
|
CPU_SUBTYPE_X86_ALL => "CPU_SUBTYPE_X86_ALL",
|
51
77
|
CPU_SUBTYPE_X86_ARCH1 => "CPU_SUBTYPE_X86_ARCH1"
|
52
78
|
}
|
53
79
|
|
54
|
-
#
|
55
|
-
MH_OBJECT = 0x1
|
56
|
-
MH_EXECUTE = 0x2 # demand paged executable file
|
57
|
-
MH_FVMLIB = 0x3 # fixed VM shared library file
|
58
|
-
MH_CORE = 0x4 # core file
|
59
|
-
MH_PRELOAD = 0x5 # preloaded executable file
|
60
|
-
MH_DYLIB = 0x6 # dynamically bound shared library
|
61
|
-
MH_DYLINKER = 0x7 # dynamic link editor
|
62
|
-
MH_BUNDLE = 0x8 # dynamically bound bundle file
|
63
|
-
MH_DYLIB_STUB = 0x9 # shared library stub for static linking only no,
|
64
|
-
# section contents
|
65
|
-
MH_DSYM = 0xa # companion file with only debug sections
|
66
|
-
MH_KEXT_BUNDLE = 0xb # x86_64 lexts
|
80
|
+
# relocatable object file
|
81
|
+
MH_OBJECT = 0x1
|
67
82
|
|
83
|
+
# demand paged executable file
|
84
|
+
MH_EXECUTE = 0x2
|
85
|
+
|
86
|
+
# fixed VM shared library file
|
87
|
+
MH_FVMLIB = 0x3
|
88
|
+
|
89
|
+
# core dump file
|
90
|
+
MH_CORE = 0x4
|
91
|
+
|
92
|
+
# preloaded executable file
|
93
|
+
MH_PRELOAD = 0x5
|
94
|
+
|
95
|
+
# dynamically bound shared library
|
96
|
+
MH_DYLIB = 0x6
|
97
|
+
|
98
|
+
# dynamic link editor
|
99
|
+
MH_DYLINKER = 0x7
|
100
|
+
|
101
|
+
# dynamically bound bundle file
|
102
|
+
MH_BUNDLE = 0x8
|
103
|
+
|
104
|
+
# shared library stub for static linking only, no section contents
|
105
|
+
MH_DYLIB_STUB = 0x9
|
106
|
+
|
107
|
+
# companion file with only debug sections
|
108
|
+
MH_DSYM = 0xa
|
109
|
+
|
110
|
+
# x86_64 kexts
|
111
|
+
MH_KEXT_BUNDLE = 0xb
|
112
|
+
|
113
|
+
# association of filetypes to string representations
|
68
114
|
MH_FILETYPES = {
|
69
115
|
MH_OBJECT => "MH_OBJECT",
|
70
116
|
MH_EXECUTE => "MH_EXECUTE",
|
@@ -79,34 +125,85 @@ module MachO
|
|
79
125
|
MH_KEXT_BUNDLE => "MH_KEXT_BUNDLE"
|
80
126
|
}
|
81
127
|
|
82
|
-
#
|
128
|
+
# the object file has no undefined references (flag)
|
83
129
|
MH_NOUNDEFS = 0x1
|
130
|
+
|
131
|
+
# the object file is the output of an incremental link against a base file (flag)
|
84
132
|
MH_INCRLINK = 0x2
|
133
|
+
|
134
|
+
# the object file is input for the dynamic linker and can't be staticly link edited again (flag)
|
85
135
|
MH_DYLDLINK = 0x4
|
136
|
+
|
137
|
+
# the object file's undefined references are bound by the dynamic linker when loaded (flag)
|
86
138
|
MH_BINDATLOAD = 0x8
|
139
|
+
|
140
|
+
# the file has its dynamic undefined references prebound (flag)
|
87
141
|
MH_PREBOUND = 0x10
|
142
|
+
|
143
|
+
# the file has its read-only and read-write segments split (flag)
|
88
144
|
MH_SPLIT_SEGS = 0x20
|
145
|
+
|
146
|
+
# the shared library init routine is to be run lazily via catching memory faults to its writeable segments (obsolete) (flag)
|
89
147
|
MH_LAZY_INIT = 0x40
|
148
|
+
|
149
|
+
# the image is using two-level name space bindings (flag)
|
90
150
|
MH_TWOLEVEL = 0x80
|
151
|
+
|
152
|
+
# the executable is forcing all images to use flat name space bindings (flag)
|
91
153
|
MH_FORCE_FLAT = 0x100
|
154
|
+
|
155
|
+
# this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used (flag)
|
92
156
|
MH_NOMULTIDEFS = 0x200
|
157
|
+
|
158
|
+
# do not have dyld notify the prebinding agent about this executable (flag)
|
93
159
|
MH_NOPREFIXBINDING = 0x400
|
160
|
+
|
161
|
+
# the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is not set (flag)
|
94
162
|
MH_PREBINDABLE = 0x800
|
163
|
+
|
164
|
+
# indicates that this binary binds to all two-level namespace modules of its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL are both set (flag)
|
95
165
|
MH_ALLMODSBOUND = 0x1000
|
166
|
+
|
167
|
+
# safe to divide up the sections into sub-sections via symbols for dead code stripping (flag)
|
96
168
|
MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000
|
169
|
+
|
170
|
+
# the binary has been canonicalized via the unprebind operation (flag)
|
97
171
|
MH_CANONICAL = 0x4000
|
172
|
+
|
173
|
+
# the final linked image contains external weak symbols (flag)
|
98
174
|
MH_WEAK_DEFINES = 0x8000
|
175
|
+
|
176
|
+
# the final linked image uses weak symbols (flag)
|
99
177
|
MH_BINDS_TO_WEAK = 0x10000
|
178
|
+
|
179
|
+
# When this bit is set, all stacks in the task will be given stack execution privilege. Only used in MH_EXECUTE filetypes (flag)
|
100
180
|
MH_ALLOW_STACK_EXECUTION = 0x20000
|
181
|
+
|
182
|
+
# When this bit is set, the binary declares it is safe for use in processes with uid zero (flag)
|
101
183
|
MH_ROOT_SAFE = 0x40000
|
184
|
+
|
185
|
+
# When this bit is set, the binary declares it is safe for use in processes when issetugid() is true (flag)
|
102
186
|
MH_SETUID_SAFE = 0x80000
|
187
|
+
|
188
|
+
# When this bit is set on a dylib, the static linker does not need to examine dependent dylibs to see if any are re-exported (flag)
|
103
189
|
MH_NO_REEXPORTED_DYLIBS = 0x100000
|
190
|
+
|
191
|
+
# When this bit is set, the OS will load the main executable at a random address. Only used in MH_EXECUTE filetypes (flag)
|
104
192
|
MH_PIE = 0x200000
|
193
|
+
|
194
|
+
# Only for use on dylibs. When linking against a dylib that has this bit set, the static linker will automatically not create a LC_LOAD_DYLIB load command to the dylib if no symbols are being referenced from the dylib (flag)
|
105
195
|
MH_DEAD_STRIPPABLE_DYLIB = 0x400000
|
196
|
+
|
197
|
+
# Contains a section of type S_THREAD_LOCAL_VARIABLES (flag)
|
106
198
|
MH_HAS_TLV_DESCRIPTORS = 0x800000
|
199
|
+
|
200
|
+
# When this bit is set, the OS will run the main executable with a non-executable heap even on platforms (e.g. i386) that don't require it. Only used in MH_EXECUTE filetypes (flag)
|
107
201
|
MH_NO_HEAP_EXECUTION = 0x1000000
|
202
|
+
|
203
|
+
# The code was linked for use in an application extension (flag)
|
108
204
|
MH_APP_EXTENSION_SAFE = 0x02000000
|
109
205
|
|
206
|
+
# association of mach header flags to string representations
|
110
207
|
MH_FLAGS = {
|
111
208
|
MH_NOUNDEFS => "MH_NOUNDEFS",
|
112
209
|
MH_INCRLINK => "MH_INCRLINK",
|
@@ -136,7 +233,6 @@ module MachO
|
|
136
233
|
MH_APP_EXTENSION_SAFE => "MH_APP_EXTENSION_SAFE"
|
137
234
|
}
|
138
235
|
|
139
|
-
# 'Fat' binaries envelop Mach-O binaries so include them for completeness,
|
140
236
|
# Fat binary header structure
|
141
237
|
class FatHeader < CStruct
|
142
238
|
uint32 :magic
|
@@ -162,6 +258,10 @@ module MachO
|
|
162
258
|
uint32 :sizeofcmds
|
163
259
|
uint32 :flags
|
164
260
|
|
261
|
+
# @example
|
262
|
+
# puts "this mach-o has position-independent execution" if header.flag?(MH_PIE)
|
263
|
+
# @param flag [Fixnum] a mach header flag constant
|
264
|
+
# @return [Boolean] true if `flag` is present in the header's flag section
|
165
265
|
def flag?(flag)
|
166
266
|
flags & flag == flag
|
167
267
|
end
|
@@ -178,6 +278,10 @@ module MachO
|
|
178
278
|
uint32 :flags
|
179
279
|
uint32 :reserved
|
180
280
|
|
281
|
+
# @example
|
282
|
+
# puts "this mach-o has position-independent execution" if header.flag?(MH_PIE)
|
283
|
+
# @param flag [Fixnum] a mach header flag constant
|
284
|
+
# @return [Boolean] true if `flag` is present in the header's flag section
|
181
285
|
def flag?(flag)
|
182
286
|
flags & flag == flag
|
183
287
|
end
|
data/lib/macho/load_commands.rb
CHANGED
@@ -3,55 +3,148 @@ module MachO
|
|
3
3
|
# LC_REQ_DYLD to be recognized by the dynamic linder (dyld)
|
4
4
|
LC_REQ_DYLD = 0x80000000
|
5
5
|
|
6
|
-
#
|
6
|
+
# segment of this file to be mapped
|
7
7
|
LC_SEGMENT = 0x1
|
8
|
+
|
9
|
+
# link-edit stab symbol table info
|
8
10
|
LC_SYMTAB = 0x2
|
11
|
+
|
12
|
+
# link-edit gdb symbol table info (obsolete)
|
9
13
|
LC_SYMSEG = 0x3
|
14
|
+
|
15
|
+
# thread
|
10
16
|
LC_THREAD = 0x4
|
17
|
+
|
18
|
+
# unix thread (includes a stack)
|
11
19
|
LC_UNIXTHREAD = 0x5
|
20
|
+
|
21
|
+
# load a specified fixed VM shared library
|
12
22
|
LC_LOADFVMLIB = 0x6
|
23
|
+
|
24
|
+
# fixed VM shared library identification
|
13
25
|
LC_IDFVMLIB = 0x7
|
26
|
+
|
27
|
+
# object identification info (obsolete)
|
14
28
|
LC_IDENT = 0x8
|
29
|
+
|
30
|
+
# fixed VM file inclusion (internal use)
|
15
31
|
LC_FVMFILE = 0x9
|
32
|
+
|
33
|
+
# prepage command (internal use)
|
16
34
|
LC_PREPAGE = 0xa
|
35
|
+
|
36
|
+
# dynamic link-edit symbol table info
|
17
37
|
LC_DYSYMTAB = 0xb
|
38
|
+
|
39
|
+
# load a dynamically linked shared library
|
18
40
|
LC_LOAD_DYLIB = 0xc
|
41
|
+
|
42
|
+
# dynamically linked shared lib ident
|
19
43
|
LC_ID_DYLIB = 0xd
|
44
|
+
|
45
|
+
# load a dynamic linker
|
20
46
|
LC_LOAD_DYLINKER = 0xe
|
47
|
+
|
48
|
+
# dynamic linker identification
|
21
49
|
LC_ID_DYLINKER = 0xf
|
50
|
+
|
51
|
+
# modules prebound for a dynamically linked shared library
|
22
52
|
LC_PREBOUND_DYLIB = 0x10
|
53
|
+
|
54
|
+
# image routines
|
23
55
|
LC_ROUTINES = 0x11
|
56
|
+
|
57
|
+
# sub framework
|
24
58
|
LC_SUB_FRAMEWORK = 0x12
|
59
|
+
|
60
|
+
# sub umbrella
|
25
61
|
LC_SUB_UMBRELLA = 0x13
|
62
|
+
|
63
|
+
# sub umbrella
|
26
64
|
LC_SUB_CLIENT = 0x14
|
65
|
+
|
66
|
+
# sub umbrella
|
27
67
|
LC_SUB_LIBRARY = 0x15
|
68
|
+
|
69
|
+
# two-level namespace lookup hints
|
28
70
|
LC_TWOLEVEL_HINTS = 0x16
|
71
|
+
|
72
|
+
# prebind checksum
|
29
73
|
LC_PREBIND_CKSUM = 0x17
|
74
|
+
|
75
|
+
# load a dynamically linked shared library that is allowed to be missing (all symbols are weak imported).
|
30
76
|
LC_LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD)
|
77
|
+
|
78
|
+
# 64-bit segment of this file to be mapped
|
31
79
|
LC_SEGMENT_64 = 0x19
|
80
|
+
|
81
|
+
# 64-bit image routines
|
32
82
|
LC_ROUTINES_64 = 0x1a
|
83
|
+
|
84
|
+
# the uuid
|
33
85
|
LC_UUID = 0x1b
|
86
|
+
|
87
|
+
# runpath additions
|
34
88
|
LC_RPATH = (0x1c | LC_REQ_DYLD)
|
89
|
+
|
90
|
+
# local of code signature
|
35
91
|
LC_CODE_SIGNATURE = 0x1d
|
92
|
+
|
93
|
+
# local of info to split segments
|
36
94
|
LC_SEGMENT_SPLIT_INFO = 0x1e
|
95
|
+
|
96
|
+
# load and re-export dylib
|
37
97
|
LC_REEXPORT_DYLIB = (0x1f | LC_REQ_DYLD)
|
98
|
+
|
99
|
+
# delay load of dylib until first use
|
38
100
|
LC_LAZY_LOAD_DYLIB = 0x20
|
101
|
+
|
102
|
+
# encrypted segment information
|
39
103
|
LC_ENCRYPTION_INFO = 0x21
|
104
|
+
|
105
|
+
# compressed dyld information
|
40
106
|
LC_DYLD_INFO = 0x22
|
107
|
+
|
108
|
+
# compressed dyld information only
|
41
109
|
LC_DYLD_INFO_ONLY = (0x22 | LC_REQ_DYLD)
|
110
|
+
|
111
|
+
# load upward dylib
|
42
112
|
LC_LOAD_UPWARD_DYLIB = (0x23 | LC_REQ_DYLD)
|
113
|
+
|
114
|
+
# build for MacOSX min OS version
|
43
115
|
LC_VERSION_MIN_MACOSX = 0x24
|
116
|
+
|
117
|
+
# build for iPhoneOS min OS version
|
44
118
|
LC_VERSION_MIN_IPHONEOS = 0x25
|
119
|
+
|
120
|
+
# compressed table of function start addresses
|
45
121
|
LC_FUNCTION_STARTS = 0x26
|
122
|
+
|
123
|
+
# string for dyld to treat like environment variable
|
46
124
|
LC_DYLD_ENVIRONMENT = 0x27
|
125
|
+
|
126
|
+
# replacement for LC_UNIXTHREAD
|
47
127
|
LC_MAIN = (0x28 | LC_REQ_DYLD)
|
128
|
+
|
129
|
+
# table of non-instructions in __text
|
48
130
|
LC_DATA_IN_CODE = 0x29
|
131
|
+
|
132
|
+
# source version used to build binary
|
49
133
|
LC_SOURCE_VERSION = 0x2a
|
134
|
+
|
135
|
+
# Code signing DRs copied from linked dylibs
|
50
136
|
LC_DYLIB_CODE_SIGN_DRS = 0x2b
|
137
|
+
|
138
|
+
# 64-bit encrypted segment information
|
51
139
|
LC_ENCRYPTION_INFO_64 = 0x2c
|
140
|
+
|
141
|
+
# linker options in MH_OBJECT files
|
52
142
|
LC_LINKER_OPTION = 0x2d
|
143
|
+
|
144
|
+
# linker options in MH_OBJECT files
|
53
145
|
LC_LINKER_OPTIMIZATION_HINT = 0x2e
|
54
146
|
|
147
|
+
# association of load commands to string representations
|
55
148
|
LOAD_COMMANDS = {
|
56
149
|
LC_SEGMENT => "LC_SEGMENT",
|
57
150
|
LC_SYMTAB => "LC_SYMTAB",
|
@@ -102,6 +195,7 @@ module MachO
|
|
102
195
|
LC_LINKER_OPTIMIZATION_HINT => "LC_LINKER_OPTIMIZATION_HINT"
|
103
196
|
}
|
104
197
|
|
198
|
+
# association of load commands to string representations of class names
|
105
199
|
LC_STRUCTURES = {
|
106
200
|
LC_SEGMENT => "SegmentCommand",
|
107
201
|
LC_SYMTAB => "SymtabCommand",
|
@@ -152,60 +246,102 @@ module MachO
|
|
152
246
|
LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand"
|
153
247
|
}
|
154
248
|
|
155
|
-
#
|
156
|
-
# we don't use these anywhere right now, but they're good to have
|
249
|
+
# pagezero segment name
|
157
250
|
SEG_PAGEZERO = "__PAGEZERO"
|
251
|
+
|
252
|
+
# text segment name
|
158
253
|
SEG_TEXT = "__TEXT"
|
254
|
+
|
255
|
+
# data segment name
|
159
256
|
SEG_DATA = "__DATA"
|
257
|
+
|
258
|
+
# objective-c runtime segment
|
160
259
|
SEG_OBJC = "__OBJC"
|
260
|
+
|
261
|
+
# icon segment
|
161
262
|
SEG_ICON = "__ICON"
|
263
|
+
|
264
|
+
# link editor structures segment
|
162
265
|
SEG_LINKEDIT = "__LINKEDIT"
|
266
|
+
|
267
|
+
# unix stack segment
|
163
268
|
SEG_UNIXSTACK = "__UNIXSTACK"
|
269
|
+
|
270
|
+
# segment for self-modifying code with RWX permissions
|
164
271
|
SEG_IMPORT = "__IMPORT"
|
165
272
|
|
166
|
-
#
|
273
|
+
# the file contents for this segment is for the high part of the VM space, the low part is zero filled (for stacks in core files)
|
167
274
|
SG_HIGHVM = 0x1
|
275
|
+
|
276
|
+
# this segment is the VM that is allocated by a fixed VM library, for overlap checking in the link editor
|
168
277
|
SG_FVMLIB = 0x2
|
278
|
+
|
279
|
+
# this segment has nothing that was relocated in it and nothing relocated to it, that is it maybe safely replaced without relocation
|
169
280
|
SG_NORELOC = 0x4
|
281
|
+
|
282
|
+
# this segment is protected. if the segment starts at file offset 0, the first page of the segment is not protected. all other pages of the segment are protected.
|
170
283
|
SG_PROTECTED_VERSION_1 = 0x8
|
171
284
|
|
172
285
|
# Mach-O load command structure
|
173
|
-
#
|
174
|
-
# represented, and no actual data.
|
175
|
-
# isn't available/implemented
|
286
|
+
# This is the most generic load command - only cmd ID and size are
|
287
|
+
# represented, and no actual data. Used when a more specific class
|
288
|
+
# isn't available/implemented.
|
176
289
|
class LoadCommand < MachOStructure
|
177
|
-
|
290
|
+
# @return [Fixnum] the offset in the file the command was created from
|
291
|
+
attr_reader :offset
|
292
|
+
|
293
|
+
# @return [Fixnum] the load command's identifying number
|
294
|
+
attr_reader :cmd
|
295
|
+
|
296
|
+
# @return [Fixnum] the size of the load command, in bytes
|
297
|
+
attr_reader :cmdsize
|
178
298
|
|
179
299
|
@format = "VV"
|
180
300
|
@sizeof = 8
|
181
301
|
|
302
|
+
# Creates a new LoadCommand given an offset and binary string
|
303
|
+
# @param offset [Fixnum] the offset to initialize with
|
304
|
+
# @param bin [String] the binary string to initialize with
|
305
|
+
# @return [MachO::LoadCommand] the new load command
|
306
|
+
# @private
|
182
307
|
def self.new_from_bin(offset, bin)
|
183
308
|
self.new(offset, *bin.unpack(@format))
|
184
309
|
end
|
185
310
|
|
311
|
+
# @param offset [Fixnum] the offset to initialize iwth
|
312
|
+
# @param cmd [Fixnum] the load command's identifying number
|
313
|
+
# @param cmdsize [Fixnum] the size of the load command in bytes
|
314
|
+
# @private
|
186
315
|
def initialize(offset, cmd, cmdsize)
|
187
316
|
@offset = offset
|
188
317
|
@cmd = cmd
|
189
318
|
@cmdsize = cmdsize
|
190
319
|
end
|
191
320
|
|
321
|
+
# @return [String] a string representation of the load command's identifying number
|
192
322
|
def to_s
|
193
323
|
LOAD_COMMANDS[cmd]
|
194
324
|
end
|
195
325
|
end
|
196
326
|
|
327
|
+
# A load command containing a single 128-bit unique random number identifying
|
328
|
+
# an object produced by static link editor. Corresponds to LC_UUID.
|
197
329
|
class UUIDCommand < LoadCommand
|
330
|
+
# @return [Array<Fixnum>] the UUID
|
198
331
|
attr_reader :uuid
|
199
332
|
|
200
333
|
@format = "VVa16"
|
201
334
|
@sizeof = 24
|
202
335
|
|
336
|
+
# @private
|
203
337
|
def initialize(offset, cmd, cmdsize, uuid)
|
204
338
|
super(offset, cmd, cmdsize)
|
205
339
|
@uuid = uuid.unpack("C16") # re-unpack for the actual UUID array
|
206
340
|
end
|
207
341
|
end
|
208
342
|
|
343
|
+
# A load command indicating that part of this file is to be mapped into
|
344
|
+
# the task's address space. Corresponds to LC_SEGMENT.
|
209
345
|
class SegmentCommand < LoadCommand
|
210
346
|
attr_reader :segname, :vmaddr, :vmsize, :fileoff, :filesize, :maxprot
|
211
347
|
attr_reader :initprot, :nsects, :flags
|
@@ -213,6 +349,7 @@ module MachO
|
|
213
349
|
@format = "VVa16VVVVVVVV"
|
214
350
|
@sizeof = 56
|
215
351
|
|
352
|
+
# @private
|
216
353
|
def initialize(offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
|
217
354
|
filesize, maxprot, initprot, nsects, flags)
|
218
355
|
super(offset, cmd, cmdsize)
|
@@ -227,11 +364,14 @@ module MachO
|
|
227
364
|
@flags = flags
|
228
365
|
end
|
229
366
|
|
367
|
+
# @return [String] the segment's name, with any trailing NULL characters removed
|
230
368
|
def segment_name
|
231
369
|
@segname.delete("\x00")
|
232
370
|
end
|
233
371
|
end
|
234
372
|
|
373
|
+
# A load command indicating that part of this file is to be mapped into
|
374
|
+
# the task's address space. Corresponds to LC_SEGMENT_64.
|
235
375
|
class SegmentCommand64 < LoadCommand
|
236
376
|
attr_reader :segname, :vmaddr, :vmsize, :fileoff, :filesize, :maxprot
|
237
377
|
attr_reader :initprot, :nsects, :flags
|
@@ -239,6 +379,7 @@ module MachO
|
|
239
379
|
@format = "VVa16QQQQVVVV"
|
240
380
|
@sizeof = 72
|
241
381
|
|
382
|
+
# @private
|
242
383
|
def initialize(offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
|
243
384
|
filesize, maxprot, initprot, nsects, flags)
|
244
385
|
super(offset, cmd, cmdsize)
|
@@ -253,17 +394,22 @@ module MachO
|
|
253
394
|
@flags = flags
|
254
395
|
end
|
255
396
|
|
397
|
+
# @return [String] the segment's name, with any trailing NULL characters removed
|
256
398
|
def segment_name
|
257
399
|
@segname.delete("\x00")
|
258
400
|
end
|
259
401
|
end
|
260
402
|
|
403
|
+
# A load command representing some aspect of shared libraries, depending
|
404
|
+
# on filetype. Corresponds to LC_ID_DYLIB, LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB,
|
405
|
+
# and LC_REEXPORT_DYLIB.
|
261
406
|
class DylibCommand < LoadCommand
|
262
407
|
attr_reader :name, :timestamp, :current_version, :compatibility_version
|
263
408
|
|
264
409
|
@format = "VVVVVV"
|
265
410
|
@sizeof = 24
|
266
411
|
|
412
|
+
# @private
|
267
413
|
def initialize(offset, cmd, cmdsize, name, timestamp, current_version,
|
268
414
|
compatibility_version)
|
269
415
|
super(offset, cmd, cmdsize)
|
@@ -274,24 +420,31 @@ module MachO
|
|
274
420
|
end
|
275
421
|
end
|
276
422
|
|
423
|
+
# A load command representing some aspect of the dynamic linker, depending
|
424
|
+
# on filetype. Corresponds to LC_ID_DYLINKER, LC_LOAD_DYLINKER, and
|
425
|
+
# LC_DYLD_ENVIRONMENT.
|
277
426
|
class DylinkerCommand < LoadCommand
|
278
427
|
attr_reader :name
|
279
428
|
|
280
429
|
@format = "VVV"
|
281
430
|
@sizeof = 12
|
282
431
|
|
432
|
+
# @private
|
283
433
|
def initialize(offset, cmd, cmdsize, name)
|
284
434
|
super(offset, cmd, cmdsize)
|
285
435
|
@name = name
|
286
436
|
end
|
287
437
|
end
|
288
438
|
|
439
|
+
# A load command used to indicate dynamic libraries used in prebinding.
|
440
|
+
# Corresponds to LC_PREBOUND_DYLIB.
|
289
441
|
class PreboundDylibCommand < LoadCommand
|
290
442
|
attr_reader :name, :nmodules, :linked_modules
|
291
443
|
|
292
444
|
@format = "VVVVV"
|
293
445
|
@sizeof = 20
|
294
446
|
|
447
|
+
# @private
|
295
448
|
def initialize(offset, cmd, cmdsize, name, nmodules, linked_modules)
|
296
449
|
super(offset, cmd, cmdsize)
|
297
450
|
@name = name
|
@@ -300,12 +453,15 @@ module MachO
|
|
300
453
|
end
|
301
454
|
end
|
302
455
|
|
303
|
-
#
|
304
|
-
# except common ones (cmd, cmdsize)
|
456
|
+
# A load command used to represent threads.
|
457
|
+
# @note cctools-870 has all fields of thread_command commented out except common ones (cmd, cmdsize)
|
305
458
|
class ThreadCommand < LoadCommand
|
306
459
|
|
307
460
|
end
|
308
461
|
|
462
|
+
# A load command containing the address of the dynamic shared library
|
463
|
+
# initialization routine and an index into the module table for the module
|
464
|
+
# that defines the routine. Corresponds to LC_ROUTINES.
|
309
465
|
class RoutinesCommand < LoadCommand
|
310
466
|
attr_reader :init_address, :init_module, :reserved1, :reserved2
|
311
467
|
attr_reader :reserved3, :reserved4, :reserved5, :reserved6
|
@@ -313,6 +469,7 @@ module MachO
|
|
313
469
|
@format = "VVVVVVVVVV"
|
314
470
|
@sizeof = 40
|
315
471
|
|
472
|
+
# @private
|
316
473
|
def initialize(offset, cmd, cmdsize, init_address, init_module,
|
317
474
|
reserved1, reserved2, reserved3, reserved4, reserved5,
|
318
475
|
reserved6)
|
@@ -328,6 +485,9 @@ module MachO
|
|
328
485
|
end
|
329
486
|
end
|
330
487
|
|
488
|
+
# A load command containing the address of the dynamic shared library
|
489
|
+
# initialization routine and an index into the module table for the module
|
490
|
+
# that defines the routine. Corresponds to LC_ROUTINES_64.
|
331
491
|
class RoutinesCommand64 < LoadCommand
|
332
492
|
attr_reader :init_address, :init_module, :reserved1, :reserved2
|
333
493
|
attr_reader :reserved3, :reserved4, :reserved5, :reserved6
|
@@ -335,6 +495,7 @@ module MachO
|
|
335
495
|
@format = "VVQQQQQQQQ"
|
336
496
|
@sizeof = 72
|
337
497
|
|
498
|
+
# @private
|
338
499
|
def initialize(offset, cmd, cmdsize, init_address, init_module,
|
339
500
|
reserved1, reserved2, reserved3, reserved4, reserved5,
|
340
501
|
reserved6)
|
@@ -350,60 +511,85 @@ module MachO
|
|
350
511
|
end
|
351
512
|
end
|
352
513
|
|
514
|
+
# A load command signifying membership of a subframework containing the name
|
515
|
+
# of an umbrella framework. Corresponds to LC_SUB_FRAMEWORK.
|
353
516
|
class SubFrameworkCommand < LoadCommand
|
354
517
|
attr_reader :umbrella
|
355
518
|
|
356
519
|
@format = "VVV"
|
357
520
|
@sizeof = 12
|
358
521
|
|
522
|
+
# @private
|
359
523
|
def initialize(offset, cmd, cmdsize, umbrella)
|
360
524
|
super(offset, cmd, cmdsize)
|
361
525
|
@umbrella = umbrella
|
362
526
|
end
|
363
527
|
end
|
364
528
|
|
529
|
+
# A load command signifying membership of a subumbrella containing the name
|
530
|
+
# of an umbrella framework. Corresponds to LC_SUB_UMBRELLA.
|
365
531
|
class SubUmbrellaCommand < LoadCommand
|
366
532
|
attr_reader :sub_umbrella
|
367
533
|
|
368
534
|
@format = "VVV"
|
369
535
|
@sizeof = 12
|
370
536
|
|
537
|
+
# @private
|
371
538
|
def initialize(offset, cmd, cmdsize, sub_umbrella)
|
372
539
|
super(offset, cmd, cmdsize)
|
373
540
|
@sub_umbrella = sub_umbrella
|
374
541
|
end
|
375
542
|
end
|
376
543
|
|
544
|
+
# A load command signifying a sublibrary of a shared library. Corresponds
|
545
|
+
# to LC_SUB_LIBRARY.
|
377
546
|
class SubLibraryCommand < LoadCommand
|
378
547
|
attr_reader :sub_library
|
379
548
|
|
380
549
|
@format = "VVV"
|
381
550
|
@sizeof = 12
|
382
551
|
|
552
|
+
# @private
|
383
553
|
def initialize(offset, cmd, cmdsize, sub_library)
|
384
554
|
super(offset, cmd, cmdsize)
|
385
555
|
@sub_library = sub_library
|
386
556
|
end
|
387
557
|
end
|
388
558
|
|
559
|
+
# A load command signifying a shared library that is a subframework of
|
560
|
+
# an umbrella framework. Corresponds to LC_SUB_CLIENT.
|
389
561
|
class SubClientCommand < LoadCommand
|
390
562
|
attr_reader :sub_client
|
391
563
|
|
392
564
|
@format = "VVV"
|
393
565
|
@sizeof = 12
|
394
566
|
|
567
|
+
# @private
|
395
568
|
def initialize(offset, cmd, cmdsize, sub_client)
|
396
569
|
super(offset, cmd, cmdsize)
|
397
570
|
@sub_client = sub_client
|
398
571
|
end
|
399
572
|
end
|
400
573
|
|
574
|
+
# A load command containing the offsets and sizes of the link-edit 4.3BSD
|
575
|
+
# "stab" style symbol table information. Corresponds to LC_SYMTAB.
|
401
576
|
class SymtabCommand < LoadCommand
|
402
|
-
|
577
|
+
# @return [Fixnum] the symbol table's offset
|
578
|
+
attr_reader :symoff
|
579
|
+
|
580
|
+
# @return [Fixnum] the number of symbol table entries
|
581
|
+
attr_reader :nsyms
|
582
|
+
|
583
|
+
# @return the string table's offset
|
584
|
+
attr_reader :stroff
|
585
|
+
|
586
|
+
# @return the string table size in bytes
|
587
|
+
attr_reader :strsize
|
403
588
|
|
404
589
|
@format = "VVVVVV"
|
405
590
|
@sizeof = 24
|
406
591
|
|
592
|
+
# @private
|
407
593
|
def initialize(offset, cmd, cmdsize, symoff, nsyms, stroff, strsize)
|
408
594
|
super(offset, cmd, cmdsize)
|
409
595
|
@symoff = symoff
|
@@ -413,16 +599,51 @@ module MachO
|
|
413
599
|
end
|
414
600
|
end
|
415
601
|
|
602
|
+
# A load command containing symbolic information needed to support data
|
603
|
+
# structures used by the dynamic link editor. Corresponds to LC_DYSYMTAB.
|
416
604
|
class DysymtabCommand < LoadCommand
|
417
|
-
attr_reader :ilocalsym
|
418
|
-
|
419
|
-
attr_reader :
|
420
|
-
|
605
|
+
attr_reader :ilocalsym
|
606
|
+
|
607
|
+
attr_reader :nlocalsym
|
608
|
+
|
609
|
+
attr_reader :iextdefsym
|
610
|
+
|
611
|
+
attr_reader :nextdefsym
|
612
|
+
|
613
|
+
attr_reader :iundefsym
|
614
|
+
|
615
|
+
attr_reader :nundefsym
|
616
|
+
|
617
|
+
attr_reader :tocoff
|
618
|
+
|
619
|
+
attr_reader :ntoc
|
620
|
+
|
621
|
+
attr_reader :modtaboff
|
622
|
+
|
623
|
+
attr_reader :nmodtab
|
624
|
+
|
625
|
+
attr_reader :extrefsymoff
|
626
|
+
|
627
|
+
attr_reader :nextrefsyms
|
628
|
+
|
629
|
+
attr_reader :indirectsymoff
|
630
|
+
|
631
|
+
attr_reader :nindirectsyms
|
632
|
+
|
633
|
+
attr_reader :extreloff
|
634
|
+
|
635
|
+
attr_reader :nextrel
|
636
|
+
|
637
|
+
attr_reader :locreloff
|
638
|
+
|
639
|
+
attr_reader :nlocrel
|
640
|
+
|
421
641
|
|
422
642
|
@format = "VVVVVVVVVVVVVVVVVVVV"
|
423
643
|
@sizeof = 80
|
424
644
|
|
425
645
|
# ugh
|
646
|
+
# @private
|
426
647
|
def initialize(offset, cmd, cmdsize, ilocalsym, nlocalsym, iextdefsym,
|
427
648
|
nextdefsym, iundefsym, nundefsym, tocoff, ntoc, modtaboff,
|
428
649
|
nmodtab, extrefsymoff, nextrefsyms, indirectsymoff,
|
@@ -449,12 +670,19 @@ module MachO
|
|
449
670
|
end
|
450
671
|
end
|
451
672
|
|
673
|
+
# A load command containing the offset and number of hints in the two-level
|
674
|
+
# namespace lookup hints table. Corresponds to LC_TWOLEVEL_HINTS.
|
452
675
|
class TwolevelHintsCommand < LoadCommand
|
453
|
-
|
676
|
+
# @return [Fixnum] the offset to the hint table
|
677
|
+
attr_reader :htoffset
|
678
|
+
|
679
|
+
# @return [Fixnum] the number of hints in the hint table
|
680
|
+
attr_reader :nhints
|
454
681
|
|
455
682
|
@format = "VVVV"
|
456
683
|
@sizeof = 16
|
457
684
|
|
685
|
+
# @private
|
458
686
|
def initialize(offset, cmd, cmdsize, htoffset, nhints)
|
459
687
|
super(offset, cmd, cmdsize)
|
460
688
|
@htoffset = htoffset
|
@@ -462,36 +690,52 @@ module MachO
|
|
462
690
|
end
|
463
691
|
end
|
464
692
|
|
693
|
+
# A load command containing the value of the original checksum for prebound
|
694
|
+
# files, or zero. Corresponds to LC_PREBIND_CKSUM.
|
465
695
|
class PrebindCksumCommand < LoadCommand
|
696
|
+
# @return [Fixnum] the checksum or 0
|
466
697
|
attr_reader :cksum
|
467
698
|
|
468
699
|
@format = "VVV"
|
469
700
|
@sizeof = 12
|
470
701
|
|
702
|
+
# @private
|
471
703
|
def initialize(offset, cmd, cmdsize, cksum)
|
472
704
|
super(offset, cmd, cmdsize)
|
473
705
|
@cksum = cksum
|
474
706
|
end
|
475
707
|
end
|
476
708
|
|
709
|
+
# A load command representing an rpath, which specifies a path that should
|
710
|
+
# be added to the current run path used to find @rpath prefixed dylibs.
|
711
|
+
# Corresponds to LC_RPATH.
|
477
712
|
class RpathCommand < LoadCommand
|
478
713
|
attr_reader :path
|
479
714
|
|
480
715
|
@format = "VVV"
|
481
716
|
@sizeof = 12
|
482
717
|
|
718
|
+
# @private
|
483
719
|
def initialize(offset, cmd, cmdsize, path)
|
484
720
|
super(offset, cmd, cmdsize)
|
485
721
|
@path = path
|
486
722
|
end
|
487
723
|
end
|
488
724
|
|
725
|
+
# A load command representing the offsets and sizes of a blob of data in
|
726
|
+
# the __LINKEDIT segment. Corresponds to LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO,
|
727
|
+
# LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS, and LC_LINKER_OPTIMIZATION_HINT.
|
489
728
|
class LinkeditDataCommand < LoadCommand
|
490
|
-
|
729
|
+
# @return [Fixnum] offset to the data in the __LINKEDIT segment
|
730
|
+
attr_reader :dataoff
|
731
|
+
|
732
|
+
# @return [Fixnum] size of the data in the __LINKEDIT segment
|
733
|
+
attr_reader :datasize
|
491
734
|
|
492
735
|
@format = "VVVV"
|
493
736
|
@sizeof = 16
|
494
737
|
|
738
|
+
# @private
|
495
739
|
def initialize(offset, cmd, cmdsize, dataoff, datasize)
|
496
740
|
super(offset, cmd, cmdsize)
|
497
741
|
@dataoff = dataoff
|
@@ -499,12 +743,22 @@ module MachO
|
|
499
743
|
end
|
500
744
|
end
|
501
745
|
|
746
|
+
# A load command representing the offset to and size of an encrypted
|
747
|
+
# segment. Corresponds to LC_ENCRYPTION_INFO.
|
502
748
|
class EncryptionInfoCommand < LoadCommand
|
503
|
-
|
749
|
+
# @return [Fixnum] the offset to the encrypted segment
|
750
|
+
attr_reader :cryptoff
|
751
|
+
|
752
|
+
# @return [Fixnum] the size of the encrypted segment
|
753
|
+
attr_reader :cryptsize
|
754
|
+
|
755
|
+
# @return [Fixnum] the encryption system, or 0 if not encrypted yet
|
756
|
+
attr_reader :cryptid
|
504
757
|
|
505
758
|
@format = "VVVVV"
|
506
759
|
@sizeof = 20
|
507
760
|
|
761
|
+
# @private
|
508
762
|
def initialize(offset, cmd, cmdsize, cryptoff, cryptsize, cryptid)
|
509
763
|
super(offset, cmd, cmdsize)
|
510
764
|
@cryptoff = cryptoff
|
@@ -513,12 +767,25 @@ module MachO
|
|
513
767
|
end
|
514
768
|
end
|
515
769
|
|
770
|
+
# A load command representing the offset to and size of an encrypted
|
771
|
+
# segment. Corresponds to LC_ENCRYPTION_INFO_64.
|
516
772
|
class EncryptionInfoCommand64 < LoadCommand
|
517
|
-
|
773
|
+
# @return [Fixnum] the offset to the encrypted segment
|
774
|
+
attr_reader :cryptoff
|
775
|
+
|
776
|
+
# @return [Fixnum] the size of the encrypted segment
|
777
|
+
attr_reader :cryptsize
|
778
|
+
|
779
|
+
# @return [Fixnum] the encryption system, or 0 if not encrypted yet
|
780
|
+
attr_reader :cryptid
|
781
|
+
|
782
|
+
# @return [Fixnum] 64-bit padding value
|
783
|
+
attr_reader :pad
|
518
784
|
|
519
785
|
@format = "VVVVVV"
|
520
786
|
@sizeof = 24
|
521
787
|
|
788
|
+
# @private
|
522
789
|
def initialize(offset, cmd, cmdsize, cryptoff, cryptsize, cryptid)
|
523
790
|
super(offset, cmd, cmdsize)
|
524
791
|
@cryptoff = cryptoff
|
@@ -528,12 +795,19 @@ module MachO
|
|
528
795
|
end
|
529
796
|
end
|
530
797
|
|
798
|
+
# A load command containing the minimum OS version on which the binary
|
799
|
+
# was built to run. Corresponds to LC_VERSION_MIN_MACOSX and LC_VERSION_MIN_IPHONEOS.
|
531
800
|
class VersionMinCommand < LoadCommand
|
532
|
-
|
801
|
+
# @return [Fixnum] the version X.Y.Z packed as x16.y8.z8
|
802
|
+
attr_reader :version
|
803
|
+
|
804
|
+
# @return [Fixnum] the SDK version X.Y.Z packed as x16.y8.z8
|
805
|
+
attr_reader :sdk
|
533
806
|
|
534
807
|
@format = "VVVV"
|
535
808
|
@sizeof = 16
|
536
809
|
|
810
|
+
# @private
|
537
811
|
def initialize(offset, cmd, cmdsize, version, sdk)
|
538
812
|
super(offset, cmd, cmdsize)
|
539
813
|
@version = version
|
@@ -541,6 +815,9 @@ module MachO
|
|
541
815
|
end
|
542
816
|
end
|
543
817
|
|
818
|
+
# A load command containing the file offsets and sizes of the new
|
819
|
+
# compressed form of the information dyld needs to load the image.
|
820
|
+
# Corresponds to LC_DYLD_INFO and LC_DYLD_INFO_ONLY.
|
544
821
|
class DyldInfoCommand < LoadCommand
|
545
822
|
attr_reader :rebase_off, :rebase_size, :bind_off, :bind_size
|
546
823
|
attr_reader :weak_bind_off, :weak_bind_size, :lazy_bind_off
|
@@ -549,6 +826,7 @@ module MachO
|
|
549
826
|
@format = "VVVVVVVVVVVV"
|
550
827
|
@sizeof = 48
|
551
828
|
|
829
|
+
# @private
|
552
830
|
def initialize(offset, cmd, cmdsize, rebase_off, rebase_size, bind_off,
|
553
831
|
bind_size, weak_bind_off, weak_bind_size, lazy_bind_off,
|
554
832
|
lazy_bind_size, export_off, export_size)
|
@@ -566,24 +844,34 @@ module MachO
|
|
566
844
|
end
|
567
845
|
end
|
568
846
|
|
847
|
+
# A load command containing linker options embedded in object files.
|
848
|
+
# Corresponds to LC_LINKER_OPTION.
|
569
849
|
class LinkerOptionCommand < LoadCommand
|
850
|
+
# @return [Fixnum] the number of strings
|
570
851
|
attr_reader :count
|
571
852
|
|
572
853
|
@format = "VVV"
|
573
854
|
@sizeof = 12
|
574
855
|
|
856
|
+
# @private
|
575
857
|
def initialize(offset, cmd, cmdsize, count)
|
576
858
|
super(offset, cmd, cmdsize)
|
577
859
|
@count = count
|
578
860
|
end
|
579
861
|
end
|
580
862
|
|
863
|
+
# A load command specifying the offset of main(). Corresponds to LC_MAIN.
|
581
864
|
class EntryPointCommand < LoadCommand
|
582
|
-
|
865
|
+
# @return [Fixnum] the file (__TEXT) offset of main()
|
866
|
+
attr_reader :entryoff
|
867
|
+
|
868
|
+
# @return [Fixnum] if not 0, the initial stack size.
|
869
|
+
attr_reader :stacksize
|
583
870
|
|
584
871
|
@format = "VVQQ"
|
585
872
|
@sizeof = 24
|
586
873
|
|
874
|
+
# @private
|
587
875
|
def initialize(offset, cmd, cmdsize, entryoff, stacksize)
|
588
876
|
super(offset, cmd, cmdsize)
|
589
877
|
@entryoff = entryoff
|
@@ -591,12 +879,16 @@ module MachO
|
|
591
879
|
end
|
592
880
|
end
|
593
881
|
|
882
|
+
# A load command specifying the version of the sources used to build the
|
883
|
+
# binary. Corresponds to LC_SOURCE_VERSION.
|
594
884
|
class SourceVersionCommand < LoadCommand
|
885
|
+
# @return [Fixnum] the version packed as a24.b10.c10.d10.e10
|
595
886
|
attr_reader :version
|
596
887
|
|
597
888
|
@format = "VVQ"
|
598
889
|
@sizeof = 16
|
599
890
|
|
891
|
+
# @private
|
600
892
|
def initialize(offset, cmd, cmdsize, version)
|
601
893
|
super(offset, cmd, cmdsize)
|
602
894
|
@version = version
|