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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c4fdf0c3007545c3c9a84dacc832b803fc83edfe4aef0513eba857f14fcd2d1
4
- data.tar.gz: 0dd36193221a6d9f25084b5d8dea8f17eb8165a1f304e2d0006433ade11d61b8
3
+ metadata.gz: a6043ad4ddee8f973862b3f37626351bce8bcd9a190ec5e3f87dbbc169185661
4
+ data.tar.gz: 95afb17f5b95f4c06e1c67ac51a8ea38903fe629b7914d5a67701509c2cad040
5
5
  SHA512:
6
- metadata.gz: a07521accccc3e50119811ca36392c9ecc579dd0d8a238e8dcec5473f75325a2017a367d58212bc8fd1287e78f0b043f19546cf37eaa95c5c7f65623e7d3e015
7
- data.tar.gz: 16f243d60a944e725795bb77b6c2a301e5be7939df83c70c9929f23346792f7854c9b5ad626ea2bdf301155f882f43b934e12064efdc709723a6321fc13a83d5
6
+ metadata.gz: 55be478649522a73fe487013c9ff32378f773b4d21b1657d584e4436cbf3d4a5462482c6a1d6b50ae34e2506051905dd1349b8ef436d80423658e70a0ccc0315
7
+ data.tar.gz: 0524245cee9c8a416734449e9f2c3ac3b7a34b2922ff1c1468edf38fe45255f912e9cd80b677cc67692b2c976af41ce4d75a88dcbef5ffd2ac0e5259dbde5afd
@@ -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.1.0".freeze
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
@@ -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
@@ -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,
@@ -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 || offset + cmd_raw.bytesize > low_fileoff
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
- if header.class.bytesize + new_sizeofcmds > low_fileoff
182
- raise HeaderPadError, @filename
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 if cmd_sym.nil?
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.1.0
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: 2018-09-26 00:00:00.000000000 Z
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.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
- rubyforge_project:
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.