ruby-macho 4.0.1 → 5.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 +1 -1
- data/lib/macho/exceptions.rb +31 -31
- data/lib/macho/headers.rb +21 -9
- data/lib/macho/load_commands.rb +124 -4
- data/lib/macho/structure.rb +1 -1
- data/lib/macho.rb +1 -1
- metadata +5 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 848be7615c0a26614ffc950ffd7a70b3efe594a4c2608aeb776d2f7a0fca472d
|
|
4
|
+
data.tar.gz: e8e084691a090ddd084196567ee80848b2cb546f9bff70ec9d43b8a8a45b0cef
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2117ef6313e528a636b43b5c45c17729627cfae074957c6bfc7486040daf4c10b3f6ce74dc48a72a8375821f77de34d723c6c586eda27a5d0cc71d47a33cc42b
|
|
7
|
+
data.tar.gz: cc3a7f948e6d9f6ae71b7f0f96eef0945d5269c8e59ab09239a61ce8f8564c9faa8b4484940907dc6bb299435f54d9a1c5b89714c692b15a048b0c0c49f6f955
|
data/README.md
CHANGED
|
@@ -3,7 +3,7 @@ ruby-macho
|
|
|
3
3
|
|
|
4
4
|
[](http://badge.fury.io/rb/ruby-macho)
|
|
5
5
|
[](https://github.com/Homebrew/ruby-macho/actions/workflows/tests.yml)
|
|
6
|
-
[](https://codecov.io/gh/Homebrew/ruby-macho)
|
|
7
7
|
|
|
8
8
|
A Ruby library for examining and modifying Mach-O files.
|
|
9
9
|
|
data/lib/macho/exceptions.rb
CHANGED
|
@@ -37,7 +37,7 @@ module MachO
|
|
|
37
37
|
# Raised when a file is too short to be a valid Mach-O file.
|
|
38
38
|
class TruncatedFileError < NotAMachOError
|
|
39
39
|
def initialize
|
|
40
|
-
super
|
|
40
|
+
super("File is too short to be a valid Mach-O")
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -45,21 +45,21 @@ module MachO
|
|
|
45
45
|
class MagicError < NotAMachOError
|
|
46
46
|
# @param num [Integer] the unknown number
|
|
47
47
|
def initialize(magic)
|
|
48
|
-
super
|
|
48
|
+
super("Unrecognized Mach-O magic: 0x%02<magic>x" % { :magic => magic })
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
# Raised when a file is a Java classfile instead of a fat Mach-O.
|
|
53
53
|
class JavaClassFileError < NotAMachOError
|
|
54
54
|
def initialize
|
|
55
|
-
super
|
|
55
|
+
super("File is a Java class file")
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
# Raised when a a fat Mach-O file has zero architectures
|
|
60
60
|
class ZeroArchitectureError < NotAMachOError
|
|
61
61
|
def initialize
|
|
62
|
-
super
|
|
62
|
+
super("Fat file has zero internal architectures")
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
|
|
@@ -71,24 +71,24 @@ module MachO
|
|
|
71
71
|
# @param cpusubtype_fat [Integer] the CPU subtype in the fat header
|
|
72
72
|
# @param cputype_macho [Integer] the CPU type in the macho header
|
|
73
73
|
# @param cpusubtype_macho [Integer] the CPU subtype in the macho header
|
|
74
|
-
super
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
78
|
end
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
# Raised when a fat binary is loaded with MachOFile.
|
|
82
82
|
class FatBinaryError < MachOError
|
|
83
83
|
def initialize
|
|
84
|
-
super
|
|
84
|
+
super("Fat binaries must be loaded with MachO::FatFile")
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
# Raised when a Mach-O is loaded with FatFile.
|
|
89
89
|
class MachOBinaryError < MachOError
|
|
90
90
|
def initialize
|
|
91
|
-
super
|
|
91
|
+
super("Normal binaries must be loaded with MachO::MachOFile")
|
|
92
92
|
end
|
|
93
93
|
end
|
|
94
94
|
|
|
@@ -96,7 +96,7 @@ module MachO
|
|
|
96
96
|
class CPUTypeError < MachOError
|
|
97
97
|
# @param cputype [Integer] the unknown CPU type
|
|
98
98
|
def initialize(cputype)
|
|
99
|
-
super
|
|
99
|
+
super("Unrecognized CPU type: 0x%08<cputype>x" % { :cputype => cputype })
|
|
100
100
|
end
|
|
101
101
|
end
|
|
102
102
|
|
|
@@ -105,8 +105,8 @@ module MachO
|
|
|
105
105
|
# @param cputype [Integer] the CPU type of the unknown pair
|
|
106
106
|
# @param cpusubtype [Integer] the CPU sub-type of the unknown pair
|
|
107
107
|
def initialize(cputype, cpusubtype)
|
|
108
|
-
super
|
|
109
|
-
"(for CPU type: 0x%08<cputype>x" % { :cputype => cputype, :cpusubtype => cpusubtype }
|
|
108
|
+
super("Unrecognized CPU sub-type: 0x%08<cpusubtype>x " \
|
|
109
|
+
"(for CPU type: 0x%08<cputype>x" % { :cputype => cputype, :cpusubtype => cpusubtype })
|
|
110
110
|
end
|
|
111
111
|
end
|
|
112
112
|
|
|
@@ -114,7 +114,7 @@ module MachO
|
|
|
114
114
|
class FiletypeError < MachOError
|
|
115
115
|
# @param num [Integer] the unknown number
|
|
116
116
|
def initialize(num)
|
|
117
|
-
super
|
|
117
|
+
super("Unrecognized Mach-O filetype code: 0x%02<num>x" % { :num => num })
|
|
118
118
|
end
|
|
119
119
|
end
|
|
120
120
|
|
|
@@ -122,7 +122,7 @@ module MachO
|
|
|
122
122
|
class LoadCommandError < MachOError
|
|
123
123
|
# @param num [Integer] the unknown number
|
|
124
124
|
def initialize(num)
|
|
125
|
-
super
|
|
125
|
+
super("Unrecognized Mach-O load command: 0x%02<num>x" % { :num => num })
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
128
|
|
|
@@ -130,7 +130,7 @@ module MachO
|
|
|
130
130
|
class LoadCommandNotCreatableError < MachOError
|
|
131
131
|
# @param cmd_sym [Symbol] the uncreatable load command's symbol
|
|
132
132
|
def initialize(cmd_sym)
|
|
133
|
-
super
|
|
133
|
+
super("Load commands of type #{cmd_sym} cannot be created manually")
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
|
|
@@ -141,8 +141,8 @@ module MachO
|
|
|
141
141
|
# @param expected_arity [Integer] the number of arguments expected
|
|
142
142
|
# @param actual_arity [Integer] the number of arguments received
|
|
143
143
|
def initialize(cmd_sym, expected_arity, actual_arity)
|
|
144
|
-
super
|
|
145
|
-
"got #{actual_arity}"
|
|
144
|
+
super("Expected #{expected_arity} arguments for #{cmd_sym} creation, " \
|
|
145
|
+
"got #{actual_arity}")
|
|
146
146
|
end
|
|
147
147
|
end
|
|
148
148
|
|
|
@@ -150,7 +150,7 @@ module MachO
|
|
|
150
150
|
class LoadCommandNotSerializableError < MachOError
|
|
151
151
|
# @param cmd_sym [Symbol] the load command's symbol
|
|
152
152
|
def initialize(cmd_sym)
|
|
153
|
-
super
|
|
153
|
+
super("Load commands of type #{cmd_sym} cannot be serialized")
|
|
154
154
|
end
|
|
155
155
|
end
|
|
156
156
|
|
|
@@ -158,8 +158,8 @@ module MachO
|
|
|
158
158
|
class LCStrMalformedError < MachOError
|
|
159
159
|
# @param lc [MachO::LoadCommand] the load command containing the string
|
|
160
160
|
def initialize(lc)
|
|
161
|
-
super
|
|
162
|
-
"malformed string"
|
|
161
|
+
super("Load command #{lc.type} at offset #{lc.view.offset} contains a " \
|
|
162
|
+
"malformed string")
|
|
163
163
|
end
|
|
164
164
|
end
|
|
165
165
|
|
|
@@ -167,7 +167,7 @@ module MachO
|
|
|
167
167
|
class OffsetInsertionError < ModificationError
|
|
168
168
|
# @param offset [Integer] the invalid offset
|
|
169
169
|
def initialize(offset)
|
|
170
|
-
super
|
|
170
|
+
super("Insertion at offset #{offset} is not valid")
|
|
171
171
|
end
|
|
172
172
|
end
|
|
173
173
|
|
|
@@ -175,9 +175,9 @@ module MachO
|
|
|
175
175
|
class HeaderPadError < ModificationError
|
|
176
176
|
# @param filename [String] the filename
|
|
177
177
|
def initialize(filename)
|
|
178
|
-
super
|
|
178
|
+
super("Updated load commands do not fit in the header of " \
|
|
179
179
|
"#{filename}. #{filename} needs to be relinked, possibly with " \
|
|
180
|
-
"-headerpad or -headerpad_max_install_names"
|
|
180
|
+
"-headerpad or -headerpad_max_install_names")
|
|
181
181
|
end
|
|
182
182
|
end
|
|
183
183
|
|
|
@@ -185,14 +185,14 @@ module MachO
|
|
|
185
185
|
class DylibUnknownError < RecoverableModificationError
|
|
186
186
|
# @param dylib [String] the unknown shared library name
|
|
187
187
|
def initialize(dylib)
|
|
188
|
-
super
|
|
188
|
+
super("No such dylib name: #{dylib}")
|
|
189
189
|
end
|
|
190
190
|
end
|
|
191
191
|
|
|
192
192
|
# Raised when a dylib is missing an ID
|
|
193
193
|
class DylibIdMissingError < RecoverableModificationError
|
|
194
194
|
def initialize
|
|
195
|
-
super
|
|
195
|
+
super("Dylib is missing a dylib ID")
|
|
196
196
|
end
|
|
197
197
|
end
|
|
198
198
|
|
|
@@ -200,7 +200,7 @@ module MachO
|
|
|
200
200
|
class RpathUnknownError < RecoverableModificationError
|
|
201
201
|
# @param path [String] the unknown runtime path
|
|
202
202
|
def initialize(path)
|
|
203
|
-
super
|
|
203
|
+
super("No such runtime path: #{path}")
|
|
204
204
|
end
|
|
205
205
|
end
|
|
206
206
|
|
|
@@ -208,7 +208,7 @@ module MachO
|
|
|
208
208
|
class RpathExistsError < RecoverableModificationError
|
|
209
209
|
# @param path [String] the extant path
|
|
210
210
|
def initialize(path)
|
|
211
|
-
super
|
|
211
|
+
super("#{path} already exists")
|
|
212
212
|
end
|
|
213
213
|
end
|
|
214
214
|
|
|
@@ -216,7 +216,7 @@ module MachO
|
|
|
216
216
|
class UnimplementedError < MachOError
|
|
217
217
|
# @param thing [String] the thing that is unimplemented
|
|
218
218
|
def initialize(thing)
|
|
219
|
-
super
|
|
219
|
+
super("Unimplemented: #{thing}")
|
|
220
220
|
end
|
|
221
221
|
end
|
|
222
222
|
|
|
@@ -225,8 +225,8 @@ module MachO
|
|
|
225
225
|
class FatArchOffsetOverflowError < MachOError
|
|
226
226
|
# @param offset [Integer] the offending offset
|
|
227
227
|
def initialize(offset)
|
|
228
|
-
super
|
|
229
|
-
"Consider merging with `fat64: true`"
|
|
228
|
+
super("Offset #{offset} exceeds the 32-bit width of a fat_arch offset. " \
|
|
229
|
+
"Consider merging with `fat64: true`")
|
|
230
230
|
end
|
|
231
231
|
end
|
|
232
232
|
|
data/lib/macho/headers.rb
CHANGED
|
@@ -60,14 +60,14 @@ module MachO
|
|
|
60
60
|
MH_CIGAM_64 => "MH_CIGAM_64",
|
|
61
61
|
}.freeze
|
|
62
62
|
|
|
63
|
-
# mask for
|
|
63
|
+
# mask for 64-bit CPU architectures with 64-bit types
|
|
64
64
|
# @api private
|
|
65
65
|
CPU_ARCH_ABI64 = 0x01000000
|
|
66
66
|
|
|
67
|
-
# mask for
|
|
67
|
+
# mask for 64-bit CPU architectures with 32-bit types (ILP32)
|
|
68
68
|
# @see https://github.com/Homebrew/ruby-macho/issues/113
|
|
69
69
|
# @api private
|
|
70
|
-
|
|
70
|
+
CPU_ARCH_ABI64_32 = 0x02000000
|
|
71
71
|
|
|
72
72
|
# any CPU (unused?)
|
|
73
73
|
# @api private
|
|
@@ -97,9 +97,10 @@ module MachO
|
|
|
97
97
|
# @api private
|
|
98
98
|
CPU_TYPE_ARM64 = (CPU_TYPE_ARM | CPU_ARCH_ABI64)
|
|
99
99
|
|
|
100
|
-
# 64-bit ARM compatible CPUs (
|
|
100
|
+
# 64-bit ARM compatible CPUs (with 32-bit types)
|
|
101
101
|
# @see https://github.com/Homebrew/ruby-macho/issues/113
|
|
102
|
-
|
|
102
|
+
# @api private
|
|
103
|
+
CPU_TYPE_ARM64_32 = (CPU_TYPE_ARM | CPU_ARCH_ABI64_32)
|
|
103
104
|
|
|
104
105
|
# PowerPC compatible CPUs
|
|
105
106
|
# @api private
|
|
@@ -450,6 +451,14 @@ module MachO
|
|
|
450
451
|
# @api private
|
|
451
452
|
MH_FILESET = 0xc
|
|
452
453
|
|
|
454
|
+
# gpu program
|
|
455
|
+
# @api private
|
|
456
|
+
MH_GPU_EXECUTE = 0xd
|
|
457
|
+
|
|
458
|
+
# gpu support functions
|
|
459
|
+
# @api private
|
|
460
|
+
MH_GPU_DYLIB = 0xe
|
|
461
|
+
|
|
453
462
|
# association of filetypes to Symbol representations
|
|
454
463
|
# @api private
|
|
455
464
|
MH_FILETYPES = {
|
|
@@ -465,6 +474,8 @@ module MachO
|
|
|
465
474
|
MH_DSYM => :dsym,
|
|
466
475
|
MH_KEXT_BUNDLE => :kext_bundle,
|
|
467
476
|
MH_FILESET => :fileset,
|
|
477
|
+
MH_GPU_EXECUTE => :gpu_execute,
|
|
478
|
+
MH_GPU_DYLIB => :gpu_dylib,
|
|
468
479
|
}.freeze
|
|
469
480
|
|
|
470
481
|
# association of mach header flag symbols to values
|
|
@@ -480,7 +491,7 @@ module MachO
|
|
|
480
491
|
:MH_TWOLEVEL => 0x80,
|
|
481
492
|
:MH_FORCE_FLAT => 0x100,
|
|
482
493
|
:MH_NOMULTIDEFS => 0x200,
|
|
483
|
-
:
|
|
494
|
+
:MH_NOFIXPREBINDING => 0x400,
|
|
484
495
|
:MH_PREBINDABLE => 0x800,
|
|
485
496
|
:MH_ALLMODSBOUND => 0x1000,
|
|
486
497
|
:MH_SUBSECTIONS_VIA_SYMBOLS => 0x2000,
|
|
@@ -495,9 +506,10 @@ module MachO
|
|
|
495
506
|
:MH_DEAD_STRIPPABLE_DYLIB => 0x400000,
|
|
496
507
|
:MH_HAS_TLV_DESCRIPTORS => 0x800000,
|
|
497
508
|
:MH_NO_HEAP_EXECUTION => 0x1000000,
|
|
498
|
-
:MH_APP_EXTENSION_SAFE =>
|
|
499
|
-
:MH_NLIST_OUTOFSYNC_WITH_DYLDINFO =>
|
|
500
|
-
:MH_SIM_SUPPORT =>
|
|
509
|
+
:MH_APP_EXTENSION_SAFE => 0x2000000,
|
|
510
|
+
:MH_NLIST_OUTOFSYNC_WITH_DYLDINFO => 0x4000000,
|
|
511
|
+
:MH_SIM_SUPPORT => 0x8000000,
|
|
512
|
+
:MH_IMPLICIT_PAGEZERO => 0x10000000,
|
|
501
513
|
:MH_DYLIB_IN_CACHE => 0x80000000,
|
|
502
514
|
}.freeze
|
|
503
515
|
|
data/lib/macho/load_commands.rb
CHANGED
|
@@ -65,6 +65,10 @@ module MachO
|
|
|
65
65
|
(LC_REQ_DYLD | 0x33) => :LC_DYLD_EXPORTS_TRIE,
|
|
66
66
|
(LC_REQ_DYLD | 0x34) => :LC_DYLD_CHAINED_FIXUPS,
|
|
67
67
|
(LC_REQ_DYLD | 0x35) => :LC_FILESET_ENTRY,
|
|
68
|
+
0x36 => :LC_ATOM_INFO,
|
|
69
|
+
0x37 => :LC_FUNCTION_VARIANTS,
|
|
70
|
+
0x38 => :LC_FUNCTION_VARIANT_FIXUPS,
|
|
71
|
+
0x39 => :LC_TARGET_TRIPLE,
|
|
68
72
|
}.freeze
|
|
69
73
|
|
|
70
74
|
# association of symbol representations to load command constants
|
|
@@ -110,7 +114,7 @@ module MachO
|
|
|
110
114
|
# "reserved for internal use only", no public struct
|
|
111
115
|
:LC_PREPAGE => "LoadCommand",
|
|
112
116
|
:LC_DYSYMTAB => "DysymtabCommand",
|
|
113
|
-
:LC_LOAD_DYLIB => "
|
|
117
|
+
:LC_LOAD_DYLIB => "DylibUseCommand",
|
|
114
118
|
:LC_ID_DYLIB => "DylibCommand",
|
|
115
119
|
:LC_LOAD_DYLINKER => "DylinkerCommand",
|
|
116
120
|
:LC_ID_DYLINKER => "DylinkerCommand",
|
|
@@ -122,7 +126,7 @@ module MachO
|
|
|
122
126
|
:LC_SUB_LIBRARY => "SubLibraryCommand",
|
|
123
127
|
:LC_TWOLEVEL_HINTS => "TwolevelHintsCommand",
|
|
124
128
|
:LC_PREBIND_CKSUM => "PrebindCksumCommand",
|
|
125
|
-
:LC_LOAD_WEAK_DYLIB => "
|
|
129
|
+
:LC_LOAD_WEAK_DYLIB => "DylibUseCommand",
|
|
126
130
|
:LC_SEGMENT_64 => "SegmentCommand64",
|
|
127
131
|
:LC_ROUTINES_64 => "RoutinesCommand64",
|
|
128
132
|
:LC_UUID => "UUIDCommand",
|
|
@@ -153,6 +157,10 @@ module MachO
|
|
|
153
157
|
:LC_DYLD_EXPORTS_TRIE => "LinkeditDataCommand",
|
|
154
158
|
:LC_DYLD_CHAINED_FIXUPS => "LinkeditDataCommand",
|
|
155
159
|
:LC_FILESET_ENTRY => "FilesetEntryCommand",
|
|
160
|
+
:LC_ATOM_INFO => "LinkeditDataCommand",
|
|
161
|
+
:LC_FUNCTION_VARIANTS => "LinkeditDataCommand",
|
|
162
|
+
:LC_FUNCTION_VARIANT_FIXUPS => "LinkeditDataCommand",
|
|
163
|
+
:LC_TARGET_TRIPLE => "TargetTripleCommand",
|
|
156
164
|
}.freeze
|
|
157
165
|
|
|
158
166
|
# association of segment name symbols to names
|
|
@@ -193,6 +201,20 @@ module MachO
|
|
|
193
201
|
:SG_READ_ONLY => 0x10,
|
|
194
202
|
}.freeze
|
|
195
203
|
|
|
204
|
+
# association of dylib use flag symbols to values
|
|
205
|
+
# @api private
|
|
206
|
+
DYLIB_USE_FLAGS = {
|
|
207
|
+
:DYLIB_USE_WEAK_LINK => 0x1,
|
|
208
|
+
:DYLIB_USE_REEXPORT => 0x2,
|
|
209
|
+
:DYLIB_USE_UPWARD => 0x4,
|
|
210
|
+
:DYLIB_USE_DELAYED_INIT => 0x8,
|
|
211
|
+
}.freeze
|
|
212
|
+
|
|
213
|
+
# the marker used to denote a newer style dylib use command.
|
|
214
|
+
# the value is the timestamp 24 January 1984 18:12:16
|
|
215
|
+
# @api private
|
|
216
|
+
DYLIB_USE_MARKER = 0x1a741800
|
|
217
|
+
|
|
196
218
|
# The top-level Mach-O load command structure.
|
|
197
219
|
#
|
|
198
220
|
# This is the most generic load command -- only the type ID and size are
|
|
@@ -231,6 +253,13 @@ module MachO
|
|
|
231
253
|
# cmd will be filled in, view and cmdsize will be left unpopulated
|
|
232
254
|
klass_arity = klass.min_args - 3
|
|
233
255
|
|
|
256
|
+
# macOS 15 introduces a new dylib load command that adds a flags field to the end.
|
|
257
|
+
# It uses the same commands with it dynamically being created if the dylib has a flags field
|
|
258
|
+
if klass == DylibUseCommand && (args[1] != DYLIB_USE_MARKER || args.size <= DylibCommand.min_args - 3)
|
|
259
|
+
klass = DylibCommand
|
|
260
|
+
klass_arity = klass.min_args - 3
|
|
261
|
+
end
|
|
262
|
+
|
|
234
263
|
raise LoadCommandCreationArityError.new(cmd_sym, klass_arity, args.size) if klass_arity > args.size
|
|
235
264
|
|
|
236
265
|
klass.new(nil, cmd, nil, *args)
|
|
@@ -465,7 +494,7 @@ module MachO
|
|
|
465
494
|
align = 0
|
|
466
495
|
segalign = 1
|
|
467
496
|
|
|
468
|
-
while (
|
|
497
|
+
while segalign.nobits?(vmaddr)
|
|
469
498
|
segalign <<= 1
|
|
470
499
|
align += 1
|
|
471
500
|
end
|
|
@@ -526,6 +555,23 @@ module MachO
|
|
|
526
555
|
# @return [Integer] the library's compatibility version number
|
|
527
556
|
field :compatibility_version, :uint32
|
|
528
557
|
|
|
558
|
+
# @example
|
|
559
|
+
# puts "this dylib is weakly loaded" if dylib_command.flag?(:DYLIB_USE_WEAK_LINK)
|
|
560
|
+
# @param flag [Symbol] a dylib use command flag symbol
|
|
561
|
+
# @return [Boolean] true if `flag` applies to this dylib command
|
|
562
|
+
def flag?(flag)
|
|
563
|
+
case cmd
|
|
564
|
+
when LOAD_COMMAND_CONSTANTS[:LC_LOAD_WEAK_DYLIB]
|
|
565
|
+
flag == :DYLIB_USE_WEAK_LINK
|
|
566
|
+
when LOAD_COMMAND_CONSTANTS[:LC_REEXPORT_DYLIB]
|
|
567
|
+
flag == :DYLIB_USE_REEXPORT
|
|
568
|
+
when LOAD_COMMAND_CONSTANTS[:LC_LOAD_UPWARD_DYLIB]
|
|
569
|
+
flag == :DYLIB_USE_UPWARD
|
|
570
|
+
else
|
|
571
|
+
false
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
|
|
529
575
|
# @param context [SerializationContext]
|
|
530
576
|
# the context
|
|
531
577
|
# @return [String] the serialized fields of the load command
|
|
@@ -551,6 +597,65 @@ module MachO
|
|
|
551
597
|
end
|
|
552
598
|
end
|
|
553
599
|
|
|
600
|
+
# The newer format of load command representing some aspect of shared libraries,
|
|
601
|
+
# depending on filetype. Corresponds to LC_LOAD_DYLIB or LC_LOAD_WEAK_DYLIB.
|
|
602
|
+
class DylibUseCommand < DylibCommand
|
|
603
|
+
# @return [Integer] any flags associated with this dylib use command
|
|
604
|
+
field :flags, :uint32
|
|
605
|
+
|
|
606
|
+
alias marker timestamp
|
|
607
|
+
|
|
608
|
+
# Instantiates a new DylibCommand or DylibUseCommand.
|
|
609
|
+
# macOS 15 and later use a new format for dylib commands (DylibUseCommand),
|
|
610
|
+
# which is determined based on a special timestamp and the name offset.
|
|
611
|
+
# @param view [MachO::MachOView] the load command's raw view
|
|
612
|
+
# @return [DylibCommand] the new dylib load command
|
|
613
|
+
# @api private
|
|
614
|
+
def self.new_from_bin(view)
|
|
615
|
+
dylib_command = DylibCommand.new_from_bin(view)
|
|
616
|
+
|
|
617
|
+
if dylib_command.timestamp == DYLIB_USE_MARKER &&
|
|
618
|
+
dylib_command.name.to_i == DylibUseCommand.bytesize
|
|
619
|
+
super
|
|
620
|
+
else
|
|
621
|
+
dylib_command
|
|
622
|
+
end
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
# @example
|
|
626
|
+
# puts "this dylib is weakly loaded" if dylib_command.flag?(:DYLIB_USE_WEAK_LINK)
|
|
627
|
+
# @param flag [Symbol] a dylib use command flag symbol
|
|
628
|
+
# @return [Boolean] true if `flag` applies to this dylib command
|
|
629
|
+
def flag?(flag)
|
|
630
|
+
flag = DYLIB_USE_FLAGS[flag]
|
|
631
|
+
|
|
632
|
+
return false if flag.nil?
|
|
633
|
+
|
|
634
|
+
flags & flag == flag
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
# @param context [SerializationContext]
|
|
638
|
+
# the context
|
|
639
|
+
# @return [String] the serialized fields of the load command
|
|
640
|
+
# @api private
|
|
641
|
+
def serialize(context)
|
|
642
|
+
format = Utils.specialize_format(self.class.format, context.endianness)
|
|
643
|
+
string_payload, string_offsets = Utils.pack_strings(self.class.bytesize,
|
|
644
|
+
context.alignment,
|
|
645
|
+
:name => name.to_s)
|
|
646
|
+
cmdsize = self.class.bytesize + string_payload.bytesize
|
|
647
|
+
[cmd, cmdsize, string_offsets[:name], marker, current_version,
|
|
648
|
+
compatibility_version, flags].pack(format) + string_payload
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
# @return [Hash] a hash representation of this {DylibUseCommand}
|
|
652
|
+
def to_h
|
|
653
|
+
{
|
|
654
|
+
"flags" => flags,
|
|
655
|
+
}.merge super
|
|
656
|
+
end
|
|
657
|
+
end
|
|
658
|
+
|
|
554
659
|
# A load command representing some aspect of the dynamic linker, depending
|
|
555
660
|
# on filetype. Corresponds to LC_ID_DYLINKER, LC_LOAD_DYLINKER, and
|
|
556
661
|
# LC_DYLD_ENVIRONMENT.
|
|
@@ -954,11 +1059,26 @@ module MachO
|
|
|
954
1059
|
end
|
|
955
1060
|
end
|
|
956
1061
|
|
|
1062
|
+
# A load command containing the target triple used when compiling the binary.
|
|
1063
|
+
# Corresponds to LC_TARGET_TRIPLE.
|
|
1064
|
+
class TargetTripleCommand < LoadCommand
|
|
1065
|
+
# @return [LCStr] the target triple used when compiling the binary
|
|
1066
|
+
field :triple, :lcstr, :to_s => true
|
|
1067
|
+
|
|
1068
|
+
# @return [Hash] a hash representation of this {TargetTripleCommand}
|
|
1069
|
+
def to_h
|
|
1070
|
+
{
|
|
1071
|
+
"triple" => triple.to_h,
|
|
1072
|
+
}.merge super
|
|
1073
|
+
end
|
|
1074
|
+
end
|
|
1075
|
+
|
|
957
1076
|
# A load command representing the offsets and sizes of a blob of data in
|
|
958
1077
|
# the __LINKEDIT segment. Corresponds to LC_CODE_SIGNATURE,
|
|
959
1078
|
# LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE,
|
|
960
1079
|
# LC_DYLIB_CODE_SIGN_DRS, LC_LINKER_OPTIMIZATION_HINT, LC_DYLD_EXPORTS_TRIE,
|
|
961
|
-
#
|
|
1080
|
+
# LC_DYLD_CHAINED_FIXUPS, LC_ATOM_INFO, LC_FUNCTION_VARIANTS,
|
|
1081
|
+
# or LC_FUNCTION_VARIANT_FIXUPS.
|
|
962
1082
|
class LinkeditDataCommand < LoadCommand
|
|
963
1083
|
# @return [Integer] offset to the data in the __LINKEDIT segment
|
|
964
1084
|
field :dataoff, :uint32
|
data/lib/macho/structure.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module MachO
|
|
4
|
-
# A general purpose pseudo-structure. Described in detail in
|
|
4
|
+
# A general purpose pseudo-structure. Described in detail in machostructure-dsl-docs.md.
|
|
5
5
|
# @abstract
|
|
6
6
|
class MachOStructure
|
|
7
7
|
# Constants used for parsing MachOStructure fields
|
data/lib/macho.rb
CHANGED
|
@@ -16,7 +16,7 @@ require_relative "macho/tools"
|
|
|
16
16
|
# The primary namespace for ruby-macho.
|
|
17
17
|
module MachO
|
|
18
18
|
# release version
|
|
19
|
-
VERSION = "
|
|
19
|
+
VERSION = "5.0.0"
|
|
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,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby-macho
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 5.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- William Woodruff
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies: []
|
|
13
12
|
description: A library for viewing and manipulating Mach-O files in Ruby.
|
|
14
13
|
email: william@yossarian.net
|
|
@@ -35,7 +34,7 @@ licenses:
|
|
|
35
34
|
- MIT
|
|
36
35
|
metadata:
|
|
37
36
|
rubygems_mfa_required: 'true'
|
|
38
|
-
|
|
37
|
+
funding_uri: https://github.com/sponsors/Homebrew
|
|
39
38
|
rdoc_options: []
|
|
40
39
|
require_paths:
|
|
41
40
|
- lib
|
|
@@ -43,15 +42,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
43
42
|
requirements:
|
|
44
43
|
- - ">="
|
|
45
44
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '2
|
|
45
|
+
version: '3.2'
|
|
47
46
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
48
47
|
requirements:
|
|
49
48
|
- - ">="
|
|
50
49
|
- !ruby/object:Gem::Version
|
|
51
50
|
version: '0'
|
|
52
51
|
requirements: []
|
|
53
|
-
rubygems_version:
|
|
54
|
-
signing_key:
|
|
52
|
+
rubygems_version: 4.0.3
|
|
55
53
|
specification_version: 4
|
|
56
54
|
summary: ruby-macho - Mach-O file analyzer.
|
|
57
55
|
test_files: []
|