ruby-macho 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/macho.rb +1 -1
- data/lib/macho/fat_file.rb +17 -9
- data/lib/macho/headers.rb +5 -0
- data/lib/macho/macho_file.rb +30 -19
- metadata +4 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6043ad4ddee8f973862b3f37626351bce8bcd9a190ec5e3f87dbbc169185661
|
4
|
+
data.tar.gz: 95afb17f5b95f4c06e1c67ac51a8ea38903fe629b7914d5a67701509c2cad040
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55be478649522a73fe487013c9ff32378f773b4d21b1657d584e4436cbf3d4a5462482c6a1d6b50ae34e2506051905dd1349b8ef436d80423658e70a0ccc0315
|
7
|
+
data.tar.gz: 0524245cee9c8a416734449e9f2c3ac3b7a34b2922ff1c1468edf38fe45255f912e9cd80b677cc67692b2c976af41ce4d75a88dcbef5ffd2ac0e5259dbde5afd
|
data/lib/macho.rb
CHANGED
@@ -12,7 +12,7 @@ require_relative "macho/tools"
|
|
12
12
|
# The primary namespace for ruby-macho.
|
13
13
|
module MachO
|
14
14
|
# release version
|
15
|
-
VERSION = "2.
|
15
|
+
VERSION = "2.2.0".freeze
|
16
16
|
|
17
17
|
# Opens the given filename as a MachOFile or FatFile, depending on its magic.
|
18
18
|
# @param filename [String] the file being opened
|
data/lib/macho/fat_file.rb
CHANGED
@@ -11,6 +11,10 @@ module MachO
|
|
11
11
|
# @return [String] the filename loaded from, or nil if loaded from a binary string
|
12
12
|
attr_accessor :filename
|
13
13
|
|
14
|
+
# @return [Hash] any parser options that the instance was created with
|
15
|
+
# @note Options specified in a {FatFile} trickle down into the internal {MachOFile}s.
|
16
|
+
attr_reader :options
|
17
|
+
|
14
18
|
# @return [Headers::FatHeader] the file's header
|
15
19
|
attr_reader :header
|
16
20
|
|
@@ -49,9 +53,7 @@ module MachO
|
|
49
53
|
machos.each do |macho|
|
50
54
|
macho_offset = Utils.round(offset, 2**macho.segment_alignment)
|
51
55
|
|
52
|
-
if !fat64 && macho_offset > (2**32 - 1)
|
53
|
-
raise FatArchOffsetOverflowError, macho_offset
|
54
|
-
end
|
56
|
+
raise FatArchOffsetOverflowError, macho_offset if !fat64 && macho_offset > (2**32 - 1)
|
55
57
|
|
56
58
|
macho_pads[macho] = Utils.padding_for(offset, 2**macho.segment_alignment)
|
57
59
|
|
@@ -72,30 +74,36 @@ module MachO
|
|
72
74
|
|
73
75
|
# Creates a new FatFile instance from a binary string.
|
74
76
|
# @param bin [String] a binary string containing raw Mach-O data
|
77
|
+
# @param opts [Hash] options to control the parser with
|
78
|
+
# @note see {MachOFile#initialize} for currently valid options
|
75
79
|
# @return [FatFile] a new FatFile
|
76
|
-
def self.new_from_bin(bin)
|
80
|
+
def self.new_from_bin(bin, **opts)
|
77
81
|
instance = allocate
|
78
|
-
instance.initialize_from_bin(bin)
|
82
|
+
instance.initialize_from_bin(bin, opts)
|
79
83
|
|
80
84
|
instance
|
81
85
|
end
|
82
86
|
|
83
87
|
# Creates a new FatFile from the given filename.
|
84
88
|
# @param filename [String] the fat file to load from
|
89
|
+
# @param opts [Hash] options to control the parser with
|
90
|
+
# @note see {MachOFile#initialize} for currently valid options
|
85
91
|
# @raise [ArgumentError] if the given file does not exist
|
86
|
-
def initialize(filename)
|
92
|
+
def initialize(filename, **opts)
|
87
93
|
raise ArgumentError, "#{filename}: no such file" unless File.file?(filename)
|
88
94
|
|
89
95
|
@filename = filename
|
96
|
+
@options = opts
|
90
97
|
@raw_data = File.open(@filename, "rb", &:read)
|
91
98
|
populate_fields
|
92
99
|
end
|
93
100
|
|
94
|
-
# Initializes a new FatFile instance from a binary string.
|
101
|
+
# Initializes a new FatFile instance from a binary string with the given options.
|
95
102
|
# @see new_from_bin
|
96
103
|
# @api private
|
97
|
-
def initialize_from_bin(bin)
|
104
|
+
def initialize_from_bin(bin, opts)
|
98
105
|
@filename = nil
|
106
|
+
@options = opts
|
99
107
|
@raw_data = bin
|
100
108
|
populate_fields
|
101
109
|
end
|
@@ -358,7 +366,7 @@ module MachO
|
|
358
366
|
machos = []
|
359
367
|
|
360
368
|
fat_archs.each do |arch|
|
361
|
-
machos << MachOFile.new_from_bin(@raw_data[arch.offset, arch.size])
|
369
|
+
machos << MachOFile.new_from_bin(@raw_data[arch.offset, arch.size], **options)
|
362
370
|
end
|
363
371
|
|
364
372
|
machos
|
data/lib/macho/headers.rb
CHANGED
@@ -241,6 +241,10 @@ module MachO
|
|
241
241
|
# @api private
|
242
242
|
CPU_SUBTYPE_ARM64_32_V8 = 1
|
243
243
|
|
244
|
+
# the e (A12) sub-type for `CPU_TYPE_ARM64`
|
245
|
+
# @api private
|
246
|
+
CPU_SUBTYPE_ARM64E = 2
|
247
|
+
|
244
248
|
# the lowest common sub-type for `CPU_TYPE_MC88000`
|
245
249
|
# @api private
|
246
250
|
CPU_SUBTYPE_MC88000_ALL = 0
|
@@ -350,6 +354,7 @@ module MachO
|
|
350
354
|
CPU_TYPE_ARM64 => {
|
351
355
|
CPU_SUBTYPE_ARM64_ALL => :arm64,
|
352
356
|
CPU_SUBTYPE_ARM64_V8 => :arm64v8,
|
357
|
+
CPU_SUBTYPE_ARM64E => :arm64e,
|
353
358
|
}.freeze,
|
354
359
|
CPU_TYPE_ARM64_32 => {
|
355
360
|
CPU_SUBTYPE_ARM64_32_V8 => :arm64_32v8,
|
data/lib/macho/macho_file.rb
CHANGED
@@ -9,10 +9,13 @@ module MachO
|
|
9
9
|
class MachOFile
|
10
10
|
extend Forwardable
|
11
11
|
|
12
|
-
# @return [String] the filename loaded from, or nil if loaded from a binary
|
12
|
+
# @return [String, nil] the filename loaded from, or nil if loaded from a binary
|
13
13
|
# string
|
14
14
|
attr_accessor :filename
|
15
15
|
|
16
|
+
# @return [Hash] any parser options that the instance was created with
|
17
|
+
attr_reader :options
|
18
|
+
|
16
19
|
# @return [Symbol] the endianness of the file, :big or :little
|
17
20
|
attr_reader :endianness
|
18
21
|
|
@@ -27,30 +30,36 @@ module MachO
|
|
27
30
|
|
28
31
|
# Creates a new instance from a binary string.
|
29
32
|
# @param bin [String] a binary string containing raw Mach-O data
|
33
|
+
# @param opts [Hash] options to control the parser with
|
34
|
+
# @option opts [Boolean] :permissive whether to ignore unknown load commands
|
30
35
|
# @return [MachOFile] a new MachOFile
|
31
|
-
def self.new_from_bin(bin)
|
36
|
+
def self.new_from_bin(bin, **opts)
|
32
37
|
instance = allocate
|
33
|
-
instance.initialize_from_bin(bin)
|
38
|
+
instance.initialize_from_bin(bin, opts)
|
34
39
|
|
35
40
|
instance
|
36
41
|
end
|
37
42
|
|
38
43
|
# Creates a new instance from data read from the given filename.
|
39
44
|
# @param filename [String] the Mach-O file to load from
|
45
|
+
# @param opts [Hash] options to control the parser with
|
46
|
+
# @option opts [Boolean] :permissive whether to ignore unknown load commands
|
40
47
|
# @raise [ArgumentError] if the given file does not exist
|
41
|
-
def initialize(filename)
|
48
|
+
def initialize(filename, **opts)
|
42
49
|
raise ArgumentError, "#{filename}: no such file" unless File.file?(filename)
|
43
50
|
|
44
51
|
@filename = filename
|
52
|
+
@options = opts
|
45
53
|
@raw_data = File.open(@filename, "rb", &:read)
|
46
54
|
populate_fields
|
47
55
|
end
|
48
56
|
|
49
|
-
# Initializes a new MachOFile instance from a binary string.
|
57
|
+
# Initializes a new MachOFile instance from a binary string with the given options.
|
50
58
|
# @see MachO::MachOFile.new_from_bin
|
51
59
|
# @api private
|
52
|
-
def initialize_from_bin(bin)
|
60
|
+
def initialize_from_bin(bin, opts)
|
53
61
|
@filename = nil
|
62
|
+
@options = opts
|
54
63
|
@raw_data = bin
|
55
64
|
populate_fields
|
56
65
|
end
|
@@ -146,16 +155,13 @@ module MachO
|
|
146
155
|
def insert_command(offset, lc, options = {})
|
147
156
|
context = LoadCommands::LoadCommand::SerializationContext.context_for(self)
|
148
157
|
cmd_raw = lc.serialize(context)
|
158
|
+
fileoff = offset + cmd_raw.bytesize
|
149
159
|
|
150
|
-
if offset < header.class.bytesize ||
|
151
|
-
raise OffsetInsertionError, offset
|
152
|
-
end
|
160
|
+
raise OffsetInsertionError, offset if offset < header.class.bytesize || fileoff > low_fileoff
|
153
161
|
|
154
162
|
new_sizeofcmds = sizeofcmds + cmd_raw.bytesize
|
155
163
|
|
156
|
-
if header.class.bytesize + new_sizeofcmds > low_fileoff
|
157
|
-
raise HeaderPadError, @filename
|
158
|
-
end
|
164
|
+
raise HeaderPadError, @filename if header.class.bytesize + new_sizeofcmds > low_fileoff
|
159
165
|
|
160
166
|
# update Mach-O header fields to account for inserted load command
|
161
167
|
update_ncmds(ncmds + 1)
|
@@ -178,9 +184,8 @@ module MachO
|
|
178
184
|
context = LoadCommands::LoadCommand::SerializationContext.context_for(self)
|
179
185
|
cmd_raw = new_lc.serialize(context)
|
180
186
|
new_sizeofcmds = sizeofcmds + cmd_raw.bytesize - old_lc.cmdsize
|
181
|
-
|
182
|
-
|
183
|
-
end
|
187
|
+
|
188
|
+
raise HeaderPadError, @filename if header.class.bytesize + new_sizeofcmds > low_fileoff
|
184
189
|
|
185
190
|
delete_command(old_lc)
|
186
191
|
insert_command(old_lc.view.offset, new_lc)
|
@@ -511,6 +516,7 @@ module MachO
|
|
511
516
|
# @raise [LoadCommandError] if an unknown load command is encountered
|
512
517
|
# @api private
|
513
518
|
def populate_load_commands
|
519
|
+
permissive = options.fetch(:permissive, false)
|
514
520
|
offset = header.class.bytesize
|
515
521
|
load_commands = []
|
516
522
|
|
@@ -519,11 +525,16 @@ module MachO
|
|
519
525
|
cmd = @raw_data.slice(offset, 4).unpack(fmt).first
|
520
526
|
cmd_sym = LoadCommands::LOAD_COMMANDS[cmd]
|
521
527
|
|
522
|
-
raise LoadCommandError, cmd
|
528
|
+
raise LoadCommandError, cmd unless cmd_sym || permissive
|
529
|
+
|
530
|
+
# If we're here, then either cmd_sym represents a valid load
|
531
|
+
# command *or* we're in permissive mode.
|
532
|
+
klass = if (klass_str = LoadCommands::LC_STRUCTURES[cmd_sym])
|
533
|
+
LoadCommands.const_get klass_str
|
534
|
+
else
|
535
|
+
LoadCommands::LoadCommand
|
536
|
+
end
|
523
537
|
|
524
|
-
# why do I do this? i don't like declaring constants below
|
525
|
-
# classes, and i need them to resolve...
|
526
|
-
klass = LoadCommands.const_get LoadCommands::LC_STRUCTURES[cmd_sym]
|
527
538
|
view = MachOView.new(@raw_data, endianness, offset)
|
528
539
|
command = klass.new_from_bin(view)
|
529
540
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-macho
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Woodruff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A library for viewing and manipulating Mach-O files in Ruby.
|
14
14
|
email: william@yossarian.net
|
@@ -42,15 +42,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
42
42
|
requirements:
|
43
43
|
- - ">="
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: '2.
|
45
|
+
version: '2.3'
|
46
46
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
47
|
requirements:
|
48
48
|
- - ">="
|
49
49
|
- !ruby/object:Gem::Version
|
50
50
|
version: '0'
|
51
51
|
requirements: []
|
52
|
-
|
53
|
-
rubygems_version: 2.7.6
|
52
|
+
rubygems_version: 3.0.1
|
54
53
|
signing_key:
|
55
54
|
specification_version: 4
|
56
55
|
summary: ruby-macho - Mach-O file analyzer.
|