ruby-macho 2.5.1 → 4.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 +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
|