ruby-macho 3.0.0 → 4.0.1
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 +30 -8
- data/lib/macho/fat_file.rb +12 -0
- data/lib/macho/headers.rb +33 -138
- data/lib/macho/load_commands.rb +181 -647
- data/lib/macho/macho_file.rb +22 -9
- data/lib/macho/sections.rb +17 -48
- data/lib/macho/structure.rb +264 -22
- data/lib/macho/view.rb +10 -1
- data/lib/macho.rb +2 -2
- metadata +5 -4
data/lib/macho/macho_file.rb
CHANGED
@@ -381,11 +381,9 @@ module MachO
|
|
381
381
|
# rpaths simultaneously.
|
382
382
|
# @return [void]
|
383
383
|
# @raise [RpathUnknownError] if no such old runtime path exists
|
384
|
-
# @raise [RpathExistsError] if the new runtime path already exists
|
385
384
|
def change_rpath(old_path, new_path, options = {})
|
386
385
|
old_lc = command(:LC_RPATH).find { |r| r.path.to_s == old_path }
|
387
386
|
raise RpathUnknownError, old_path if old_lc.nil?
|
388
|
-
raise RpathExistsError, new_path if rpaths.include?(new_path)
|
389
387
|
|
390
388
|
new_lc = LoadCommands::LoadCommand.create(:LC_RPATH, new_path)
|
391
389
|
|
@@ -413,22 +411,37 @@ module MachO
|
|
413
411
|
|
414
412
|
# Delete the given runtime path from the Mach-O.
|
415
413
|
# @example
|
416
|
-
#
|
417
|
-
#
|
418
|
-
#
|
414
|
+
# file1.rpaths # => ["/lib", "/usr/lib", "/lib"]
|
415
|
+
# file1.delete_rpath("/lib")
|
416
|
+
# file1.rpaths # => ["/usr/lib", "/lib"]
|
417
|
+
# file2.rpaths # => ["foo", "foo"]
|
418
|
+
# file2.delete_rpath("foo", :uniq => true)
|
419
|
+
# file2.rpaths # => []
|
420
|
+
# file3.rpaths # => ["foo", "bar", "foo"]
|
421
|
+
# file3.delete_rpath("foo", :last => true)
|
422
|
+
# file3.rpaths # => ["foo", "bar"]
|
419
423
|
# @param path [String] the runtime path to delete
|
420
424
|
# @param options [Hash]
|
421
425
|
# @option options [Boolean] :uniq (false) if true, also delete
|
422
426
|
# duplicates of the requested path. If false, delete the first
|
423
|
-
# instance (by offset) of the requested path.
|
427
|
+
# instance (by offset) of the requested path, unless :last is true.
|
428
|
+
# Incompatible with :last.
|
429
|
+
# @option options [Boolean] :last (false) if true, delete the last
|
430
|
+
# instance (by offset) of the requested path. Incompatible with :uniq.
|
424
431
|
# @return void
|
425
432
|
# @raise [RpathUnknownError] if no such runtime path exists
|
433
|
+
# @raise [ArgumentError] if both :uniq and :last are true
|
426
434
|
def delete_rpath(path, options = {})
|
427
435
|
uniq = options.fetch(:uniq, false)
|
428
|
-
|
436
|
+
last = options.fetch(:last, false)
|
437
|
+
raise ArgumentError, "Cannot set both :uniq and :last to true" if uniq && last
|
438
|
+
|
439
|
+
search_method = uniq || last ? :select : :find
|
440
|
+
rpath_cmds = command(:LC_RPATH).public_send(search_method) { |r| r.path.to_s == path }
|
441
|
+
rpath_cmds = rpath_cmds.last if last
|
429
442
|
|
430
443
|
# Cast rpath_cmds into an Array so we can handle the uniq and non-uniq cases the same way
|
431
|
-
rpath_cmds = Array(
|
444
|
+
rpath_cmds = Array(rpath_cmds)
|
432
445
|
raise RpathUnknownError, path if rpath_cmds.empty?
|
433
446
|
|
434
447
|
# delete the commands in reverse order, offset descending.
|
@@ -592,7 +605,7 @@ module MachO
|
|
592
605
|
LoadCommands::LoadCommand
|
593
606
|
end
|
594
607
|
|
595
|
-
view = MachOView.new(@raw_data, endianness, offset)
|
608
|
+
view = MachOView.new(self, @raw_data, endianness, offset)
|
596
609
|
command = klass.new_from_bin(view)
|
597
610
|
|
598
611
|
load_commands << command
|
data/lib/macho/sections.rb
CHANGED
@@ -89,61 +89,38 @@ module MachO
|
|
89
89
|
# Represents a section of a segment for 32-bit architectures.
|
90
90
|
class Section < MachOStructure
|
91
91
|
# @return [String] the name of the section, including null pad bytes
|
92
|
-
|
92
|
+
field :sectname, :string, :padding => :null, :size => 16
|
93
93
|
|
94
94
|
# @return [String] the name of the segment's section, including null
|
95
95
|
# pad bytes
|
96
|
-
|
96
|
+
field :segname, :string, :padding => :null, :size => 16
|
97
97
|
|
98
98
|
# @return [Integer] the memory address of the section
|
99
|
-
|
99
|
+
field :addr, :uint32
|
100
100
|
|
101
101
|
# @return [Integer] the size, in bytes, of the section
|
102
|
-
|
102
|
+
field :size, :uint32
|
103
103
|
|
104
104
|
# @return [Integer] the file offset of the section
|
105
|
-
|
105
|
+
field :offset, :uint32
|
106
106
|
|
107
107
|
# @return [Integer] the section alignment (power of 2) of the section
|
108
|
-
|
108
|
+
field :align, :uint32
|
109
109
|
|
110
110
|
# @return [Integer] the file offset of the section's relocation entries
|
111
|
-
|
111
|
+
field :reloff, :uint32
|
112
112
|
|
113
113
|
# @return [Integer] the number of relocation entries
|
114
|
-
|
114
|
+
field :nreloc, :uint32
|
115
115
|
|
116
116
|
# @return [Integer] flags for type and attributes of the section
|
117
|
-
|
117
|
+
field :flags, :uint32
|
118
118
|
|
119
119
|
# @return [void] reserved (for offset or index)
|
120
|
-
|
120
|
+
field :reserved1, :uint32
|
121
121
|
|
122
122
|
# @return [void] reserved (for count or sizeof)
|
123
|
-
|
124
|
-
|
125
|
-
# @see MachOStructure::FORMAT
|
126
|
-
FORMAT = "Z16Z16L=9"
|
127
|
-
|
128
|
-
# @see MachOStructure::SIZEOF
|
129
|
-
SIZEOF = 68
|
130
|
-
|
131
|
-
# @api private
|
132
|
-
def initialize(sectname, segname, addr, size, offset, align, reloff,
|
133
|
-
nreloc, flags, reserved1, reserved2)
|
134
|
-
super()
|
135
|
-
@sectname = sectname
|
136
|
-
@segname = segname
|
137
|
-
@addr = addr
|
138
|
-
@size = size
|
139
|
-
@offset = offset
|
140
|
-
@align = align
|
141
|
-
@reloff = reloff
|
142
|
-
@nreloc = nreloc
|
143
|
-
@flags = flags
|
144
|
-
@reserved1 = reserved1
|
145
|
-
@reserved2 = reserved2
|
146
|
-
end
|
123
|
+
field :reserved2, :uint32
|
147
124
|
|
148
125
|
# @return [String] the section's name
|
149
126
|
def section_name
|
@@ -219,22 +196,14 @@ module MachO
|
|
219
196
|
|
220
197
|
# Represents a section of a segment for 64-bit architectures.
|
221
198
|
class Section64 < Section
|
222
|
-
# @return [
|
223
|
-
|
224
|
-
|
225
|
-
# @see MachOStructure::FORMAT
|
226
|
-
FORMAT = "Z16Z16Q=2L=8"
|
199
|
+
# @return [Integer] the memory address of the section
|
200
|
+
field :addr, :uint64
|
227
201
|
|
228
|
-
# @
|
229
|
-
|
202
|
+
# @return [Integer] the size, in bytes, of the section
|
203
|
+
field :size, :uint64
|
230
204
|
|
231
|
-
# @
|
232
|
-
|
233
|
-
nreloc, flags, reserved1, reserved2, reserved3)
|
234
|
-
super(sectname, segname, addr, size, offset, align, reloff,
|
235
|
-
nreloc, flags, reserved1, reserved2)
|
236
|
-
@reserved3 = reserved3
|
237
|
-
end
|
205
|
+
# @return [void] reserved
|
206
|
+
field :reserved3, :uint32
|
238
207
|
|
239
208
|
# @return [Hash] a hash representation of this {Section64}
|
240
209
|
def to_h
|
data/lib/macho/structure.rb
CHANGED
@@ -1,42 +1,284 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module MachO
|
4
|
-
# A general purpose pseudo-structure.
|
4
|
+
# A general purpose pseudo-structure. Described in detail in docs/machostructure-dsl.md.
|
5
5
|
# @abstract
|
6
6
|
class MachOStructure
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
7
|
+
# Constants used for parsing MachOStructure fields
|
8
|
+
module Fields
|
9
|
+
# 1. All fields with empty strings and zeros aren't used
|
10
|
+
# to calculate the format and sizeof variables.
|
11
|
+
# 2. All fields with nil should provide those values manually
|
12
|
+
# via the :size parameter.
|
13
|
+
|
14
|
+
# association of field types to byte size
|
15
|
+
# @api private
|
16
|
+
BYTE_SIZE = {
|
17
|
+
# Binary slices
|
18
|
+
:string => nil,
|
19
|
+
:null_padded_string => nil,
|
20
|
+
:int32 => 4,
|
21
|
+
:uint32 => 4,
|
22
|
+
:uint64 => 8,
|
23
|
+
# Classes
|
24
|
+
:view => 0,
|
25
|
+
:lcstr => 4,
|
26
|
+
:two_level_hints_table => 0,
|
27
|
+
:tool_entries => 4,
|
28
|
+
}.freeze
|
29
|
+
|
30
|
+
# association of field types with ruby format codes
|
31
|
+
# Binary format codes can be found here:
|
32
|
+
# https://docs.ruby-lang.org/en/2.6.0/String.html#method-i-unpack
|
33
|
+
#
|
34
|
+
# The equals sign is used to manually change endianness using
|
35
|
+
# the Utils#specialize_format() method.
|
36
|
+
# @api private
|
37
|
+
FORMAT_CODE = {
|
38
|
+
# Binary slices
|
39
|
+
:string => "a",
|
40
|
+
:null_padded_string => "Z",
|
41
|
+
:int32 => "l=",
|
42
|
+
:uint32 => "L=",
|
43
|
+
:uint64 => "Q=",
|
44
|
+
# Classes
|
45
|
+
:view => "",
|
46
|
+
:lcstr => "L=",
|
47
|
+
:two_level_hints_table => "",
|
48
|
+
:tool_entries => "L=",
|
49
|
+
}.freeze
|
50
|
+
|
51
|
+
# A list of classes that must get initialized
|
52
|
+
# To add a new class append it here and add the init method to the def_class_reader method
|
53
|
+
# @api private
|
54
|
+
CLASSES_TO_INIT = %i[lcstr tool_entries two_level_hints_table].freeze
|
55
|
+
|
56
|
+
# A list of fields that don't require arguments in the initializer
|
57
|
+
# Used to calculate MachOStructure#min_args
|
58
|
+
# @api private
|
59
|
+
NO_ARG_REQUIRED = %i[two_level_hints_table].freeze
|
20
60
|
end
|
21
61
|
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
|
27
|
-
format = Utils.specialize_format(self::FORMAT, endianness)
|
62
|
+
# map of field names to indices
|
63
|
+
@field_idxs = {}
|
64
|
+
|
65
|
+
# array of fields sizes
|
66
|
+
@size_list = []
|
28
67
|
|
29
|
-
|
68
|
+
# array of field format codes
|
69
|
+
@fmt_list = []
|
70
|
+
|
71
|
+
# minimum number of required arguments
|
72
|
+
@min_args = 0
|
73
|
+
|
74
|
+
# @param args [Array[Value]] list of field parameters
|
75
|
+
def initialize(*args)
|
76
|
+
raise ArgumentError, "Invalid number of arguments" if args.size < self.class.min_args
|
77
|
+
|
78
|
+
@values = args
|
30
79
|
end
|
31
80
|
|
32
81
|
# @return [Hash] a hash representation of this {MachOStructure}.
|
33
82
|
def to_h
|
34
83
|
{
|
35
84
|
"structure" => {
|
36
|
-
"format" => self.class
|
85
|
+
"format" => self.class.format,
|
37
86
|
"bytesize" => self.class.bytesize,
|
38
87
|
},
|
39
88
|
}
|
40
89
|
end
|
90
|
+
|
91
|
+
class << self
|
92
|
+
attr_reader :min_args
|
93
|
+
|
94
|
+
# @param endianness [Symbol] either `:big` or `:little`
|
95
|
+
# @param bin [String] the string to be unpacked into the new structure
|
96
|
+
# @return [MachO::MachOStructure] the resulting structure
|
97
|
+
# @api private
|
98
|
+
def new_from_bin(endianness, bin)
|
99
|
+
format = Utils.specialize_format(self.format, endianness)
|
100
|
+
|
101
|
+
new(*bin.unpack(format))
|
102
|
+
end
|
103
|
+
|
104
|
+
def format
|
105
|
+
@format ||= @fmt_list.join
|
106
|
+
end
|
107
|
+
|
108
|
+
def bytesize
|
109
|
+
@bytesize ||= @size_list.sum
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# @param subclass [Class] subclass type
|
115
|
+
# @api private
|
116
|
+
def inherited(subclass) # rubocop:disable Lint/MissingSuper
|
117
|
+
# Clone all class instance variables
|
118
|
+
field_idxs = @field_idxs.dup
|
119
|
+
size_list = @size_list.dup
|
120
|
+
fmt_list = @fmt_list.dup
|
121
|
+
min_args = @min_args.dup
|
122
|
+
|
123
|
+
# Add those values to the inheriting class
|
124
|
+
subclass.class_eval do
|
125
|
+
@field_idxs = field_idxs
|
126
|
+
@size_list = size_list
|
127
|
+
@fmt_list = fmt_list
|
128
|
+
@min_args = min_args
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# @param name [Symbol] name of internal field
|
133
|
+
# @param type [Symbol] type of field in terms of binary size
|
134
|
+
# @param options [Hash] set of additional options
|
135
|
+
# Expected options
|
136
|
+
# :size [Integer] size in bytes
|
137
|
+
# :mask [Integer] bitmask
|
138
|
+
# :unpack [String] string format
|
139
|
+
# :default [Value] default value
|
140
|
+
# :to_s [Boolean] flag for generating #to_s
|
141
|
+
# :endian [Symbol] optionally specify :big or :little endian
|
142
|
+
# :padding [Symbol] optionally specify :null padding
|
143
|
+
# @api private
|
144
|
+
def field(name, type, **options)
|
145
|
+
raise ArgumentError, "Invalid field type #{type}" unless Fields::FORMAT_CODE.key?(type)
|
146
|
+
|
147
|
+
# Get field idx for size_list and fmt_list
|
148
|
+
idx = if @field_idxs.key?(name)
|
149
|
+
@field_idxs[name]
|
150
|
+
else
|
151
|
+
@min_args += 1 unless options.key?(:default) || Fields::NO_ARG_REQUIRED.include?(type)
|
152
|
+
@field_idxs[name] = @field_idxs.size
|
153
|
+
@size_list << nil
|
154
|
+
@fmt_list << nil
|
155
|
+
@field_idxs.size - 1
|
156
|
+
end
|
157
|
+
|
158
|
+
# Update string type if padding is specified
|
159
|
+
type = :null_padded_string if type == :string && options[:padding] == :null
|
160
|
+
|
161
|
+
# Add to size_list and fmt_list
|
162
|
+
@size_list[idx] = Fields::BYTE_SIZE[type] || options[:size]
|
163
|
+
@fmt_list[idx] = if options[:endian]
|
164
|
+
Utils.specialize_format(Fields::FORMAT_CODE[type], options[:endian])
|
165
|
+
else
|
166
|
+
Fields::FORMAT_CODE[type]
|
167
|
+
end
|
168
|
+
@fmt_list[idx] += options[:size].to_s if options.key?(:size)
|
169
|
+
|
170
|
+
# Generate methods
|
171
|
+
if Fields::CLASSES_TO_INIT.include?(type)
|
172
|
+
def_class_reader(name, type, idx)
|
173
|
+
elsif options.key?(:mask)
|
174
|
+
def_mask_reader(name, idx, options[:mask])
|
175
|
+
elsif options.key?(:unpack)
|
176
|
+
def_unpack_reader(name, idx, options[:unpack])
|
177
|
+
elsif options.key?(:default)
|
178
|
+
def_default_reader(name, idx, options[:default])
|
179
|
+
else
|
180
|
+
def_reader(name, idx)
|
181
|
+
end
|
182
|
+
|
183
|
+
def_to_s(name) if options[:to_s]
|
184
|
+
end
|
185
|
+
|
186
|
+
#
|
187
|
+
# Method Generators
|
188
|
+
#
|
189
|
+
|
190
|
+
# Generates a reader method for classes that need to be initialized.
|
191
|
+
# These classes are defined in the Fields::CLASSES_TO_INIT array.
|
192
|
+
# @param name [Symbol] name of internal field
|
193
|
+
# @param type [Symbol] type of field in terms of binary size
|
194
|
+
# @param idx [Integer] the index of the field value in the @values array
|
195
|
+
# @api private
|
196
|
+
def def_class_reader(name, type, idx)
|
197
|
+
case type
|
198
|
+
when :lcstr
|
199
|
+
define_method(name) do
|
200
|
+
instance_variable_defined?("@#{name}") ||
|
201
|
+
instance_variable_set("@#{name}", LoadCommands::LoadCommand::LCStr.new(self, @values[idx]))
|
202
|
+
|
203
|
+
instance_variable_get("@#{name}")
|
204
|
+
end
|
205
|
+
when :two_level_hints_table
|
206
|
+
define_method(name) do
|
207
|
+
instance_variable_defined?("@#{name}") ||
|
208
|
+
instance_variable_set("@#{name}", LoadCommands::TwolevelHintsCommand::TwolevelHintsTable.new(view, htoffset, nhints))
|
209
|
+
|
210
|
+
instance_variable_get("@#{name}")
|
211
|
+
end
|
212
|
+
when :tool_entries
|
213
|
+
define_method(name) do
|
214
|
+
instance_variable_defined?("@#{name}") ||
|
215
|
+
instance_variable_set("@#{name}", LoadCommands::BuildVersionCommand::ToolEntries.new(view, @values[idx]))
|
216
|
+
|
217
|
+
instance_variable_get("@#{name}")
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Generates a reader method for fields that need to be bitmasked.
|
223
|
+
# @param name [Symbol] name of internal field
|
224
|
+
# @param idx [Integer] the index of the field value in the @values array
|
225
|
+
# @param mask [Integer] the bitmask
|
226
|
+
# @api private
|
227
|
+
def def_mask_reader(name, idx, mask)
|
228
|
+
define_method(name) do
|
229
|
+
instance_variable_defined?("@#{name}") ||
|
230
|
+
instance_variable_set("@#{name}", @values[idx] & ~mask)
|
231
|
+
|
232
|
+
instance_variable_get("@#{name}")
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
# Generates a reader method for fields that need further unpacking.
|
237
|
+
# @param name [Symbol] name of internal field
|
238
|
+
# @param idx [Integer] the index of the field value in the @values array
|
239
|
+
# @param unpack [String] the format code used for further binary unpacking
|
240
|
+
# @api private
|
241
|
+
def def_unpack_reader(name, idx, unpack)
|
242
|
+
define_method(name) do
|
243
|
+
instance_variable_defined?("@#{name}") ||
|
244
|
+
instance_variable_set("@#{name}", @values[idx].unpack(unpack))
|
245
|
+
|
246
|
+
instance_variable_get("@#{name}")
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# Generates a reader method for fields that have default values.
|
251
|
+
# @param name [Symbol] name of internal field
|
252
|
+
# @param idx [Integer] the index of the field value in the @values array
|
253
|
+
# @param default [Value] the default value
|
254
|
+
# @api private
|
255
|
+
def def_default_reader(name, idx, default)
|
256
|
+
define_method(name) do
|
257
|
+
instance_variable_defined?("@#{name}") ||
|
258
|
+
instance_variable_set("@#{name}", @values.size > idx ? @values[idx] : default)
|
259
|
+
|
260
|
+
instance_variable_get("@#{name}")
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Generates an attr_reader like method for a field.
|
265
|
+
# @param name [Symbol] name of internal field
|
266
|
+
# @param idx [Integer] the index of the field value in the @values array
|
267
|
+
# @api private
|
268
|
+
def def_reader(name, idx)
|
269
|
+
define_method(name) do
|
270
|
+
@values[idx]
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
# Generates the to_s method based on the named field.
|
275
|
+
# @param name [Symbol] name of the field
|
276
|
+
# @api private
|
277
|
+
def def_to_s(name)
|
278
|
+
define_method(:to_s) do
|
279
|
+
send(name).to_s
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
41
283
|
end
|
42
284
|
end
|
data/lib/macho/view.rb
CHANGED
@@ -3,6 +3,9 @@
|
|
3
3
|
module MachO
|
4
4
|
# A representation of some unspecified Mach-O data.
|
5
5
|
class MachOView
|
6
|
+
# @return [MachOFile] that this view belongs to
|
7
|
+
attr_reader :macho_file
|
8
|
+
|
6
9
|
# @return [String] the raw Mach-O data
|
7
10
|
attr_reader :raw_data
|
8
11
|
|
@@ -13,10 +16,12 @@ module MachO
|
|
13
16
|
attr_reader :offset
|
14
17
|
|
15
18
|
# Creates a new MachOView.
|
19
|
+
# @param macho_file [MachOFile] the file this view slice is from
|
16
20
|
# @param raw_data [String] the raw Mach-O data
|
17
21
|
# @param endianness [Symbol] the endianness of the data
|
18
22
|
# @param offset [Integer] the offset of the relevant data
|
19
|
-
def initialize(raw_data, endianness, offset)
|
23
|
+
def initialize(macho_file, raw_data, endianness, offset)
|
24
|
+
@macho_file = macho_file
|
20
25
|
@raw_data = raw_data
|
21
26
|
@endianness = endianness
|
22
27
|
@offset = offset
|
@@ -29,5 +34,9 @@ module MachO
|
|
29
34
|
"offset" => offset,
|
30
35
|
}
|
31
36
|
end
|
37
|
+
|
38
|
+
def inspect
|
39
|
+
"#<#{self.class}:0x#{(object_id << 1).to_s(16)} @endianness=#{@endianness.inspect}, @offset=#{@offset.inspect}, length=#{@raw_data.length}>"
|
40
|
+
end
|
32
41
|
end
|
33
42
|
end
|
data/lib/macho.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "open3"
|
4
4
|
|
5
|
+
require_relative "macho/utils"
|
5
6
|
require_relative "macho/structure"
|
6
7
|
require_relative "macho/view"
|
7
8
|
require_relative "macho/headers"
|
@@ -10,13 +11,12 @@ require_relative "macho/sections"
|
|
10
11
|
require_relative "macho/macho_file"
|
11
12
|
require_relative "macho/fat_file"
|
12
13
|
require_relative "macho/exceptions"
|
13
|
-
require_relative "macho/utils"
|
14
14
|
require_relative "macho/tools"
|
15
15
|
|
16
16
|
# The primary namespace for ruby-macho.
|
17
17
|
module MachO
|
18
18
|
# release version
|
19
|
-
VERSION = "
|
19
|
+
VERSION = "4.0.1"
|
20
20
|
|
21
21
|
# Opens the given filename as a MachOFile or FatFile, depending on its magic.
|
22
22
|
# @param filename [String] the file being opened
|
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:
|
4
|
+
version: 4.0.1
|
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: 2024-02-16 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
|
@@ -33,7 +33,8 @@ files:
|
|
33
33
|
homepage: https://github.com/Homebrew/ruby-macho
|
34
34
|
licenses:
|
35
35
|
- MIT
|
36
|
-
metadata:
|
36
|
+
metadata:
|
37
|
+
rubygems_mfa_required: 'true'
|
37
38
|
post_install_message:
|
38
39
|
rdoc_options: []
|
39
40
|
require_paths:
|
@@ -49,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
50
|
- !ruby/object:Gem::Version
|
50
51
|
version: '0'
|
51
52
|
requirements: []
|
52
|
-
rubygems_version: 3.
|
53
|
+
rubygems_version: 3.4.10
|
53
54
|
signing_key:
|
54
55
|
specification_version: 4
|
55
56
|
summary: ruby-macho - Mach-O file analyzer.
|