ruby-macho 2.1.0 → 2.2.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 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.