ruby-macho 2.5.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -2
- data/lib/macho/exceptions.rb +42 -10
- data/lib/macho/fat_file.rb +21 -4
- data/lib/macho/headers.rb +107 -103
- data/lib/macho/load_commands.rb +207 -627
- data/lib/macho/macho_file.rb +86 -21
- data/lib/macho/sections.rb +63 -54
- data/lib/macho/structure.rb +264 -22
- data/lib/macho/tools.rb +4 -0
- data/lib/macho/utils.rb +7 -0
- data/lib/macho/view.rb +10 -1
- data/lib/macho.rb +2 -2
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 669b2133517dc564c92df8ebdc0b2f6fdc91869939cd6a642cfbc2b1c6e20a09
|
4
|
+
data.tar.gz: 0077afabc9c4be7d891e5c7e5a8b4ec173223b00f73d550fc96fb7cf4f103c1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e8bd64595d93d50c0046c5bd292010a51a9d4154cbcda3a0a0a962882475e61d631d55da106e4655ba31a32011f583222d5b147129230e08ad11d12a34ee8e6
|
7
|
+
data.tar.gz: ccc53798eb56f378f5688ad7141636ecca274e552e8ad62f4fab5600b6a6fddcac0e5ffc75ed4924e62538a6b3ac7b291667870b6cd02bf0edf6286da1a4e62a
|
data/README.md
CHANGED
@@ -56,11 +56,24 @@ puts lc_vers.version_string # => "10.10.0"
|
|
56
56
|
|
57
57
|
* Unit and performance testing.
|
58
58
|
|
59
|
-
|
59
|
+
### Contributing, setting up `overcommit` and the linters
|
60
|
+
|
61
|
+
In order to keep the repo, docs and data tidy, we use a tool called [`overcommit`](https://github.com/sds/overcommit)
|
62
|
+
to connect up the git hooks to a set of quality checks. The fastest way to get setup is to run the following to make
|
63
|
+
sure you have all the tools:
|
64
|
+
|
65
|
+
```shell
|
66
|
+
gem install overcommit bundler
|
67
|
+
bundle install
|
68
|
+
overcommit --install
|
69
|
+
```
|
70
|
+
|
71
|
+
### Attribution
|
60
72
|
|
61
73
|
* Constants were taken from Apple, Inc's
|
62
|
-
[`loader.h` in `cctools/include/mach-o`](https://
|
74
|
+
[`loader.h` in `cctools/include/mach-o`](https://opensource.apple.com/source/cctools/cctools-973.0.1/include/mach-o/loader.h.auto.html).
|
63
75
|
(Apple Public Source License 2.0).
|
76
|
+
* Binary files used for testing were taken from The LLVM Project. ([Apache License v2.0 with LLVM Exceptions](test/bin/llvm/LICENSE.txt)).
|
64
77
|
|
65
78
|
### License
|
66
79
|
|
data/lib/macho/exceptions.rb
CHANGED
@@ -56,6 +56,28 @@ module MachO
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
# Raised when a a fat Mach-O file has zero architectures
|
60
|
+
class ZeroArchitectureError < NotAMachOError
|
61
|
+
def initialize
|
62
|
+
super "Fat file has zero internal architectures"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Raised when there is a mismatch between the fat arch
|
67
|
+
# and internal slice cputype or cpusubtype.
|
68
|
+
class CPUTypeMismatchError < NotAMachOError
|
69
|
+
def initialize(fat_cputype, fat_cpusubtype, macho_cputype, macho_cpusubtype)
|
70
|
+
# @param cputype_fat [Integer] the CPU type in the fat header
|
71
|
+
# @param cpusubtype_fat [Integer] the CPU subtype in the fat header
|
72
|
+
# @param cputype_macho [Integer] the CPU type in the macho header
|
73
|
+
# @param cpusubtype_macho [Integer] the CPU subtype in the macho header
|
74
|
+
super ("Mismatch between cputypes >> 0x%08<fat_cputype>x and 0x%08<macho_cputype>x\n" \
|
75
|
+
"and/or cpusubtypes >> 0x%08<fat_cpusubtype>x and 0x%08<macho_cpusubtype>x" %
|
76
|
+
{ :fat_cputype => fat_cputype, :macho_cputype => macho_cputype,
|
77
|
+
:fat_cpusubtype => fat_cpusubtype, :macho_cpusubtype => macho_cpusubtype })
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
59
81
|
# Raised when a fat binary is loaded with MachOFile.
|
60
82
|
class FatBinaryError < MachOError
|
61
83
|
def initialize
|
@@ -83,8 +105,8 @@ module MachO
|
|
83
105
|
# @param cputype [Integer] the CPU type of the unknown pair
|
84
106
|
# @param cpusubtype [Integer] the CPU sub-type of the unknown pair
|
85
107
|
def initialize(cputype, cpusubtype)
|
86
|
-
super "Unrecognized CPU sub-type: 0x%08<cpusubtype>x" \
|
87
|
-
|
108
|
+
super "Unrecognized CPU sub-type: 0x%08<cpusubtype>x " \
|
109
|
+
"(for CPU type: 0x%08<cputype>x" % { :cputype => cputype, :cpusubtype => cpusubtype }
|
88
110
|
end
|
89
111
|
end
|
90
112
|
|
@@ -119,8 +141,8 @@ module MachO
|
|
119
141
|
# @param expected_arity [Integer] the number of arguments expected
|
120
142
|
# @param actual_arity [Integer] the number of arguments received
|
121
143
|
def initialize(cmd_sym, expected_arity, actual_arity)
|
122
|
-
super "Expected #{expected_arity} arguments for #{cmd_sym} creation," \
|
123
|
-
|
144
|
+
super "Expected #{expected_arity} arguments for #{cmd_sym} creation, " \
|
145
|
+
"got #{actual_arity}"
|
124
146
|
end
|
125
147
|
end
|
126
148
|
|
@@ -136,8 +158,8 @@ module MachO
|
|
136
158
|
class LCStrMalformedError < MachOError
|
137
159
|
# @param lc [MachO::LoadCommand] the load command containing the string
|
138
160
|
def initialize(lc)
|
139
|
-
super "Load command #{lc.type} at offset #{lc.view.offset} contains a" \
|
140
|
-
|
161
|
+
super "Load command #{lc.type} at offset #{lc.view.offset} contains a " \
|
162
|
+
"malformed string"
|
141
163
|
end
|
142
164
|
end
|
143
165
|
|
@@ -154,8 +176,8 @@ module MachO
|
|
154
176
|
# @param filename [String] the filename
|
155
177
|
def initialize(filename)
|
156
178
|
super "Updated load commands do not fit in the header of " \
|
157
|
-
|
158
|
-
|
179
|
+
"#{filename}. #{filename} needs to be relinked, possibly with " \
|
180
|
+
"-headerpad or -headerpad_max_install_names"
|
159
181
|
end
|
160
182
|
end
|
161
183
|
|
@@ -203,8 +225,18 @@ module MachO
|
|
203
225
|
class FatArchOffsetOverflowError < MachOError
|
204
226
|
# @param offset [Integer] the offending offset
|
205
227
|
def initialize(offset)
|
206
|
-
super "Offset #{offset} exceeds the 32-bit width of a fat_arch offset." \
|
207
|
-
"
|
228
|
+
super "Offset #{offset} exceeds the 32-bit width of a fat_arch offset. " \
|
229
|
+
"Consider merging with `fat64: true`"
|
208
230
|
end
|
209
231
|
end
|
232
|
+
|
233
|
+
# Raised when attempting to parse a compressed Mach-O without explicitly
|
234
|
+
# requesting decompression.
|
235
|
+
class CompressedMachOError < MachOError
|
236
|
+
end
|
237
|
+
|
238
|
+
# Raised when attempting to decompress a compressed Mach-O without adequate
|
239
|
+
# dependencies, or on other decompression errors.
|
240
|
+
class DecompressionError < MachOError
|
241
|
+
end
|
210
242
|
end
|
data/lib/macho/fat_file.rb
CHANGED
@@ -55,7 +55,7 @@ module MachO
|
|
55
55
|
machos.each do |macho|
|
56
56
|
macho_offset = Utils.round(offset, 2**macho.segment_alignment)
|
57
57
|
|
58
|
-
raise FatArchOffsetOverflowError, macho_offset if !fat64 && macho_offset > (2**32 - 1)
|
58
|
+
raise FatArchOffsetOverflowError, macho_offset if !fat64 && macho_offset > ((2**32) - 1)
|
59
59
|
|
60
60
|
macho_pads[macho] = Utils.padding_for(offset, 2**macho.segment_alignment)
|
61
61
|
|
@@ -96,7 +96,7 @@ module MachO
|
|
96
96
|
|
97
97
|
@filename = filename
|
98
98
|
@options = opts
|
99
|
-
@raw_data = File.
|
99
|
+
@raw_data = File.binread(@filename)
|
100
100
|
populate_fields
|
101
101
|
end
|
102
102
|
|
@@ -238,6 +238,8 @@ module MachO
|
|
238
238
|
# @param options [Hash]
|
239
239
|
# @option options [Boolean] :strict (true) if true, fail if one slice fails.
|
240
240
|
# if false, fail only if all slices fail.
|
241
|
+
# @option options [Boolean] :uniq (false) for each slice: if true, change
|
242
|
+
# each rpath simultaneously.
|
241
243
|
# @return [void]
|
242
244
|
# @see MachOFile#change_rpath
|
243
245
|
def change_rpath(old_path, new_path, options = {})
|
@@ -268,6 +270,9 @@ module MachO
|
|
268
270
|
# @param options [Hash]
|
269
271
|
# @option options [Boolean] :strict (true) if true, fail if one slice fails.
|
270
272
|
# if false, fail only if all slices fail.
|
273
|
+
# @option options [Boolean] :uniq (false) for each slice: if true, delete
|
274
|
+
# only the first runtime path that matches. if false, delete all duplicate
|
275
|
+
# paths that match.
|
271
276
|
# @return void
|
272
277
|
# @see MachOFile#delete_rpath
|
273
278
|
def delete_rpath(path, options = {})
|
@@ -291,7 +296,7 @@ module MachO
|
|
291
296
|
# @param filename [String] the file to write to
|
292
297
|
# @return [void]
|
293
298
|
def write(filename)
|
294
|
-
File.
|
299
|
+
File.binwrite(filename, @raw_data)
|
295
300
|
end
|
296
301
|
|
297
302
|
# Write all (fat) data to the file used to initialize the instance.
|
@@ -301,7 +306,7 @@ module MachO
|
|
301
306
|
def write!
|
302
307
|
raise MachOError, "no initial file to write to" if filename.nil?
|
303
308
|
|
304
|
-
File.
|
309
|
+
File.binwrite(@filename, @raw_data)
|
305
310
|
end
|
306
311
|
|
307
312
|
# @return [Hash] a hash representation of this {FatFile}
|
@@ -322,6 +327,8 @@ module MachO
|
|
322
327
|
# @raise [MagicError] if the magic is not valid Mach-O magic
|
323
328
|
# @raise [MachOBinaryError] if the magic is for a non-fat Mach-O file
|
324
329
|
# @raise [JavaClassFileError] if the file is a Java classfile
|
330
|
+
# @raise [ZeroArchitectureError] if the file has no internal slices
|
331
|
+
# (i.e., nfat_arch == 0) and the permissive option is not set
|
325
332
|
# @api private
|
326
333
|
def populate_fat_header
|
327
334
|
# the smallest fat Mach-O header is 8 bytes
|
@@ -341,6 +348,9 @@ module MachO
|
|
341
348
|
# formats.
|
342
349
|
raise JavaClassFileError if fh.nfat_arch > 30
|
343
350
|
|
351
|
+
# Rationale: return an error if the file has no internal slices.
|
352
|
+
raise ZeroArchitectureError if fh.nfat_arch.zero?
|
353
|
+
|
344
354
|
fh
|
345
355
|
end
|
346
356
|
|
@@ -369,6 +379,13 @@ module MachO
|
|
369
379
|
|
370
380
|
fat_archs.each do |arch|
|
371
381
|
machos << MachOFile.new_from_bin(@raw_data[arch.offset, arch.size], **options)
|
382
|
+
|
383
|
+
# Make sure that each fat_arch and internal slice.
|
384
|
+
# contain matching cputypes and cpusubtypes
|
385
|
+
next if machos.last.header.cputype == arch.cputype &&
|
386
|
+
machos.last.header.cpusubtype == arch.cpusubtype
|
387
|
+
|
388
|
+
raise CPUTypeMismatchError.new(arch.cputype, arch.cpusubtype, machos.last.header.cputype, machos.last.header.cpusubtype)
|
372
389
|
end
|
373
390
|
|
374
391
|
machos
|
data/lib/macho/headers.rb
CHANGED
@@ -37,6 +37,18 @@ module MachO
|
|
37
37
|
# @api private
|
38
38
|
MH_CIGAM_64 = 0xcffaedfe
|
39
39
|
|
40
|
+
# compressed mach-o magic
|
41
|
+
# @api private
|
42
|
+
COMPRESSED_MAGIC = 0x636f6d70 # "comp"
|
43
|
+
|
44
|
+
# a compressed mach-o slice, using LZSS for compression
|
45
|
+
# @api private
|
46
|
+
COMP_TYPE_LZSS = 0x6c7a7373 # "lzss"
|
47
|
+
|
48
|
+
# a compressed mach-o slice, using LZVN ("FastLib") for compression
|
49
|
+
# @api private
|
50
|
+
COMP_TYPE_FASTLIB = 0x6c7a766e # "lzvn"
|
51
|
+
|
40
52
|
# association of magic numbers to string representations
|
41
53
|
# @api private
|
42
54
|
MH_MAGICS = {
|
@@ -433,6 +445,11 @@ module MachO
|
|
433
445
|
# @api private
|
434
446
|
MH_KEXT_BUNDLE = 0xb
|
435
447
|
|
448
|
+
# a set of Mach-Os, running in the same userspace, sharing a linkedit. The kext collection files are an example
|
449
|
+
# of this object type
|
450
|
+
# @api private
|
451
|
+
MH_FILESET = 0xc
|
452
|
+
|
436
453
|
# association of filetypes to Symbol representations
|
437
454
|
# @api private
|
438
455
|
MH_FILETYPES = {
|
@@ -447,6 +464,7 @@ module MachO
|
|
447
464
|
MH_DYLIB_STUB => :dylib_stub,
|
448
465
|
MH_DSYM => :dsym,
|
449
466
|
MH_KEXT_BUNDLE => :kext_bundle,
|
467
|
+
MH_FILESET => :fileset,
|
450
468
|
}.freeze
|
451
469
|
|
452
470
|
# association of mach header flag symbols to values
|
@@ -478,36 +496,23 @@ module MachO
|
|
478
496
|
:MH_HAS_TLV_DESCRIPTORS => 0x800000,
|
479
497
|
:MH_NO_HEAP_EXECUTION => 0x1000000,
|
480
498
|
:MH_APP_EXTENSION_SAFE => 0x02000000,
|
499
|
+
:MH_NLIST_OUTOFSYNC_WITH_DYLDINFO => 0x04000000,
|
500
|
+
:MH_SIM_SUPPORT => 0x08000000,
|
501
|
+
:MH_DYLIB_IN_CACHE => 0x80000000,
|
481
502
|
}.freeze
|
482
503
|
|
483
504
|
# Fat binary header structure
|
484
505
|
# @see MachO::FatArch
|
485
506
|
class FatHeader < MachOStructure
|
486
507
|
# @return [Integer] the magic number of the header (and file)
|
487
|
-
|
508
|
+
field :magic, :uint32, :endian => :big
|
488
509
|
|
489
510
|
# @return [Integer] the number of fat architecture structures following the header
|
490
|
-
|
491
|
-
|
492
|
-
# always big-endian
|
493
|
-
# @see MachOStructure::FORMAT
|
494
|
-
# @api private
|
495
|
-
FORMAT = "N2"
|
496
|
-
|
497
|
-
# @see MachOStructure::SIZEOF
|
498
|
-
# @api private
|
499
|
-
SIZEOF = 8
|
500
|
-
|
501
|
-
# @api private
|
502
|
-
def initialize(magic, nfat_arch)
|
503
|
-
super()
|
504
|
-
@magic = magic
|
505
|
-
@nfat_arch = nfat_arch
|
506
|
-
end
|
511
|
+
field :nfat_arch, :uint32, :endian => :big
|
507
512
|
|
508
513
|
# @return [String] the serialized fields of the fat header
|
509
514
|
def serialize
|
510
|
-
[magic, nfat_arch].pack(
|
515
|
+
[magic, nfat_arch].pack(self.class.format)
|
511
516
|
end
|
512
517
|
|
513
518
|
# @return [Hash] a hash representation of this {FatHeader}
|
@@ -527,42 +532,23 @@ module MachO
|
|
527
532
|
# @see MachO::Headers::FatHeader
|
528
533
|
class FatArch < MachOStructure
|
529
534
|
# @return [Integer] the CPU type of the Mach-O
|
530
|
-
|
535
|
+
field :cputype, :uint32, :endian => :big
|
531
536
|
|
532
537
|
# @return [Integer] the CPU subtype of the Mach-O
|
533
|
-
|
538
|
+
field :cpusubtype, :uint32, :endian => :big, :mask => CPU_SUBTYPE_MASK
|
534
539
|
|
535
540
|
# @return [Integer] the file offset to the beginning of the Mach-O data
|
536
|
-
|
541
|
+
field :offset, :uint32, :endian => :big
|
537
542
|
|
538
543
|
# @return [Integer] the size, in bytes, of the Mach-O data
|
539
|
-
|
544
|
+
field :size, :uint32, :endian => :big
|
540
545
|
|
541
546
|
# @return [Integer] the alignment, as a power of 2
|
542
|
-
|
543
|
-
|
544
|
-
# @note Always big endian.
|
545
|
-
# @see MachOStructure::FORMAT
|
546
|
-
# @api private
|
547
|
-
FORMAT = "L>5"
|
548
|
-
|
549
|
-
# @see MachOStructure::SIZEOF
|
550
|
-
# @api private
|
551
|
-
SIZEOF = 20
|
552
|
-
|
553
|
-
# @api private
|
554
|
-
def initialize(cputype, cpusubtype, offset, size, align)
|
555
|
-
super()
|
556
|
-
@cputype = cputype
|
557
|
-
@cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK
|
558
|
-
@offset = offset
|
559
|
-
@size = size
|
560
|
-
@align = align
|
561
|
-
end
|
547
|
+
field :align, :uint32, :endian => :big
|
562
548
|
|
563
549
|
# @return [String] the serialized fields of the fat arch
|
564
550
|
def serialize
|
565
|
-
[cputype, cpusubtype, offset, size, align].pack(
|
551
|
+
[cputype, cpusubtype, offset, size, align].pack(self.class.format)
|
566
552
|
end
|
567
553
|
|
568
554
|
# @return [Hash] a hash representation of this {FatArch}
|
@@ -585,27 +571,18 @@ module MachO
|
|
585
571
|
# Mach-Os that it points to necessarily *are* 64-bit.
|
586
572
|
# @see MachO::Headers::FatHeader
|
587
573
|
class FatArch64 < FatArch
|
588
|
-
# @return [
|
589
|
-
|
590
|
-
|
591
|
-
# @note Always big endian.
|
592
|
-
# @see MachOStructure::FORMAT
|
593
|
-
# @api private
|
594
|
-
FORMAT = "L>2Q>2L>2"
|
574
|
+
# @return [Integer] the file offset to the beginning of the Mach-O data
|
575
|
+
field :offset, :uint64, :endian => :big
|
595
576
|
|
596
|
-
# @
|
597
|
-
|
598
|
-
SIZEOF = 32
|
577
|
+
# @return [Integer] the size, in bytes, of the Mach-O data
|
578
|
+
field :size, :uint64, :endian => :big
|
599
579
|
|
600
|
-
# @
|
601
|
-
|
602
|
-
super(cputype, cpusubtype, offset, size, align)
|
603
|
-
@reserved = reserved
|
604
|
-
end
|
580
|
+
# @return [void]
|
581
|
+
field :reserved, :uint32, :endian => :big, :default => 0
|
605
582
|
|
606
583
|
# @return [String] the serialized fields of the fat arch
|
607
584
|
def serialize
|
608
|
-
[cputype, cpusubtype, offset, size, align, reserved].pack(
|
585
|
+
[cputype, cpusubtype, offset, size, align, reserved].pack(self.class.format)
|
609
586
|
end
|
610
587
|
|
611
588
|
# @return [Hash] a hash representation of this {FatArch64}
|
@@ -619,48 +596,25 @@ module MachO
|
|
619
596
|
# 32-bit Mach-O file header structure
|
620
597
|
class MachHeader < MachOStructure
|
621
598
|
# @return [Integer] the magic number
|
622
|
-
|
599
|
+
field :magic, :uint32
|
623
600
|
|
624
601
|
# @return [Integer] the CPU type of the Mach-O
|
625
|
-
|
602
|
+
field :cputype, :uint32
|
626
603
|
|
627
604
|
# @return [Integer] the CPU subtype of the Mach-O
|
628
|
-
|
605
|
+
field :cpusubtype, :uint32, :mask => CPU_SUBTYPE_MASK
|
629
606
|
|
630
607
|
# @return [Integer] the file type of the Mach-O
|
631
|
-
|
608
|
+
field :filetype, :uint32
|
632
609
|
|
633
610
|
# @return [Integer] the number of load commands in the Mach-O
|
634
|
-
|
611
|
+
field :ncmds, :uint32
|
635
612
|
|
636
613
|
# @return [Integer] the size of all load commands, in bytes, in the Mach-O
|
637
|
-
|
614
|
+
field :sizeofcmds, :uint32
|
638
615
|
|
639
616
|
# @return [Integer] the header flags associated with the Mach-O
|
640
|
-
|
641
|
-
|
642
|
-
# @see MachOStructure::FORMAT
|
643
|
-
# @api private
|
644
|
-
FORMAT = "L=7"
|
645
|
-
|
646
|
-
# @see MachOStructure::SIZEOF
|
647
|
-
# @api private
|
648
|
-
SIZEOF = 28
|
649
|
-
|
650
|
-
# @api private
|
651
|
-
def initialize(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds,
|
652
|
-
flags)
|
653
|
-
super()
|
654
|
-
@magic = magic
|
655
|
-
@cputype = cputype
|
656
|
-
# For now we're not interested in additional capability bits also to be
|
657
|
-
# found in the `cpusubtype` field. We only care about the CPU sub-type.
|
658
|
-
@cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK
|
659
|
-
@filetype = filetype
|
660
|
-
@ncmds = ncmds
|
661
|
-
@sizeofcmds = sizeofcmds
|
662
|
-
@flags = flags
|
663
|
-
end
|
617
|
+
field :flags, :uint32
|
664
618
|
|
665
619
|
# @example
|
666
620
|
# puts "this mach-o has position-independent execution" if header.flag?(:MH_PIE)
|
@@ -724,6 +678,11 @@ module MachO
|
|
724
678
|
filetype == Headers::MH_KEXT_BUNDLE
|
725
679
|
end
|
726
680
|
|
681
|
+
# @return [Boolean] whether or not the file is of type `MH_FILESET`
|
682
|
+
def fileset?
|
683
|
+
filetype == Headers::MH_FILESET
|
684
|
+
end
|
685
|
+
|
727
686
|
# @return [Boolean] true if the Mach-O has 32-bit magic, false otherwise
|
728
687
|
def magic32?
|
729
688
|
Utils.magic32?(magic)
|
@@ -761,27 +720,72 @@ module MachO
|
|
761
720
|
# 64-bit Mach-O file header structure
|
762
721
|
class MachHeader64 < MachHeader
|
763
722
|
# @return [void]
|
764
|
-
|
723
|
+
field :reserved, :uint32
|
724
|
+
|
725
|
+
# @return [Hash] a hash representation of this {MachHeader64}
|
726
|
+
def to_h
|
727
|
+
{
|
728
|
+
"reserved" => reserved,
|
729
|
+
}.merge super
|
730
|
+
end
|
731
|
+
end
|
732
|
+
|
733
|
+
# Prelinked kernel/"kernelcache" header structure
|
734
|
+
class PrelinkedKernelHeader < MachOStructure
|
735
|
+
# @return [Integer] the magic number for a compressed header ({COMPRESSED_MAGIC})
|
736
|
+
field :signature, :uint32, :endian => :big
|
737
|
+
|
738
|
+
# @return [Integer] the type of compression used
|
739
|
+
field :compress_type, :uint32, :endian => :big
|
740
|
+
|
741
|
+
# @return [Integer] a checksum for the uncompressed data
|
742
|
+
field :adler32, :uint32, :endian => :big
|
743
|
+
|
744
|
+
# @return [Integer] the size of the uncompressed data, in bytes
|
745
|
+
field :uncompressed_size, :uint32, :endian => :big
|
746
|
+
|
747
|
+
# @return [Integer] the size of the compressed data, in bytes
|
748
|
+
field :compressed_size, :uint32, :endian => :big
|
749
|
+
|
750
|
+
# @return [Integer] the version of the prelink format
|
751
|
+
field :prelink_version, :uint32, :endian => :big
|
752
|
+
|
753
|
+
# @return [void]
|
754
|
+
field :reserved, :string, :size => 40, :unpack => "L>10"
|
755
|
+
|
756
|
+
# @return [void]
|
757
|
+
field :platform_name, :string, :size => 64
|
765
758
|
|
766
|
-
# @
|
767
|
-
|
768
|
-
FORMAT = "L=8"
|
759
|
+
# @return [void]
|
760
|
+
field :root_path, :string, :size => 256
|
769
761
|
|
770
|
-
# @
|
771
|
-
|
772
|
-
|
762
|
+
# @return [Boolean] whether this prelinked kernel supports KASLR
|
763
|
+
def kaslr?
|
764
|
+
prelink_version >= 1
|
765
|
+
end
|
773
766
|
|
774
|
-
# @
|
775
|
-
def
|
776
|
-
|
777
|
-
super(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags)
|
778
|
-
@reserved = reserved
|
767
|
+
# @return [Boolean] whether this prelinked kernel is compressed with LZSS
|
768
|
+
def lzss?
|
769
|
+
compress_type == COMP_TYPE_LZSS
|
779
770
|
end
|
780
771
|
|
781
|
-
# @return [
|
772
|
+
# @return [Boolean] whether this prelinked kernel is compressed with LZVN
|
773
|
+
def lzvn?
|
774
|
+
compress_type == COMP_TYPE_FASTLIB
|
775
|
+
end
|
776
|
+
|
777
|
+
# @return [Hash] a hash representation of this {PrelinkedKernelHeader}
|
782
778
|
def to_h
|
783
779
|
{
|
780
|
+
"signature" => signature,
|
781
|
+
"compress_type" => compress_type,
|
782
|
+
"adler32" => adler32,
|
783
|
+
"uncompressed_size" => uncompressed_size,
|
784
|
+
"compressed_size" => compressed_size,
|
785
|
+
"prelink_version" => prelink_version,
|
784
786
|
"reserved" => reserved,
|
787
|
+
"platform_name" => platform_name,
|
788
|
+
"root_path" => root_path,
|
785
789
|
}.merge super
|
786
790
|
end
|
787
791
|
end
|