ruby-macho 0.2.6 → 1.0.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/README.md +0 -3
- data/lib/macho.rb +25 -2
- data/lib/macho/fat_file.rb +10 -10
- data/lib/macho/headers.rb +552 -549
- data/lib/macho/load_commands.rb +1064 -1061
- data/lib/macho/macho_file.rb +52 -52
- data/lib/macho/sections.rb +160 -157
- data/lib/macho/utils.rb +6 -6
- metadata +3 -4
- data/lib/macho/open.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c4525869d67df12f84b98120b7a0e28cd2e554b
|
4
|
+
data.tar.gz: 007fa710b4d119fe5bb477d4dea2c51664ddbb8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c90ef356d11b1c19b28703ef5a45ef2f1f999a7836ec126b4106a17dcc39630b825a8cd860cbd70c6c31225182c348eb5d1b2f0579fe9ecc072ce39a0ffc0c7c
|
7
|
+
data.tar.gz: a8bb43dd63755f1b1db1f1e3bfc23120d88f41020aa021dea91db9c8e2c7a2e14d7c5182bf2bb315c09236decba982202461a57f8b670ee78d57e1a40b04b874
|
data/README.md
CHANGED
@@ -14,9 +14,6 @@ executables, dynamic libraries, and so forth.
|
|
14
14
|
|
15
15
|
### Documentation
|
16
16
|
|
17
|
-
**Important**: ruby-macho does not have a stable API (yet). Use it with this
|
18
|
-
in mind.
|
19
|
-
|
20
17
|
Full documentation is available on [RubyDoc](http://www.rubydoc.info/gems/ruby-macho/).
|
21
18
|
|
22
19
|
A quick example of what ruby-macho can do:
|
data/lib/macho.rb
CHANGED
@@ -5,7 +5,6 @@ require "#{File.dirname(__FILE__)}/macho/load_commands"
|
|
5
5
|
require "#{File.dirname(__FILE__)}/macho/sections"
|
6
6
|
require "#{File.dirname(__FILE__)}/macho/macho_file"
|
7
7
|
require "#{File.dirname(__FILE__)}/macho/fat_file"
|
8
|
-
require "#{File.dirname(__FILE__)}/macho/open"
|
9
8
|
require "#{File.dirname(__FILE__)}/macho/exceptions"
|
10
9
|
require "#{File.dirname(__FILE__)}/macho/utils"
|
11
10
|
require "#{File.dirname(__FILE__)}/macho/tools"
|
@@ -13,5 +12,29 @@ require "#{File.dirname(__FILE__)}/macho/tools"
|
|
13
12
|
# The primary namespace for ruby-macho.
|
14
13
|
module MachO
|
15
14
|
# release version
|
16
|
-
VERSION = "0.
|
15
|
+
VERSION = "1.0.0".freeze
|
16
|
+
|
17
|
+
# Opens the given filename as a MachOFile or FatFile, depending on its magic.
|
18
|
+
# @param filename [String] the file being opened
|
19
|
+
# @return [MachO::MachOFile] if the file is a Mach-O
|
20
|
+
# @return [MachO::FatFile] if the file is a Fat file
|
21
|
+
# @raise [ArgumentError] if the given file does not exist
|
22
|
+
# @raise [MachO::TruncatedFileError] if the file is too small to have a valid header
|
23
|
+
# @raise [MachO::MagicError] if the file's magic is not valid Mach-O magic
|
24
|
+
def self.open(filename)
|
25
|
+
raise ArgumentError, "#{filename}: no such file" unless File.file?(filename)
|
26
|
+
raise TruncatedFileError unless File.stat(filename).size >= 4
|
27
|
+
|
28
|
+
magic = File.open(filename, "rb") { |f| f.read(4) }.unpack("N").first
|
29
|
+
|
30
|
+
if Utils.fat_magic?(magic)
|
31
|
+
file = FatFile.new(filename)
|
32
|
+
elsif Utils.magic?(magic)
|
33
|
+
file = MachOFile.new(filename)
|
34
|
+
else
|
35
|
+
raise MagicError, magic
|
36
|
+
end
|
37
|
+
|
38
|
+
file
|
39
|
+
end
|
17
40
|
end
|
data/lib/macho/fat_file.rb
CHANGED
@@ -7,10 +7,10 @@ module MachO
|
|
7
7
|
# @return [String] the filename loaded from, or nil if loaded from a binary string
|
8
8
|
attr_accessor :filename
|
9
9
|
|
10
|
-
# @return [MachO::FatHeader] the file's header
|
10
|
+
# @return [MachO::Headers::FatHeader] the file's header
|
11
11
|
attr_reader :header
|
12
12
|
|
13
|
-
# @return [Array<MachO::FatArch>] an array of fat architectures
|
13
|
+
# @return [Array<MachO::Headers::FatArch>] an array of fat architectures
|
14
14
|
attr_reader :fat_archs
|
15
15
|
|
16
16
|
# @return [Array<MachO::MachOFile>] an array of Mach-O binaries
|
@@ -109,7 +109,7 @@ module MachO
|
|
109
109
|
|
110
110
|
# @return [String] a string representation of the file's magic number
|
111
111
|
def magic_string
|
112
|
-
MH_MAGICS[magic]
|
112
|
+
Headers::MH_MAGICS[magic]
|
113
113
|
end
|
114
114
|
|
115
115
|
# The file's type. Assumed to be the same for every Mach-O within.
|
@@ -128,7 +128,7 @@ module MachO
|
|
128
128
|
end
|
129
129
|
|
130
130
|
# All load commands responsible for loading dylibs in the file's Mach-O's.
|
131
|
-
# @return [Array<MachO::DylibCommand>] an array of DylibCommands
|
131
|
+
# @return [Array<MachO::LoadCommands::DylibCommand>] an array of DylibCommands
|
132
132
|
def dylib_load_commands
|
133
133
|
machos.map(&:dylib_load_commands).flatten
|
134
134
|
end
|
@@ -280,7 +280,7 @@ module MachO
|
|
280
280
|
private
|
281
281
|
|
282
282
|
# Obtain the fat header from raw file data.
|
283
|
-
# @return [MachO::FatHeader] the fat header
|
283
|
+
# @return [MachO::Headers::FatHeader] the fat header
|
284
284
|
# @raise [MachO::TruncatedFileError] if the file is too small to have a valid header
|
285
285
|
# @raise [MachO::MagicError] if the magic is not valid Mach-O magic
|
286
286
|
# @raise [MachO::MachOBinaryError] if the magic is for a non-fat Mach-O file
|
@@ -290,7 +290,7 @@ module MachO
|
|
290
290
|
# the smallest fat Mach-O header is 8 bytes
|
291
291
|
raise TruncatedFileError if @raw_data.size < 8
|
292
292
|
|
293
|
-
fh = FatHeader.new_from_bin(:big, @raw_data[0, FatHeader.bytesize])
|
293
|
+
fh = Headers::FatHeader.new_from_bin(:big, @raw_data[0, Headers::FatHeader.bytesize])
|
294
294
|
|
295
295
|
raise MagicError, fh.magic unless Utils.magic?(fh.magic)
|
296
296
|
raise MachOBinaryError unless Utils.fat_magic?(fh.magic)
|
@@ -308,15 +308,15 @@ module MachO
|
|
308
308
|
end
|
309
309
|
|
310
310
|
# Obtain an array of fat architectures from raw file data.
|
311
|
-
# @return [Array<MachO::FatArch>] an array of fat architectures
|
311
|
+
# @return [Array<MachO::Headers::FatArch>] an array of fat architectures
|
312
312
|
# @api private
|
313
313
|
def populate_fat_archs
|
314
314
|
archs = []
|
315
315
|
|
316
|
-
fa_off = FatHeader.bytesize
|
317
|
-
fa_len = FatArch.bytesize
|
316
|
+
fa_off = Headers::FatHeader.bytesize
|
317
|
+
fa_len = Headers::FatArch.bytesize
|
318
318
|
header.nfat_arch.times do |i|
|
319
|
-
archs << FatArch.new_from_bin(:big, @raw_data[fa_off + (fa_len * i), fa_len])
|
319
|
+
archs << Headers::FatArch.new_from_bin(:big, @raw_data[fa_off + (fa_len * i), fa_len])
|
320
320
|
end
|
321
321
|
|
322
322
|
archs
|
data/lib/macho/headers.rb
CHANGED
@@ -1,587 +1,590 @@
|
|
1
1
|
module MachO
|
2
|
-
#
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
# this is defined, but should never appear in ruby-macho code because
|
8
|
-
# fat headers are always big-endian and therefore always unpacked as such.
|
9
|
-
# @api private
|
10
|
-
FAT_CIGAM = 0xbebafeca
|
11
|
-
|
12
|
-
# 32-bit big-endian magic
|
13
|
-
# @api private
|
14
|
-
MH_MAGIC = 0xfeedface
|
15
|
-
|
16
|
-
# 32-bit little-endian magic
|
17
|
-
# @api private
|
18
|
-
MH_CIGAM = 0xcefaedfe
|
19
|
-
|
20
|
-
# 64-bit big-endian magic
|
21
|
-
# @api private
|
22
|
-
MH_MAGIC_64 = 0xfeedfacf
|
23
|
-
|
24
|
-
# 64-bit little-endian magic
|
25
|
-
# @api private
|
26
|
-
MH_CIGAM_64 = 0xcffaedfe
|
27
|
-
|
28
|
-
# association of magic numbers to string representations
|
29
|
-
# @api private
|
30
|
-
MH_MAGICS = {
|
31
|
-
FAT_MAGIC => "FAT_MAGIC",
|
32
|
-
MH_MAGIC => "MH_MAGIC",
|
33
|
-
MH_CIGAM => "MH_CIGAM",
|
34
|
-
MH_MAGIC_64 => "MH_MAGIC_64",
|
35
|
-
MH_CIGAM_64 => "MH_CIGAM_64",
|
36
|
-
}.freeze
|
37
|
-
|
38
|
-
# mask for CPUs with 64-bit architectures (when running a 64-bit ABI?)
|
39
|
-
# @api private
|
40
|
-
CPU_ARCH_ABI64 = 0x01000000
|
41
|
-
|
42
|
-
# any CPU (unused?)
|
43
|
-
# @api private
|
44
|
-
CPU_TYPE_ANY = -1
|
45
|
-
|
46
|
-
# m68k compatible CPUs
|
47
|
-
# @api private
|
48
|
-
CPU_TYPE_MC680X0 = 0x06
|
49
|
-
|
50
|
-
# i386 and later compatible CPUs
|
51
|
-
# @api private
|
52
|
-
CPU_TYPE_I386 = 0x07
|
53
|
-
|
54
|
-
# x86_64 (AMD64) compatible CPUs
|
55
|
-
# @api private
|
56
|
-
CPU_TYPE_X86_64 = (CPU_TYPE_I386 | CPU_ARCH_ABI64)
|
57
|
-
|
58
|
-
# 32-bit ARM compatible CPUs
|
59
|
-
# @api private
|
60
|
-
CPU_TYPE_ARM = 0x0c
|
61
|
-
|
62
|
-
# m88k compatible CPUs
|
63
|
-
# @api private
|
64
|
-
CPU_TYPE_MC88000 = 0xd
|
65
|
-
|
66
|
-
# 64-bit ARM compatible CPUs
|
67
|
-
# @api private
|
68
|
-
CPU_TYPE_ARM64 = (CPU_TYPE_ARM | CPU_ARCH_ABI64)
|
69
|
-
|
70
|
-
# PowerPC compatible CPUs
|
71
|
-
# @api private
|
72
|
-
CPU_TYPE_POWERPC = 0x12
|
73
|
-
|
74
|
-
# PowerPC64 compatible CPUs
|
75
|
-
# @api private
|
76
|
-
CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
|
77
|
-
|
78
|
-
# association of cpu types to symbol representations
|
79
|
-
# @api private
|
80
|
-
CPU_TYPES = {
|
81
|
-
CPU_TYPE_ANY => :any,
|
82
|
-
CPU_TYPE_I386 => :i386,
|
83
|
-
CPU_TYPE_X86_64 => :x86_64,
|
84
|
-
CPU_TYPE_ARM => :arm,
|
85
|
-
CPU_TYPE_ARM64 => :arm64,
|
86
|
-
CPU_TYPE_POWERPC => :ppc,
|
87
|
-
CPU_TYPE_POWERPC64 => :ppc64,
|
88
|
-
}.freeze
|
89
|
-
|
90
|
-
# mask for CPU subtype capabilities
|
91
|
-
# @api private
|
92
|
-
CPU_SUBTYPE_MASK = 0xff000000
|
93
|
-
|
94
|
-
# 64-bit libraries (undocumented!)
|
95
|
-
# @see http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
|
96
|
-
# @api private
|
97
|
-
CPU_SUBTYPE_LIB64 = 0x80000000
|
98
|
-
|
99
|
-
# the lowest common sub-type for `CPU_TYPE_I386`
|
100
|
-
# @api private
|
101
|
-
CPU_SUBTYPE_I386 = 3
|
102
|
-
|
103
|
-
# the i486 sub-type for `CPU_TYPE_I386`
|
104
|
-
# @api private
|
105
|
-
CPU_SUBTYPE_486 = 4
|
106
|
-
|
107
|
-
# the i486SX sub-type for `CPU_TYPE_I386`
|
108
|
-
# @api private
|
109
|
-
CPU_SUBTYPE_486SX = 132
|
110
|
-
|
111
|
-
# the i586 (P5, Pentium) sub-type for `CPU_TYPE_I386`
|
112
|
-
# @api private
|
113
|
-
CPU_SUBTYPE_586 = 5
|
114
|
-
|
115
|
-
# @see CPU_SUBTYPE_586
|
116
|
-
# @api private
|
117
|
-
CPU_SUBTYPE_PENT = CPU_SUBTYPE_586
|
118
|
-
|
119
|
-
# the Pentium Pro (P6) sub-type for `CPU_TYPE_I386`
|
120
|
-
# @api private
|
121
|
-
CPU_SUBTYPE_PENTPRO = 22
|
122
|
-
|
123
|
-
# the Pentium II (P6, M3?) sub-type for `CPU_TYPE_I386`
|
124
|
-
# @api private
|
125
|
-
CPU_SUBTYPE_PENTII_M3 = 54
|
126
|
-
|
127
|
-
# the Pentium II (P6, M5?) sub-type for `CPU_TYPE_I386`
|
128
|
-
# @api private
|
129
|
-
CPU_SUBTYPE_PENTII_M5 = 86
|
130
|
-
|
131
|
-
# the Pentium 4 (Netburst) sub-type for `CPU_TYPE_I386`
|
132
|
-
# @api private
|
133
|
-
CPU_SUBTYPE_PENTIUM_4 = 10
|
134
|
-
|
135
|
-
# the lowest common sub-type for `CPU_TYPE_MC680X0`
|
136
|
-
# @api private
|
137
|
-
CPU_SUBTYPE_MC680X0_ALL = 1
|
138
|
-
|
139
|
-
# @see CPU_SUBTYPE_MC680X0_ALL
|
140
|
-
# @api private
|
141
|
-
CPU_SUBTYPE_MC68030 = CPU_SUBTYPE_MC680X0_ALL
|
142
|
-
|
143
|
-
# the 040 subtype for `CPU_TYPE_MC680X0`
|
144
|
-
# @api private
|
145
|
-
CPU_SUBTYPE_MC68040 = 2
|
146
|
-
|
147
|
-
# the 030 subtype for `CPU_TYPE_MC680X0`
|
148
|
-
# @api private
|
149
|
-
CPU_SUBTYPE_MC68030_ONLY = 3
|
150
|
-
|
151
|
-
# the lowest common sub-type for `CPU_TYPE_X86_64`
|
152
|
-
# @api private
|
153
|
-
CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_I386
|
154
|
-
|
155
|
-
# the Haskell sub-type for `CPU_TYPE_X86_64`
|
156
|
-
# @api private
|
157
|
-
CPU_SUBTYPE_X86_64_H = 8
|
158
|
-
|
159
|
-
# the lowest common sub-type for `CPU_TYPE_ARM`
|
160
|
-
# @api private
|
161
|
-
CPU_SUBTYPE_ARM_ALL = 0
|
162
|
-
|
163
|
-
# the v4t sub-type for `CPU_TYPE_ARM`
|
164
|
-
# @api private
|
165
|
-
CPU_SUBTYPE_ARM_V4T = 5
|
166
|
-
|
167
|
-
# the v6 sub-type for `CPU_TYPE_ARM`
|
168
|
-
# @api private
|
169
|
-
CPU_SUBTYPE_ARM_V6 = 6
|
170
|
-
|
171
|
-
# the v5 sub-type for `CPU_TYPE_ARM`
|
172
|
-
# @api private
|
173
|
-
CPU_SUBTYPE_ARM_V5TEJ = 7
|
174
|
-
|
175
|
-
# the xscale (v5 family) sub-type for `CPU_TYPE_ARM`
|
176
|
-
# @api private
|
177
|
-
CPU_SUBTYPE_ARM_XSCALE = 8
|
178
|
-
|
179
|
-
# the v7 sub-type for `CPU_TYPE_ARM`
|
180
|
-
# @api private
|
181
|
-
CPU_SUBTYPE_ARM_V7 = 9
|
182
|
-
|
183
|
-
# the v7f (Cortex A9) sub-type for `CPU_TYPE_ARM`
|
184
|
-
# @api private
|
185
|
-
CPU_SUBTYPE_ARM_V7F = 10
|
2
|
+
# Classes and constants for parsing the headers of Mach-O binaries.
|
3
|
+
module Headers
|
4
|
+
# big-endian fat magic
|
5
|
+
# @api private
|
6
|
+
FAT_MAGIC = 0xcafebabe
|
186
7
|
|
187
|
-
|
188
|
-
|
189
|
-
|
8
|
+
# little-endian fat magic
|
9
|
+
# this is defined, but should never appear in ruby-macho code because
|
10
|
+
# fat headers are always big-endian and therefore always unpacked as such.
|
11
|
+
# @api private
|
12
|
+
FAT_CIGAM = 0xbebafeca
|
190
13
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
# the v6m sub-type for `CPU_TYPE_ARM`
|
196
|
-
# @api private
|
197
|
-
CPU_SUBTYPE_ARM_V6M = 14
|
198
|
-
|
199
|
-
# the v7m sub-type for `CPU_TYPE_ARM`
|
200
|
-
# @api private
|
201
|
-
CPU_SUBTYPE_ARM_V7M = 15
|
202
|
-
|
203
|
-
# the v7em sub-type for `CPU_TYPE_ARM`
|
204
|
-
# @api private
|
205
|
-
CPU_SUBTYPE_ARM_V7EM = 16
|
206
|
-
|
207
|
-
# the v8 sub-type for `CPU_TYPE_ARM`
|
208
|
-
# @api private
|
209
|
-
CPU_SUBTYPE_ARM_V8 = 13
|
210
|
-
|
211
|
-
# the lowest common sub-type for `CPU_TYPE_ARM64`
|
212
|
-
# @api private
|
213
|
-
CPU_SUBTYPE_ARM64_ALL = 0
|
214
|
-
|
215
|
-
# the v8 sub-type for `CPU_TYPE_ARM64`
|
216
|
-
# @api private
|
217
|
-
CPU_SUBTYPE_ARM64_V8 = 1
|
218
|
-
|
219
|
-
# the lowest common sub-type for `CPU_TYPE_MC88000`
|
220
|
-
# @api private
|
221
|
-
CPU_SUBTYPE_MC88000_ALL = 0
|
222
|
-
|
223
|
-
# @see CPU_SUBTYPE_MC88000_ALL
|
224
|
-
# @api private
|
225
|
-
CPU_SUBTYPE_MMAX_JPC = CPU_SUBTYPE_MC88000_ALL
|
226
|
-
|
227
|
-
# the 100 sub-type for `CPU_TYPE_MC88000`
|
228
|
-
# @api private
|
229
|
-
CPU_SUBTYPE_MC88100 = 1
|
230
|
-
|
231
|
-
# the 110 sub-type for `CPU_TYPE_MC88000`
|
232
|
-
# @api private
|
233
|
-
CPU_SUBTYPE_MC88110 = 2
|
234
|
-
|
235
|
-
# the lowest common sub-type for `CPU_TYPE_POWERPC`
|
236
|
-
# @api private
|
237
|
-
CPU_SUBTYPE_POWERPC_ALL = 0
|
238
|
-
|
239
|
-
# the 601 sub-type for `CPU_TYPE_POWERPC`
|
240
|
-
# @api private
|
241
|
-
CPU_SUBTYPE_POWERPC_601 = 1
|
242
|
-
|
243
|
-
# the 602 sub-type for `CPU_TYPE_POWERPC`
|
244
|
-
# @api private
|
245
|
-
CPU_SUBTYPE_POWERPC_602 = 2
|
246
|
-
|
247
|
-
# the 603 sub-type for `CPU_TYPE_POWERPC`
|
248
|
-
# @api private
|
249
|
-
CPU_SUBTYPE_POWERPC_603 = 3
|
250
|
-
|
251
|
-
# the 603e (G2) sub-type for `CPU_TYPE_POWERPC`
|
252
|
-
# @api private
|
253
|
-
CPU_SUBTYPE_POWERPC_603E = 4
|
254
|
-
|
255
|
-
# the 603ev sub-type for `CPU_TYPE_POWERPC`
|
256
|
-
# @api private
|
257
|
-
CPU_SUBTYPE_POWERPC_603EV = 5
|
258
|
-
|
259
|
-
# the 604 sub-type for `CPU_TYPE_POWERPC`
|
260
|
-
# @api private
|
261
|
-
CPU_SUBTYPE_POWERPC_604 = 6
|
262
|
-
|
263
|
-
# the 604e sub-type for `CPU_TYPE_POWERPC`
|
264
|
-
# @api private
|
265
|
-
CPU_SUBTYPE_POWERPC_604E = 7
|
266
|
-
|
267
|
-
# the 620 sub-type for `CPU_TYPE_POWERPC`
|
268
|
-
# @api private
|
269
|
-
CPU_SUBTYPE_POWERPC_620 = 8
|
270
|
-
|
271
|
-
# the 750 (G3) sub-type for `CPU_TYPE_POWERPC`
|
272
|
-
# @api private
|
273
|
-
CPU_SUBTYPE_POWERPC_750 = 9
|
274
|
-
|
275
|
-
# the 7400 (G4) sub-type for `CPU_TYPE_POWERPC`
|
276
|
-
# @api private
|
277
|
-
CPU_SUBTYPE_POWERPC_7400 = 10
|
278
|
-
|
279
|
-
# the 7450 (G4 "Voyager") sub-type for `CPU_TYPE_POWERPC`
|
280
|
-
# @api private
|
281
|
-
CPU_SUBTYPE_POWERPC_7450 = 11
|
282
|
-
|
283
|
-
# the 970 (G5) sub-type for `CPU_TYPE_POWERPC`
|
284
|
-
# @api private
|
285
|
-
CPU_SUBTYPE_POWERPC_970 = 100
|
286
|
-
|
287
|
-
# any CPU sub-type for CPU type `CPU_TYPE_POWERPC64`
|
288
|
-
# @api private
|
289
|
-
CPU_SUBTYPE_POWERPC64_ALL = CPU_SUBTYPE_POWERPC_ALL
|
290
|
-
|
291
|
-
# association of CPU types/subtype pairs to symbol representations in
|
292
|
-
# (very) roughly descending order of commonness
|
293
|
-
# @see https://opensource.apple.com/source/cctools/cctools-877.8/libstuff/arch.c
|
294
|
-
# @api private
|
295
|
-
CPU_SUBTYPES = {
|
296
|
-
CPU_TYPE_I386 => {
|
297
|
-
CPU_SUBTYPE_I386 => :i386,
|
298
|
-
CPU_SUBTYPE_486 => :i486,
|
299
|
-
CPU_SUBTYPE_486SX => :i486SX,
|
300
|
-
CPU_SUBTYPE_586 => :i586, # also "pentium" in arch(3)
|
301
|
-
CPU_SUBTYPE_PENTPRO => :i686, # also "pentpro" in arch(3)
|
302
|
-
CPU_SUBTYPE_PENTII_M3 => :pentIIm3,
|
303
|
-
CPU_SUBTYPE_PENTII_M5 => :pentIIm5,
|
304
|
-
CPU_SUBTYPE_PENTIUM_4 => :pentium4,
|
305
|
-
}.freeze,
|
306
|
-
CPU_TYPE_X86_64 => {
|
307
|
-
CPU_SUBTYPE_X86_64_ALL => :x86_64,
|
308
|
-
CPU_SUBTYPE_X86_64_H => :x86_64h,
|
309
|
-
}.freeze,
|
310
|
-
CPU_TYPE_ARM => {
|
311
|
-
CPU_SUBTYPE_ARM_ALL => :arm,
|
312
|
-
CPU_SUBTYPE_ARM_V4T => :armv4t,
|
313
|
-
CPU_SUBTYPE_ARM_V6 => :armv6,
|
314
|
-
CPU_SUBTYPE_ARM_V5TEJ => :armv5,
|
315
|
-
CPU_SUBTYPE_ARM_XSCALE => :xscale,
|
316
|
-
CPU_SUBTYPE_ARM_V7 => :armv7,
|
317
|
-
CPU_SUBTYPE_ARM_V7F => :armv7f,
|
318
|
-
CPU_SUBTYPE_ARM_V7S => :armv7s,
|
319
|
-
CPU_SUBTYPE_ARM_V7K => :armv7k,
|
320
|
-
CPU_SUBTYPE_ARM_V6M => :armv6m,
|
321
|
-
CPU_SUBTYPE_ARM_V7M => :armv7m,
|
322
|
-
CPU_SUBTYPE_ARM_V7EM => :armv7em,
|
323
|
-
CPU_SUBTYPE_ARM_V8 => :armv8,
|
324
|
-
}.freeze,
|
325
|
-
CPU_TYPE_ARM64 => {
|
326
|
-
CPU_SUBTYPE_ARM64_ALL => :arm64,
|
327
|
-
CPU_SUBTYPE_ARM64_V8 => :arm64v8,
|
328
|
-
}.freeze,
|
329
|
-
CPU_TYPE_POWERPC => {
|
330
|
-
CPU_SUBTYPE_POWERPC_ALL => :ppc,
|
331
|
-
CPU_SUBTYPE_POWERPC_601 => :ppc601,
|
332
|
-
CPU_SUBTYPE_POWERPC_603 => :ppc603,
|
333
|
-
CPU_SUBTYPE_POWERPC_603E => :ppc603e,
|
334
|
-
CPU_SUBTYPE_POWERPC_603EV => :ppc603ev,
|
335
|
-
CPU_SUBTYPE_POWERPC_604 => :ppc604,
|
336
|
-
CPU_SUBTYPE_POWERPC_604E => :ppc604e,
|
337
|
-
CPU_SUBTYPE_POWERPC_750 => :ppc750,
|
338
|
-
CPU_SUBTYPE_POWERPC_7400 => :ppc7400,
|
339
|
-
CPU_SUBTYPE_POWERPC_7450 => :ppc7450,
|
340
|
-
CPU_SUBTYPE_POWERPC_970 => :ppc970,
|
341
|
-
}.freeze,
|
342
|
-
CPU_TYPE_POWERPC64 => {
|
343
|
-
CPU_SUBTYPE_POWERPC64_ALL => :ppc64,
|
344
|
-
# apparently the only exception to the naming scheme
|
345
|
-
CPU_SUBTYPE_POWERPC_970 => :ppc970_64,
|
346
|
-
}.freeze,
|
347
|
-
CPU_TYPE_MC680X0 => {
|
348
|
-
CPU_SUBTYPE_MC680X0_ALL => :m68k,
|
349
|
-
CPU_SUBTYPE_MC68030 => :mc68030,
|
350
|
-
CPU_SUBTYPE_MC68040 => :mc68040,
|
351
|
-
},
|
352
|
-
CPU_TYPE_MC88000 => {
|
353
|
-
CPU_SUBTYPE_MC88000_ALL => :m88k,
|
354
|
-
},
|
355
|
-
}.freeze
|
356
|
-
|
357
|
-
# relocatable object file
|
358
|
-
# @api private
|
359
|
-
MH_OBJECT = 0x1
|
360
|
-
|
361
|
-
# demand paged executable file
|
362
|
-
# @api private
|
363
|
-
MH_EXECUTE = 0x2
|
364
|
-
|
365
|
-
# fixed VM shared library file
|
366
|
-
# @api private
|
367
|
-
MH_FVMLIB = 0x3
|
368
|
-
|
369
|
-
# core dump file
|
370
|
-
# @api private
|
371
|
-
MH_CORE = 0x4
|
372
|
-
|
373
|
-
# preloaded executable file
|
374
|
-
# @api private
|
375
|
-
MH_PRELOAD = 0x5
|
376
|
-
|
377
|
-
# dynamically bound shared library
|
378
|
-
# @api private
|
379
|
-
MH_DYLIB = 0x6
|
380
|
-
|
381
|
-
# dynamic link editor
|
382
|
-
# @api private
|
383
|
-
MH_DYLINKER = 0x7
|
384
|
-
|
385
|
-
# dynamically bound bundle file
|
386
|
-
# @api private
|
387
|
-
MH_BUNDLE = 0x8
|
388
|
-
|
389
|
-
# shared library stub for static linking only, no section contents
|
390
|
-
# @api private
|
391
|
-
MH_DYLIB_STUB = 0x9
|
392
|
-
|
393
|
-
# companion file with only debug sections
|
394
|
-
# @api private
|
395
|
-
MH_DSYM = 0xa
|
396
|
-
|
397
|
-
# x86_64 kexts
|
398
|
-
# @api private
|
399
|
-
MH_KEXT_BUNDLE = 0xb
|
400
|
-
|
401
|
-
# association of filetypes to Symbol representations
|
402
|
-
# @api private
|
403
|
-
MH_FILETYPES = {
|
404
|
-
MH_OBJECT => :object,
|
405
|
-
MH_EXECUTE => :execute,
|
406
|
-
MH_FVMLIB => :fvmlib,
|
407
|
-
MH_CORE => :core,
|
408
|
-
MH_PRELOAD => :preload,
|
409
|
-
MH_DYLIB => :dylib,
|
410
|
-
MH_DYLINKER => :dylinker,
|
411
|
-
MH_BUNDLE => :bundle,
|
412
|
-
MH_DYLIB_STUB => :dylib_stub,
|
413
|
-
MH_DSYM => :dsym,
|
414
|
-
MH_KEXT_BUNDLE => :kext_bundle,
|
415
|
-
}.freeze
|
416
|
-
|
417
|
-
# association of mach header flag symbols to values
|
418
|
-
# @api private
|
419
|
-
MH_FLAGS = {
|
420
|
-
:MH_NOUNDEFS => 0x1,
|
421
|
-
:MH_INCRLINK => 0x2,
|
422
|
-
:MH_DYLDLINK => 0x4,
|
423
|
-
:MH_BINDATLOAD => 0x8,
|
424
|
-
:MH_PREBOUND => 0x10,
|
425
|
-
:MH_SPLIT_SEGS => 0x20,
|
426
|
-
:MH_LAZY_INIT => 0x40,
|
427
|
-
:MH_TWOLEVEL => 0x80,
|
428
|
-
:MH_FORCE_FLAT => 0x100,
|
429
|
-
:MH_NOMULTIDEFS => 0x200,
|
430
|
-
:MH_NOPREFIXBINDING => 0x400,
|
431
|
-
:MH_PREBINDABLE => 0x800,
|
432
|
-
:MH_ALLMODSBOUND => 0x1000,
|
433
|
-
:MH_SUBSECTIONS_VIA_SYMBOLS => 0x2000,
|
434
|
-
:MH_CANONICAL => 0x4000,
|
435
|
-
:MH_WEAK_DEFINES => 0x8000,
|
436
|
-
:MH_BINDS_TO_WEAK => 0x10000,
|
437
|
-
:MH_ALLOW_STACK_EXECUTION => 0x20000,
|
438
|
-
:MH_ROOT_SAFE => 0x40000,
|
439
|
-
:MH_SETUID_SAFE => 0x80000,
|
440
|
-
:MH_NO_REEXPORTED_DYLIBS => 0x100000,
|
441
|
-
:MH_PIE => 0x200000,
|
442
|
-
:MH_DEAD_STRIPPABLE_DYLIB => 0x400000,
|
443
|
-
:MH_HAS_TLV_DESCRIPTORS => 0x800000,
|
444
|
-
:MH_NO_HEAP_EXECUTION => 0x1000000,
|
445
|
-
:MH_APP_EXTENSION_SAFE => 0x02000000,
|
446
|
-
}.freeze
|
447
|
-
|
448
|
-
# Fat binary header structure
|
449
|
-
# @see MachO::FatArch
|
450
|
-
class FatHeader < MachOStructure
|
451
|
-
# @return [Fixnum] the magic number of the header (and file)
|
452
|
-
attr_reader :magic
|
453
|
-
|
454
|
-
# @return [Fixnum] the number of fat architecture structures following the header
|
455
|
-
attr_reader :nfat_arch
|
456
|
-
|
457
|
-
# always big-endian
|
458
|
-
# @see MachOStructure::FORMAT
|
459
|
-
# @api private
|
460
|
-
FORMAT = "N2".freeze
|
461
|
-
|
462
|
-
# @see MachOStructure::SIZEOF
|
463
|
-
# @api private
|
464
|
-
SIZEOF = 8
|
465
|
-
|
466
|
-
# @api private
|
467
|
-
def initialize(magic, nfat_arch)
|
468
|
-
@magic = magic
|
469
|
-
@nfat_arch = nfat_arch
|
470
|
-
end
|
471
|
-
end
|
14
|
+
# 32-bit big-endian magic
|
15
|
+
# @api private
|
16
|
+
MH_MAGIC = 0xfeedface
|
472
17
|
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
class FatArch < MachOStructure
|
477
|
-
# @return [Fixnum] the CPU type of the Mach-O
|
478
|
-
attr_reader :cputype
|
18
|
+
# 32-bit little-endian magic
|
19
|
+
# @api private
|
20
|
+
MH_CIGAM = 0xcefaedfe
|
479
21
|
|
480
|
-
#
|
481
|
-
|
22
|
+
# 64-bit big-endian magic
|
23
|
+
# @api private
|
24
|
+
MH_MAGIC_64 = 0xfeedfacf
|
482
25
|
|
483
|
-
#
|
484
|
-
|
26
|
+
# 64-bit little-endian magic
|
27
|
+
# @api private
|
28
|
+
MH_CIGAM_64 = 0xcffaedfe
|
485
29
|
|
486
|
-
#
|
487
|
-
|
30
|
+
# association of magic numbers to string representations
|
31
|
+
# @api private
|
32
|
+
MH_MAGICS = {
|
33
|
+
FAT_MAGIC => "FAT_MAGIC",
|
34
|
+
MH_MAGIC => "MH_MAGIC",
|
35
|
+
MH_CIGAM => "MH_CIGAM",
|
36
|
+
MH_MAGIC_64 => "MH_MAGIC_64",
|
37
|
+
MH_CIGAM_64 => "MH_CIGAM_64",
|
38
|
+
}.freeze
|
39
|
+
|
40
|
+
# mask for CPUs with 64-bit architectures (when running a 64-bit ABI?)
|
41
|
+
# @api private
|
42
|
+
CPU_ARCH_ABI64 = 0x01000000
|
488
43
|
|
489
|
-
#
|
490
|
-
|
44
|
+
# any CPU (unused?)
|
45
|
+
# @api private
|
46
|
+
CPU_TYPE_ANY = -1
|
491
47
|
|
492
|
-
#
|
493
|
-
# @see MachOStructure::FORMAT
|
48
|
+
# m68k compatible CPUs
|
494
49
|
# @api private
|
495
|
-
|
50
|
+
CPU_TYPE_MC680X0 = 0x06
|
496
51
|
|
497
|
-
#
|
52
|
+
# i386 and later compatible CPUs
|
498
53
|
# @api private
|
499
|
-
|
54
|
+
CPU_TYPE_I386 = 0x07
|
500
55
|
|
56
|
+
# x86_64 (AMD64) compatible CPUs
|
501
57
|
# @api private
|
502
|
-
|
503
|
-
@cputype = cputype
|
504
|
-
@cpusubtype = cpusubtype
|
505
|
-
@offset = offset
|
506
|
-
@size = size
|
507
|
-
@align = align
|
508
|
-
end
|
509
|
-
end
|
58
|
+
CPU_TYPE_X86_64 = (CPU_TYPE_I386 | CPU_ARCH_ABI64)
|
510
59
|
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
attr_reader :magic
|
60
|
+
# 32-bit ARM compatible CPUs
|
61
|
+
# @api private
|
62
|
+
CPU_TYPE_ARM = 0x0c
|
515
63
|
|
516
|
-
#
|
517
|
-
|
64
|
+
# m88k compatible CPUs
|
65
|
+
# @api private
|
66
|
+
CPU_TYPE_MC88000 = 0xd
|
518
67
|
|
519
|
-
#
|
520
|
-
|
68
|
+
# 64-bit ARM compatible CPUs
|
69
|
+
# @api private
|
70
|
+
CPU_TYPE_ARM64 = (CPU_TYPE_ARM | CPU_ARCH_ABI64)
|
521
71
|
|
522
|
-
#
|
523
|
-
|
72
|
+
# PowerPC compatible CPUs
|
73
|
+
# @api private
|
74
|
+
CPU_TYPE_POWERPC = 0x12
|
524
75
|
|
525
|
-
#
|
526
|
-
|
76
|
+
# PowerPC64 compatible CPUs
|
77
|
+
# @api private
|
78
|
+
CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
|
527
79
|
|
528
|
-
#
|
529
|
-
|
80
|
+
# association of cpu types to symbol representations
|
81
|
+
# @api private
|
82
|
+
CPU_TYPES = {
|
83
|
+
CPU_TYPE_ANY => :any,
|
84
|
+
CPU_TYPE_I386 => :i386,
|
85
|
+
CPU_TYPE_X86_64 => :x86_64,
|
86
|
+
CPU_TYPE_ARM => :arm,
|
87
|
+
CPU_TYPE_ARM64 => :arm64,
|
88
|
+
CPU_TYPE_POWERPC => :ppc,
|
89
|
+
CPU_TYPE_POWERPC64 => :ppc64,
|
90
|
+
}.freeze
|
91
|
+
|
92
|
+
# mask for CPU subtype capabilities
|
93
|
+
# @api private
|
94
|
+
CPU_SUBTYPE_MASK = 0xff000000
|
530
95
|
|
531
|
-
#
|
532
|
-
|
96
|
+
# 64-bit libraries (undocumented!)
|
97
|
+
# @see http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
|
98
|
+
# @api private
|
99
|
+
CPU_SUBTYPE_LIB64 = 0x80000000
|
533
100
|
|
534
|
-
#
|
101
|
+
# the lowest common sub-type for `CPU_TYPE_I386`
|
535
102
|
# @api private
|
536
|
-
|
103
|
+
CPU_SUBTYPE_I386 = 3
|
537
104
|
|
538
|
-
#
|
105
|
+
# the i486 sub-type for `CPU_TYPE_I386`
|
539
106
|
# @api private
|
540
|
-
|
107
|
+
CPU_SUBTYPE_486 = 4
|
541
108
|
|
109
|
+
# the i486SX sub-type for `CPU_TYPE_I386`
|
542
110
|
# @api private
|
543
|
-
|
544
|
-
flags)
|
545
|
-
@magic = magic
|
546
|
-
@cputype = cputype
|
547
|
-
# For now we're not interested in additional capability bits also to be
|
548
|
-
# found in the `cpusubtype` field. We only care about the CPU sub-type.
|
549
|
-
@cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK
|
550
|
-
@filetype = filetype
|
551
|
-
@ncmds = ncmds
|
552
|
-
@sizeofcmds = sizeofcmds
|
553
|
-
@flags = flags
|
554
|
-
end
|
111
|
+
CPU_SUBTYPE_486SX = 132
|
555
112
|
|
556
|
-
#
|
557
|
-
#
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
113
|
+
# the i586 (P5, Pentium) sub-type for `CPU_TYPE_I386`
|
114
|
+
# @api private
|
115
|
+
CPU_SUBTYPE_586 = 5
|
116
|
+
|
117
|
+
# @see CPU_SUBTYPE_586
|
118
|
+
# @api private
|
119
|
+
CPU_SUBTYPE_PENT = CPU_SUBTYPE_586
|
120
|
+
|
121
|
+
# the Pentium Pro (P6) sub-type for `CPU_TYPE_I386`
|
122
|
+
# @api private
|
123
|
+
CPU_SUBTYPE_PENTPRO = 22
|
124
|
+
|
125
|
+
# the Pentium II (P6, M3?) sub-type for `CPU_TYPE_I386`
|
126
|
+
# @api private
|
127
|
+
CPU_SUBTYPE_PENTII_M3 = 54
|
128
|
+
|
129
|
+
# the Pentium II (P6, M5?) sub-type for `CPU_TYPE_I386`
|
130
|
+
# @api private
|
131
|
+
CPU_SUBTYPE_PENTII_M5 = 86
|
132
|
+
|
133
|
+
# the Pentium 4 (Netburst) sub-type for `CPU_TYPE_I386`
|
134
|
+
# @api private
|
135
|
+
CPU_SUBTYPE_PENTIUM_4 = 10
|
136
|
+
|
137
|
+
# the lowest common sub-type for `CPU_TYPE_MC680X0`
|
138
|
+
# @api private
|
139
|
+
CPU_SUBTYPE_MC680X0_ALL = 1
|
140
|
+
|
141
|
+
# @see CPU_SUBTYPE_MC680X0_ALL
|
142
|
+
# @api private
|
143
|
+
CPU_SUBTYPE_MC68030 = CPU_SUBTYPE_MC680X0_ALL
|
144
|
+
|
145
|
+
# the 040 subtype for `CPU_TYPE_MC680X0`
|
146
|
+
# @api private
|
147
|
+
CPU_SUBTYPE_MC68040 = 2
|
148
|
+
|
149
|
+
# the 030 subtype for `CPU_TYPE_MC680X0`
|
150
|
+
# @api private
|
151
|
+
CPU_SUBTYPE_MC68030_ONLY = 3
|
152
|
+
|
153
|
+
# the lowest common sub-type for `CPU_TYPE_X86_64`
|
154
|
+
# @api private
|
155
|
+
CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_I386
|
156
|
+
|
157
|
+
# the Haskell sub-type for `CPU_TYPE_X86_64`
|
158
|
+
# @api private
|
159
|
+
CPU_SUBTYPE_X86_64_H = 8
|
160
|
+
|
161
|
+
# the lowest common sub-type for `CPU_TYPE_ARM`
|
162
|
+
# @api private
|
163
|
+
CPU_SUBTYPE_ARM_ALL = 0
|
164
|
+
|
165
|
+
# the v4t sub-type for `CPU_TYPE_ARM`
|
166
|
+
# @api private
|
167
|
+
CPU_SUBTYPE_ARM_V4T = 5
|
168
|
+
|
169
|
+
# the v6 sub-type for `CPU_TYPE_ARM`
|
170
|
+
# @api private
|
171
|
+
CPU_SUBTYPE_ARM_V6 = 6
|
172
|
+
|
173
|
+
# the v5 sub-type for `CPU_TYPE_ARM`
|
174
|
+
# @api private
|
175
|
+
CPU_SUBTYPE_ARM_V5TEJ = 7
|
176
|
+
|
177
|
+
# the xscale (v5 family) sub-type for `CPU_TYPE_ARM`
|
178
|
+
# @api private
|
179
|
+
CPU_SUBTYPE_ARM_XSCALE = 8
|
180
|
+
|
181
|
+
# the v7 sub-type for `CPU_TYPE_ARM`
|
182
|
+
# @api private
|
183
|
+
CPU_SUBTYPE_ARM_V7 = 9
|
184
|
+
|
185
|
+
# the v7f (Cortex A9) sub-type for `CPU_TYPE_ARM`
|
186
|
+
# @api private
|
187
|
+
CPU_SUBTYPE_ARM_V7F = 10
|
188
|
+
|
189
|
+
# the v7s ("Swift") sub-type for `CPU_TYPE_ARM`
|
190
|
+
# @api private
|
191
|
+
CPU_SUBTYPE_ARM_V7S = 11
|
192
|
+
|
193
|
+
# the v7k ("Kirkwood40") sub-type for `CPU_TYPE_ARM`
|
194
|
+
# @api private
|
195
|
+
CPU_SUBTYPE_ARM_V7K = 12
|
196
|
+
|
197
|
+
# the v6m sub-type for `CPU_TYPE_ARM`
|
198
|
+
# @api private
|
199
|
+
CPU_SUBTYPE_ARM_V6M = 14
|
200
|
+
|
201
|
+
# the v7m sub-type for `CPU_TYPE_ARM`
|
202
|
+
# @api private
|
203
|
+
CPU_SUBTYPE_ARM_V7M = 15
|
566
204
|
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
205
|
+
# the v7em sub-type for `CPU_TYPE_ARM`
|
206
|
+
# @api private
|
207
|
+
CPU_SUBTYPE_ARM_V7EM = 16
|
208
|
+
|
209
|
+
# the v8 sub-type for `CPU_TYPE_ARM`
|
210
|
+
# @api private
|
211
|
+
CPU_SUBTYPE_ARM_V8 = 13
|
212
|
+
|
213
|
+
# the lowest common sub-type for `CPU_TYPE_ARM64`
|
214
|
+
# @api private
|
215
|
+
CPU_SUBTYPE_ARM64_ALL = 0
|
216
|
+
|
217
|
+
# the v8 sub-type for `CPU_TYPE_ARM64`
|
218
|
+
# @api private
|
219
|
+
CPU_SUBTYPE_ARM64_V8 = 1
|
220
|
+
|
221
|
+
# the lowest common sub-type for `CPU_TYPE_MC88000`
|
222
|
+
# @api private
|
223
|
+
CPU_SUBTYPE_MC88000_ALL = 0
|
224
|
+
|
225
|
+
# @see CPU_SUBTYPE_MC88000_ALL
|
226
|
+
# @api private
|
227
|
+
CPU_SUBTYPE_MMAX_JPC = CPU_SUBTYPE_MC88000_ALL
|
228
|
+
|
229
|
+
# the 100 sub-type for `CPU_TYPE_MC88000`
|
230
|
+
# @api private
|
231
|
+
CPU_SUBTYPE_MC88100 = 1
|
232
|
+
|
233
|
+
# the 110 sub-type for `CPU_TYPE_MC88000`
|
234
|
+
# @api private
|
235
|
+
CPU_SUBTYPE_MC88110 = 2
|
236
|
+
|
237
|
+
# the lowest common sub-type for `CPU_TYPE_POWERPC`
|
238
|
+
# @api private
|
239
|
+
CPU_SUBTYPE_POWERPC_ALL = 0
|
240
|
+
|
241
|
+
# the 601 sub-type for `CPU_TYPE_POWERPC`
|
242
|
+
# @api private
|
243
|
+
CPU_SUBTYPE_POWERPC_601 = 1
|
244
|
+
|
245
|
+
# the 602 sub-type for `CPU_TYPE_POWERPC`
|
246
|
+
# @api private
|
247
|
+
CPU_SUBTYPE_POWERPC_602 = 2
|
248
|
+
|
249
|
+
# the 603 sub-type for `CPU_TYPE_POWERPC`
|
250
|
+
# @api private
|
251
|
+
CPU_SUBTYPE_POWERPC_603 = 3
|
252
|
+
|
253
|
+
# the 603e (G2) sub-type for `CPU_TYPE_POWERPC`
|
254
|
+
# @api private
|
255
|
+
CPU_SUBTYPE_POWERPC_603E = 4
|
256
|
+
|
257
|
+
# the 603ev sub-type for `CPU_TYPE_POWERPC`
|
258
|
+
# @api private
|
259
|
+
CPU_SUBTYPE_POWERPC_603EV = 5
|
260
|
+
|
261
|
+
# the 604 sub-type for `CPU_TYPE_POWERPC`
|
262
|
+
# @api private
|
263
|
+
CPU_SUBTYPE_POWERPC_604 = 6
|
264
|
+
|
265
|
+
# the 604e sub-type for `CPU_TYPE_POWERPC`
|
266
|
+
# @api private
|
267
|
+
CPU_SUBTYPE_POWERPC_604E = 7
|
268
|
+
|
269
|
+
# the 620 sub-type for `CPU_TYPE_POWERPC`
|
270
|
+
# @api private
|
271
|
+
CPU_SUBTYPE_POWERPC_620 = 8
|
272
|
+
|
273
|
+
# the 750 (G3) sub-type for `CPU_TYPE_POWERPC`
|
274
|
+
# @api private
|
275
|
+
CPU_SUBTYPE_POWERPC_750 = 9
|
571
276
|
|
572
|
-
#
|
277
|
+
# the 7400 (G4) sub-type for `CPU_TYPE_POWERPC`
|
573
278
|
# @api private
|
574
|
-
|
279
|
+
CPU_SUBTYPE_POWERPC_7400 = 10
|
575
280
|
|
576
|
-
#
|
281
|
+
# the 7450 (G4 "Voyager") sub-type for `CPU_TYPE_POWERPC`
|
577
282
|
# @api private
|
578
|
-
|
283
|
+
CPU_SUBTYPE_POWERPC_7450 = 11
|
579
284
|
|
285
|
+
# the 970 (G5) sub-type for `CPU_TYPE_POWERPC`
|
580
286
|
# @api private
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
287
|
+
CPU_SUBTYPE_POWERPC_970 = 100
|
288
|
+
|
289
|
+
# any CPU sub-type for CPU type `CPU_TYPE_POWERPC64`
|
290
|
+
# @api private
|
291
|
+
CPU_SUBTYPE_POWERPC64_ALL = CPU_SUBTYPE_POWERPC_ALL
|
292
|
+
|
293
|
+
# association of CPU types/subtype pairs to symbol representations in
|
294
|
+
# (very) roughly descending order of commonness
|
295
|
+
# @see https://opensource.apple.com/source/cctools/cctools-877.8/libstuff/arch.c
|
296
|
+
# @api private
|
297
|
+
CPU_SUBTYPES = {
|
298
|
+
CPU_TYPE_I386 => {
|
299
|
+
CPU_SUBTYPE_I386 => :i386,
|
300
|
+
CPU_SUBTYPE_486 => :i486,
|
301
|
+
CPU_SUBTYPE_486SX => :i486SX,
|
302
|
+
CPU_SUBTYPE_586 => :i586, # also "pentium" in arch(3)
|
303
|
+
CPU_SUBTYPE_PENTPRO => :i686, # also "pentpro" in arch(3)
|
304
|
+
CPU_SUBTYPE_PENTII_M3 => :pentIIm3,
|
305
|
+
CPU_SUBTYPE_PENTII_M5 => :pentIIm5,
|
306
|
+
CPU_SUBTYPE_PENTIUM_4 => :pentium4,
|
307
|
+
}.freeze,
|
308
|
+
CPU_TYPE_X86_64 => {
|
309
|
+
CPU_SUBTYPE_X86_64_ALL => :x86_64,
|
310
|
+
CPU_SUBTYPE_X86_64_H => :x86_64h,
|
311
|
+
}.freeze,
|
312
|
+
CPU_TYPE_ARM => {
|
313
|
+
CPU_SUBTYPE_ARM_ALL => :arm,
|
314
|
+
CPU_SUBTYPE_ARM_V4T => :armv4t,
|
315
|
+
CPU_SUBTYPE_ARM_V6 => :armv6,
|
316
|
+
CPU_SUBTYPE_ARM_V5TEJ => :armv5,
|
317
|
+
CPU_SUBTYPE_ARM_XSCALE => :xscale,
|
318
|
+
CPU_SUBTYPE_ARM_V7 => :armv7,
|
319
|
+
CPU_SUBTYPE_ARM_V7F => :armv7f,
|
320
|
+
CPU_SUBTYPE_ARM_V7S => :armv7s,
|
321
|
+
CPU_SUBTYPE_ARM_V7K => :armv7k,
|
322
|
+
CPU_SUBTYPE_ARM_V6M => :armv6m,
|
323
|
+
CPU_SUBTYPE_ARM_V7M => :armv7m,
|
324
|
+
CPU_SUBTYPE_ARM_V7EM => :armv7em,
|
325
|
+
CPU_SUBTYPE_ARM_V8 => :armv8,
|
326
|
+
}.freeze,
|
327
|
+
CPU_TYPE_ARM64 => {
|
328
|
+
CPU_SUBTYPE_ARM64_ALL => :arm64,
|
329
|
+
CPU_SUBTYPE_ARM64_V8 => :arm64v8,
|
330
|
+
}.freeze,
|
331
|
+
CPU_TYPE_POWERPC => {
|
332
|
+
CPU_SUBTYPE_POWERPC_ALL => :ppc,
|
333
|
+
CPU_SUBTYPE_POWERPC_601 => :ppc601,
|
334
|
+
CPU_SUBTYPE_POWERPC_603 => :ppc603,
|
335
|
+
CPU_SUBTYPE_POWERPC_603E => :ppc603e,
|
336
|
+
CPU_SUBTYPE_POWERPC_603EV => :ppc603ev,
|
337
|
+
CPU_SUBTYPE_POWERPC_604 => :ppc604,
|
338
|
+
CPU_SUBTYPE_POWERPC_604E => :ppc604e,
|
339
|
+
CPU_SUBTYPE_POWERPC_750 => :ppc750,
|
340
|
+
CPU_SUBTYPE_POWERPC_7400 => :ppc7400,
|
341
|
+
CPU_SUBTYPE_POWERPC_7450 => :ppc7450,
|
342
|
+
CPU_SUBTYPE_POWERPC_970 => :ppc970,
|
343
|
+
}.freeze,
|
344
|
+
CPU_TYPE_POWERPC64 => {
|
345
|
+
CPU_SUBTYPE_POWERPC64_ALL => :ppc64,
|
346
|
+
# apparently the only exception to the naming scheme
|
347
|
+
CPU_SUBTYPE_POWERPC_970 => :ppc970_64,
|
348
|
+
}.freeze,
|
349
|
+
CPU_TYPE_MC680X0 => {
|
350
|
+
CPU_SUBTYPE_MC680X0_ALL => :m68k,
|
351
|
+
CPU_SUBTYPE_MC68030 => :mc68030,
|
352
|
+
CPU_SUBTYPE_MC68040 => :mc68040,
|
353
|
+
},
|
354
|
+
CPU_TYPE_MC88000 => {
|
355
|
+
CPU_SUBTYPE_MC88000_ALL => :m88k,
|
356
|
+
},
|
357
|
+
}.freeze
|
358
|
+
|
359
|
+
# relocatable object file
|
360
|
+
# @api private
|
361
|
+
MH_OBJECT = 0x1
|
362
|
+
|
363
|
+
# demand paged executable file
|
364
|
+
# @api private
|
365
|
+
MH_EXECUTE = 0x2
|
366
|
+
|
367
|
+
# fixed VM shared library file
|
368
|
+
# @api private
|
369
|
+
MH_FVMLIB = 0x3
|
370
|
+
|
371
|
+
# core dump file
|
372
|
+
# @api private
|
373
|
+
MH_CORE = 0x4
|
374
|
+
|
375
|
+
# preloaded executable file
|
376
|
+
# @api private
|
377
|
+
MH_PRELOAD = 0x5
|
378
|
+
|
379
|
+
# dynamically bound shared library
|
380
|
+
# @api private
|
381
|
+
MH_DYLIB = 0x6
|
382
|
+
|
383
|
+
# dynamic link editor
|
384
|
+
# @api private
|
385
|
+
MH_DYLINKER = 0x7
|
386
|
+
|
387
|
+
# dynamically bound bundle file
|
388
|
+
# @api private
|
389
|
+
MH_BUNDLE = 0x8
|
390
|
+
|
391
|
+
# shared library stub for static linking only, no section contents
|
392
|
+
# @api private
|
393
|
+
MH_DYLIB_STUB = 0x9
|
394
|
+
|
395
|
+
# companion file with only debug sections
|
396
|
+
# @api private
|
397
|
+
MH_DSYM = 0xa
|
398
|
+
|
399
|
+
# x86_64 kexts
|
400
|
+
# @api private
|
401
|
+
MH_KEXT_BUNDLE = 0xb
|
402
|
+
|
403
|
+
# association of filetypes to Symbol representations
|
404
|
+
# @api private
|
405
|
+
MH_FILETYPES = {
|
406
|
+
MH_OBJECT => :object,
|
407
|
+
MH_EXECUTE => :execute,
|
408
|
+
MH_FVMLIB => :fvmlib,
|
409
|
+
MH_CORE => :core,
|
410
|
+
MH_PRELOAD => :preload,
|
411
|
+
MH_DYLIB => :dylib,
|
412
|
+
MH_DYLINKER => :dylinker,
|
413
|
+
MH_BUNDLE => :bundle,
|
414
|
+
MH_DYLIB_STUB => :dylib_stub,
|
415
|
+
MH_DSYM => :dsym,
|
416
|
+
MH_KEXT_BUNDLE => :kext_bundle,
|
417
|
+
}.freeze
|
418
|
+
|
419
|
+
# association of mach header flag symbols to values
|
420
|
+
# @api private
|
421
|
+
MH_FLAGS = {
|
422
|
+
:MH_NOUNDEFS => 0x1,
|
423
|
+
:MH_INCRLINK => 0x2,
|
424
|
+
:MH_DYLDLINK => 0x4,
|
425
|
+
:MH_BINDATLOAD => 0x8,
|
426
|
+
:MH_PREBOUND => 0x10,
|
427
|
+
:MH_SPLIT_SEGS => 0x20,
|
428
|
+
:MH_LAZY_INIT => 0x40,
|
429
|
+
:MH_TWOLEVEL => 0x80,
|
430
|
+
:MH_FORCE_FLAT => 0x100,
|
431
|
+
:MH_NOMULTIDEFS => 0x200,
|
432
|
+
:MH_NOPREFIXBINDING => 0x400,
|
433
|
+
:MH_PREBINDABLE => 0x800,
|
434
|
+
:MH_ALLMODSBOUND => 0x1000,
|
435
|
+
:MH_SUBSECTIONS_VIA_SYMBOLS => 0x2000,
|
436
|
+
:MH_CANONICAL => 0x4000,
|
437
|
+
:MH_WEAK_DEFINES => 0x8000,
|
438
|
+
:MH_BINDS_TO_WEAK => 0x10000,
|
439
|
+
:MH_ALLOW_STACK_EXECUTION => 0x20000,
|
440
|
+
:MH_ROOT_SAFE => 0x40000,
|
441
|
+
:MH_SETUID_SAFE => 0x80000,
|
442
|
+
:MH_NO_REEXPORTED_DYLIBS => 0x100000,
|
443
|
+
:MH_PIE => 0x200000,
|
444
|
+
:MH_DEAD_STRIPPABLE_DYLIB => 0x400000,
|
445
|
+
:MH_HAS_TLV_DESCRIPTORS => 0x800000,
|
446
|
+
:MH_NO_HEAP_EXECUTION => 0x1000000,
|
447
|
+
:MH_APP_EXTENSION_SAFE => 0x02000000,
|
448
|
+
}.freeze
|
449
|
+
|
450
|
+
# Fat binary header structure
|
451
|
+
# @see MachO::FatArch
|
452
|
+
class FatHeader < MachOStructure
|
453
|
+
# @return [Fixnum] the magic number of the header (and file)
|
454
|
+
attr_reader :magic
|
455
|
+
|
456
|
+
# @return [Fixnum] the number of fat architecture structures following the header
|
457
|
+
attr_reader :nfat_arch
|
458
|
+
|
459
|
+
# always big-endian
|
460
|
+
# @see MachOStructure::FORMAT
|
461
|
+
# @api private
|
462
|
+
FORMAT = "N2".freeze
|
463
|
+
|
464
|
+
# @see MachOStructure::SIZEOF
|
465
|
+
# @api private
|
466
|
+
SIZEOF = 8
|
467
|
+
|
468
|
+
# @api private
|
469
|
+
def initialize(magic, nfat_arch)
|
470
|
+
@magic = magic
|
471
|
+
@nfat_arch = nfat_arch
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
# Fat binary header architecture structure. A Fat binary has one or more of
|
476
|
+
# these, representing one or more internal Mach-O blobs.
|
477
|
+
# @see MachO::Headers::FatHeader
|
478
|
+
class FatArch < MachOStructure
|
479
|
+
# @return [Fixnum] the CPU type of the Mach-O
|
480
|
+
attr_reader :cputype
|
481
|
+
|
482
|
+
# @return [Fixnum] the CPU subtype of the Mach-O
|
483
|
+
attr_reader :cpusubtype
|
484
|
+
|
485
|
+
# @return [Fixnum] the file offset to the beginning of the Mach-O data
|
486
|
+
attr_reader :offset
|
487
|
+
|
488
|
+
# @return [Fixnum] the size, in bytes, of the Mach-O data
|
489
|
+
attr_reader :size
|
490
|
+
|
491
|
+
# @return [Fixnum] the alignment, as a power of 2
|
492
|
+
attr_reader :align
|
493
|
+
|
494
|
+
# always big-endian
|
495
|
+
# @see MachOStructure::FORMAT
|
496
|
+
# @api private
|
497
|
+
FORMAT = "N5".freeze
|
498
|
+
|
499
|
+
# @see MachOStructure::SIZEOF
|
500
|
+
# @api private
|
501
|
+
SIZEOF = 20
|
502
|
+
|
503
|
+
# @api private
|
504
|
+
def initialize(cputype, cpusubtype, offset, size, align)
|
505
|
+
@cputype = cputype
|
506
|
+
@cpusubtype = cpusubtype
|
507
|
+
@offset = offset
|
508
|
+
@size = size
|
509
|
+
@align = align
|
510
|
+
end
|
511
|
+
end
|
512
|
+
|
513
|
+
# 32-bit Mach-O file header structure
|
514
|
+
class MachHeader < MachOStructure
|
515
|
+
# @return [Fixnum] the magic number
|
516
|
+
attr_reader :magic
|
517
|
+
|
518
|
+
# @return [Fixnum] the CPU type of the Mach-O
|
519
|
+
attr_reader :cputype
|
520
|
+
|
521
|
+
# @return [Fixnum] the CPU subtype of the Mach-O
|
522
|
+
attr_reader :cpusubtype
|
523
|
+
|
524
|
+
# @return [Fixnum] the file type of the Mach-O
|
525
|
+
attr_reader :filetype
|
526
|
+
|
527
|
+
# @return [Fixnum] the number of load commands in the Mach-O
|
528
|
+
attr_reader :ncmds
|
529
|
+
|
530
|
+
# @return [Fixnum] the size of all load commands, in bytes, in the Mach-O
|
531
|
+
attr_reader :sizeofcmds
|
532
|
+
|
533
|
+
# @return [Fixnum] the header flags associated with the Mach-O
|
534
|
+
attr_reader :flags
|
535
|
+
|
536
|
+
# @see MachOStructure::FORMAT
|
537
|
+
# @api private
|
538
|
+
FORMAT = "L=7".freeze
|
539
|
+
|
540
|
+
# @see MachOStructure::SIZEOF
|
541
|
+
# @api private
|
542
|
+
SIZEOF = 28
|
543
|
+
|
544
|
+
# @api private
|
545
|
+
def initialize(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds,
|
546
|
+
flags)
|
547
|
+
@magic = magic
|
548
|
+
@cputype = cputype
|
549
|
+
# For now we're not interested in additional capability bits also to be
|
550
|
+
# found in the `cpusubtype` field. We only care about the CPU sub-type.
|
551
|
+
@cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK
|
552
|
+
@filetype = filetype
|
553
|
+
@ncmds = ncmds
|
554
|
+
@sizeofcmds = sizeofcmds
|
555
|
+
@flags = flags
|
556
|
+
end
|
557
|
+
|
558
|
+
# @example
|
559
|
+
# puts "this mach-o has position-independent execution" if header.flag?(:MH_PIE)
|
560
|
+
# @param flag [Symbol] a mach header flag symbol
|
561
|
+
# @return [Boolean] true if `flag` is present in the header's flag section
|
562
|
+
def flag?(flag)
|
563
|
+
flag = MH_FLAGS[flag]
|
564
|
+
return false if flag.nil?
|
565
|
+
flags & flag == flag
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
# 64-bit Mach-O file header structure
|
570
|
+
class MachHeader64 < MachHeader
|
571
|
+
# @return [void]
|
572
|
+
attr_reader :reserved
|
573
|
+
|
574
|
+
# @see MachOStructure::FORMAT
|
575
|
+
# @api private
|
576
|
+
FORMAT = "L=8".freeze
|
577
|
+
|
578
|
+
# @see MachOStructure::SIZEOF
|
579
|
+
# @api private
|
580
|
+
SIZEOF = 32
|
581
|
+
|
582
|
+
# @api private
|
583
|
+
def initialize(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds,
|
584
|
+
flags, reserved)
|
585
|
+
super(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags)
|
586
|
+
@reserved = reserved
|
587
|
+
end
|
585
588
|
end
|
586
589
|
end
|
587
590
|
end
|