ruby-macho 0.1.6 → 0.1.8
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 +3 -14
- data/lib/macho/fat_file.rb +58 -0
- data/lib/macho/load_commands.rb +107 -250
- data/lib/macho/macho_file.rb +49 -12
- data/lib/macho/open.rb +16 -0
- data/lib/macho/sections.rb +73 -7
- data/lib/macho/tools.rb +30 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16240f8ca67e156531a460441d739de7d63fbe9e
|
4
|
+
data.tar.gz: 9a4baa19c7d468ea968a1d0eac8f12941053fcf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbf7d99140e66376e18dfae8efc2e0b1d9d921e4f5ba3813a6cf09f478ec5a6de2a777b6b4b582afcf8427a005d3807c6b72f13862b4d7c0d30c476a8711d547
|
7
|
+
data.tar.gz: f2a8064e9246c8b1d5f671edc830a902023f754458a2cc6a4abed62dde247e698d1b955eff5c9e91f8951e66fe6d095fd6677f8a9a7e45f0c34acb435f2b2ed5
|
data/lib/macho.rb
CHANGED
@@ -4,24 +4,13 @@ require "#{File.dirname(__FILE__)}/macho/load_commands"
|
|
4
4
|
require "#{File.dirname(__FILE__)}/macho/sections"
|
5
5
|
require "#{File.dirname(__FILE__)}/macho/macho_file"
|
6
6
|
require "#{File.dirname(__FILE__)}/macho/fat_file"
|
7
|
+
require "#{File.dirname(__FILE__)}/macho/open"
|
7
8
|
require "#{File.dirname(__FILE__)}/macho/exceptions"
|
8
9
|
require "#{File.dirname(__FILE__)}/macho/utils"
|
9
10
|
require "#{File.dirname(__FILE__)}/macho/tools"
|
10
11
|
|
11
12
|
# The primary namespace for ruby-macho.
|
12
13
|
module MachO
|
13
|
-
#
|
14
|
-
|
15
|
-
# @return [MachO::MachOFile] if the file is a Mach-O
|
16
|
-
# @return [MachO::FatFile] if the file is a Fat file
|
17
|
-
def self.open(filename)
|
18
|
-
# open file and test magic instead of using exceptions for control?
|
19
|
-
begin
|
20
|
-
file = MachOFile.new(filename)
|
21
|
-
rescue FatBinaryError
|
22
|
-
file = FatFile.new(filename)
|
23
|
-
end
|
24
|
-
|
25
|
-
file
|
26
|
-
end
|
14
|
+
# release version
|
15
|
+
VERSION = "0.1.8".freeze
|
27
16
|
end
|
data/lib/macho/fat_file.rb
CHANGED
@@ -32,6 +32,64 @@ module MachO
|
|
32
32
|
@raw_data
|
33
33
|
end
|
34
34
|
|
35
|
+
# @return [Boolean] true if the Mach-O is of type `MH_OBJECT`, false otherwise
|
36
|
+
def object?
|
37
|
+
machos.first.object?
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Boolean] true if the Mach-O is of type `MH_EXECUTE`, false otherwise
|
41
|
+
def executable?
|
42
|
+
machos.first.executable?
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [Boolean] true if the Mach-O is of type `MH_FVMLIB`, false otherwise
|
46
|
+
def fvmlib?
|
47
|
+
machos.first.fvmlib?
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Boolean] true if the Mach-O is of type `MH_CORE`, false otherwise
|
51
|
+
def core?
|
52
|
+
machos.first.core?
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Boolean] true if the Mach-O is of type `MH_PRELOAD`, false otherwise
|
56
|
+
def preload?
|
57
|
+
machos.first.preload?
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Boolean] true if the Mach-O is of type `MH_DYLIB`, false otherwise
|
61
|
+
def dylib?
|
62
|
+
machos.first.dylib?
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [Boolean] true if the Mach-O is of type `MH_DYLINKER`, false otherwise
|
66
|
+
def dylinker?
|
67
|
+
machos.first.dylinker?
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Boolean] true if the Mach-O is of type `MH_BUNDLE`, false otherwise
|
71
|
+
def bundle?
|
72
|
+
machos.first.bundle?
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Boolean] true if the Mach-O is of type `MH_DSYM`, false otherwise
|
76
|
+
def dsym?
|
77
|
+
machos.first.dsym?
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [Boolean] true if the Mach-O is of type `MH_KEXT_BUNDLE`, false otherwise
|
81
|
+
def kext?
|
82
|
+
machos.first.kext?
|
83
|
+
end
|
84
|
+
|
85
|
+
def magic
|
86
|
+
header.magic
|
87
|
+
end
|
88
|
+
|
89
|
+
def magic_string
|
90
|
+
MH_MAGICS[magic]
|
91
|
+
end
|
92
|
+
|
35
93
|
# The file's type. Assumed to be the same for every Mach-O within.
|
36
94
|
# @return [String] the filetype
|
37
95
|
def filetype
|
data/lib/macho/load_commands.rb
CHANGED
@@ -3,247 +3,107 @@ module MachO
|
|
3
3
|
# LC_REQ_DYLD to be recognized by the dynamic linder (dyld)
|
4
4
|
LC_REQ_DYLD = 0x80000000
|
5
5
|
|
6
|
-
# segment of this file to be mapped
|
7
|
-
LC_SEGMENT = 0x1
|
8
|
-
|
9
|
-
# link-edit stab symbol table info
|
10
|
-
LC_SYMTAB = 0x2
|
11
|
-
|
12
|
-
# link-edit gdb symbol table info (obsolete)
|
13
|
-
LC_SYMSEG = 0x3
|
14
|
-
|
15
|
-
# thread
|
16
|
-
LC_THREAD = 0x4
|
17
|
-
|
18
|
-
# unix thread (includes a stack)
|
19
|
-
LC_UNIXTHREAD = 0x5
|
20
|
-
|
21
|
-
# load a specified fixed VM shared library
|
22
|
-
LC_LOADFVMLIB = 0x6
|
23
|
-
|
24
|
-
# fixed VM shared library identification
|
25
|
-
LC_IDFVMLIB = 0x7
|
26
|
-
|
27
|
-
# object identification info (obsolete)
|
28
|
-
LC_IDENT = 0x8
|
29
|
-
|
30
|
-
# fixed VM file inclusion (internal use)
|
31
|
-
LC_FVMFILE = 0x9
|
32
|
-
|
33
|
-
# prepage command (internal use)
|
34
|
-
LC_PREPAGE = 0xa
|
35
|
-
|
36
|
-
# dynamic link-edit symbol table info
|
37
|
-
LC_DYSYMTAB = 0xb
|
38
|
-
|
39
|
-
# load a dynamically linked shared library
|
40
|
-
LC_LOAD_DYLIB = 0xc
|
41
|
-
|
42
|
-
# dynamically linked shared lib ident
|
43
|
-
LC_ID_DYLIB = 0xd
|
44
|
-
|
45
|
-
# load a dynamic linker
|
46
|
-
LC_LOAD_DYLINKER = 0xe
|
47
|
-
|
48
|
-
# dynamic linker identification
|
49
|
-
LC_ID_DYLINKER = 0xf
|
50
|
-
|
51
|
-
# modules prebound for a dynamically linked shared library
|
52
|
-
LC_PREBOUND_DYLIB = 0x10
|
53
|
-
|
54
|
-
# image routines
|
55
|
-
LC_ROUTINES = 0x11
|
56
|
-
|
57
|
-
# sub framework
|
58
|
-
LC_SUB_FRAMEWORK = 0x12
|
59
|
-
|
60
|
-
# sub umbrella
|
61
|
-
LC_SUB_UMBRELLA = 0x13
|
62
|
-
|
63
|
-
# sub umbrella
|
64
|
-
LC_SUB_CLIENT = 0x14
|
65
|
-
|
66
|
-
# sub umbrella
|
67
|
-
LC_SUB_LIBRARY = 0x15
|
68
|
-
|
69
|
-
# two-level namespace lookup hints
|
70
|
-
LC_TWOLEVEL_HINTS = 0x16
|
71
|
-
|
72
|
-
# prebind checksum
|
73
|
-
LC_PREBIND_CKSUM = 0x17
|
74
|
-
|
75
|
-
# load a dynamically linked shared library that is allowed to be missing (all symbols are weak imported).
|
76
|
-
LC_LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD)
|
77
|
-
|
78
|
-
# 64-bit segment of this file to be mapped
|
79
|
-
LC_SEGMENT_64 = 0x19
|
80
|
-
|
81
|
-
# 64-bit image routines
|
82
|
-
LC_ROUTINES_64 = 0x1a
|
83
|
-
|
84
|
-
# the uuid
|
85
|
-
LC_UUID = 0x1b
|
86
|
-
|
87
|
-
# runpath additions
|
88
|
-
LC_RPATH = (0x1c | LC_REQ_DYLD)
|
89
|
-
|
90
|
-
# local of code signature
|
91
|
-
LC_CODE_SIGNATURE = 0x1d
|
92
|
-
|
93
|
-
# local of info to split segments
|
94
|
-
LC_SEGMENT_SPLIT_INFO = 0x1e
|
95
|
-
|
96
|
-
# load and re-export dylib
|
97
|
-
LC_REEXPORT_DYLIB = (0x1f | LC_REQ_DYLD)
|
98
|
-
|
99
|
-
# delay load of dylib until first use
|
100
|
-
LC_LAZY_LOAD_DYLIB = 0x20
|
101
|
-
|
102
|
-
# encrypted segment information
|
103
|
-
LC_ENCRYPTION_INFO = 0x21
|
104
|
-
|
105
|
-
# compressed dyld information
|
106
|
-
LC_DYLD_INFO = 0x22
|
107
|
-
|
108
|
-
# compressed dyld information only
|
109
|
-
LC_DYLD_INFO_ONLY = (0x22 | LC_REQ_DYLD)
|
110
|
-
|
111
|
-
# load upward dylib
|
112
|
-
LC_LOAD_UPWARD_DYLIB = (0x23 | LC_REQ_DYLD)
|
113
|
-
|
114
|
-
# build for MacOSX min OS version
|
115
|
-
LC_VERSION_MIN_MACOSX = 0x24
|
116
|
-
|
117
|
-
# build for iPhoneOS min OS version
|
118
|
-
LC_VERSION_MIN_IPHONEOS = 0x25
|
119
|
-
|
120
|
-
# compressed table of function start addresses
|
121
|
-
LC_FUNCTION_STARTS = 0x26
|
122
|
-
|
123
|
-
# string for dyld to treat like environment variable
|
124
|
-
LC_DYLD_ENVIRONMENT = 0x27
|
125
|
-
|
126
|
-
# replacement for LC_UNIXTHREAD
|
127
|
-
LC_MAIN = (0x28 | LC_REQ_DYLD)
|
128
|
-
|
129
|
-
# table of non-instructions in __text
|
130
|
-
LC_DATA_IN_CODE = 0x29
|
131
|
-
|
132
|
-
# source version used to build binary
|
133
|
-
LC_SOURCE_VERSION = 0x2a
|
134
|
-
|
135
|
-
# Code signing DRs copied from linked dylibs
|
136
|
-
LC_DYLIB_CODE_SIGN_DRS = 0x2b
|
137
|
-
|
138
|
-
# 64-bit encrypted segment information
|
139
|
-
LC_ENCRYPTION_INFO_64 = 0x2c
|
140
|
-
|
141
|
-
# linker options in MH_OBJECT files
|
142
|
-
LC_LINKER_OPTION = 0x2d
|
143
|
-
|
144
|
-
# linker options in MH_OBJECT files
|
145
|
-
LC_LINKER_OPTIMIZATION_HINT = 0x2e
|
146
|
-
|
147
6
|
# association of load commands to string representations
|
7
|
+
# @api private
|
148
8
|
LOAD_COMMANDS = {
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
9
|
+
0x1 => :LC_SEGMENT,
|
10
|
+
0x2 => :LC_SYMTAB,
|
11
|
+
0x3 => :LC_SYMSEG,
|
12
|
+
0x4 => :LC_THREAD,
|
13
|
+
0x5 => :LC_UNIXTHREAD,
|
14
|
+
0x6 => :LC_LOADFVMLIB,
|
15
|
+
0x7 => :LC_IDFVMLIB,
|
16
|
+
0x8 => :LC_IDENT,
|
17
|
+
0x9 => :LC_FVMFILE,
|
18
|
+
0xa => :LC_PREPAGE,
|
19
|
+
0xb => :LC_DYSYMTAB,
|
20
|
+
0xc => :LC_LOAD_DYLIB,
|
21
|
+
0xd => :LC_ID_DYLIB,
|
22
|
+
0xe => :LC_LOAD_DYLINKER,
|
23
|
+
0xf => :LC_ID_DYLINKER,
|
24
|
+
0x10 => :LC_PREBOUND_DYLIB,
|
25
|
+
0x11 => :LC_ROUTINES,
|
26
|
+
0x12 => :LC_SUB_FRAMEWORK,
|
27
|
+
0x13 => :LC_SUB_UMBRELLA,
|
28
|
+
0x14 => :LC_SUB_CLIENT,
|
29
|
+
0x15 => :LC_SUB_LIBRARY,
|
30
|
+
0x16 => :LC_TWOLEVEL_HINTS,
|
31
|
+
0x17 => :LC_PREBIND_CKSUM,
|
32
|
+
(0x18 | LC_REQ_DYLD) => :LC_LOAD_WEAK_DYLIB,
|
33
|
+
0x19 => :LC_SEGMENT_64,
|
34
|
+
0x1a => :LC_ROUTINES_64,
|
35
|
+
0x1b => :LC_UUID,
|
36
|
+
(0x1c | LC_REQ_DYLD) => :LC_RPATH,
|
37
|
+
0x1d => :LC_CODE_SIGNATURE,
|
38
|
+
0x1e => :LC_SEGMENT_SPLIT_INFO,
|
39
|
+
(0x1f | LC_REQ_DYLD) => :LC_REEXPORT_DYLIB,
|
40
|
+
0x20 => :LC_LAZY_LOAD_DYLIB,
|
41
|
+
0x21 => :LC_ENCRYPTION_INFO,
|
42
|
+
0x22 => :LC_DYLD_INFO,
|
43
|
+
(0x22 | LC_REQ_DYLD) => :LC_DYLD_INFO_ONLY,
|
44
|
+
(0x23 | LC_REQ_DYLD) => :LC_LOAD_UPWARD_DYLIB,
|
45
|
+
0x24 => :LC_VERSION_MIN_MACOSX,
|
46
|
+
0x25 => :LC_VERSION_MIN_IPHONEOS,
|
47
|
+
0x26 => :LC_FUNCTION_STARTS,
|
48
|
+
0x27 => :LC_DYLD_ENVIRONMENT,
|
49
|
+
(0x28 | LC_REQ_DYLD) => :LC_MAIN,
|
50
|
+
0x29 => :LC_DATA_IN_CODE,
|
51
|
+
0x2a => :LC_SOURCE_VERSION,
|
52
|
+
0x2b => :LC_DYLIB_CODE_SIGN_DRS,
|
53
|
+
0x2c => :LC_ENCRYPTION_INFO_64,
|
54
|
+
0x2d => :LC_LINKER_OPTION,
|
55
|
+
0x2e => :LC_LINKER_OPTIMIZATION_HINT
|
196
56
|
}
|
197
57
|
|
198
58
|
# association of load commands to string representations of class names
|
199
59
|
LC_STRUCTURES = {
|
200
|
-
LC_SEGMENT => "SegmentCommand",
|
201
|
-
LC_SYMTAB => "SymtabCommand",
|
202
|
-
LC_SYMSEG => "LoadCommand", # obsolete
|
203
|
-
LC_THREAD => "ThreadCommand",
|
204
|
-
LC_UNIXTHREAD => "ThreadCommand",
|
205
|
-
LC_LOADFVMLIB => "LoadCommand", # obsolete
|
206
|
-
LC_IDFVMLIB => "LoadCommand", # obsolete
|
207
|
-
LC_IDENT => "LoadCommand", # obsolete
|
208
|
-
LC_FVMFILE => "LoadCommand", # reserved for internal use only
|
209
|
-
LC_PREPAGE => "LoadCommand", # reserved for internal use only
|
210
|
-
LC_DYSYMTAB => "DysymtabCommand",
|
211
|
-
LC_LOAD_DYLIB => "DylibCommand",
|
212
|
-
LC_ID_DYLIB => "DylibCommand",
|
213
|
-
LC_LOAD_DYLINKER => "DylinkerCommand",
|
214
|
-
LC_ID_DYLINKER => "DylinkerCommand",
|
215
|
-
LC_PREBOUND_DYLIB => "PreboundDylibCommand",
|
216
|
-
LC_ROUTINES => "RoutinesCommand",
|
217
|
-
LC_SUB_FRAMEWORK => "SubFrameworkCommand",
|
218
|
-
LC_SUB_UMBRELLA => "SubUmbrellaCommand",
|
219
|
-
LC_SUB_CLIENT => "SubClientCommand",
|
220
|
-
LC_SUB_LIBRARY => "SubLibraryCommand",
|
221
|
-
LC_TWOLEVEL_HINTS => "TwolevelHintsCommand",
|
222
|
-
LC_PREBIND_CKSUM => "PrebindCksumCommand",
|
223
|
-
LC_LOAD_WEAK_DYLIB => "DylibCommand",
|
224
|
-
LC_SEGMENT_64 => "SegmentCommand64",
|
225
|
-
LC_ROUTINES_64 => "RoutinesCommand64",
|
226
|
-
LC_UUID => "UUIDCommand",
|
227
|
-
LC_RPATH => "RpathCommand",
|
228
|
-
LC_CODE_SIGNATURE => "LinkeditDataCommand",
|
229
|
-
LC_SEGMENT_SPLIT_INFO => "LinkeditDataCommand",
|
230
|
-
LC_REEXPORT_DYLIB => "DylibCommand",
|
231
|
-
LC_LAZY_LOAD_DYLIB => "LoadCommand", # undoc, maybe DylibCommand?
|
232
|
-
LC_ENCRYPTION_INFO => "EncryptionInfoCommand",
|
233
|
-
LC_DYLD_INFO => "DyldInfoCommand",
|
234
|
-
LC_DYLD_INFO_ONLY => "DyldInfoCommand",
|
235
|
-
LC_LOAD_UPWARD_DYLIB => "LoadCommand", # undoc, maybe DylibCommand?
|
236
|
-
LC_VERSION_MIN_MACOSX => "VersionMinCommand",
|
237
|
-
LC_VERSION_MIN_IPHONEOS => "VersionMinCommand",
|
238
|
-
LC_FUNCTION_STARTS => "LinkeditDataCommand",
|
239
|
-
LC_DYLD_ENVIRONMENT => "DylinkerCommand",
|
240
|
-
LC_MAIN => "EntryPointCommand",
|
241
|
-
LC_DATA_IN_CODE => "LinkeditDataCommand",
|
242
|
-
LC_SOURCE_VERSION => "SourceVersionCommand",
|
243
|
-
LC_DYLIB_CODE_SIGN_DRS => "LinkeditDataCommand",
|
244
|
-
LC_ENCRYPTION_INFO_64 => "EncryptionInfoCommand64",
|
245
|
-
LC_LINKER_OPTION => "LinkerOptionCommand",
|
246
|
-
LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand"
|
60
|
+
:LC_SEGMENT => "SegmentCommand",
|
61
|
+
:LC_SYMTAB => "SymtabCommand",
|
62
|
+
:LC_SYMSEG => "LoadCommand", # obsolete
|
63
|
+
:LC_THREAD => "ThreadCommand",
|
64
|
+
:LC_UNIXTHREAD => "ThreadCommand",
|
65
|
+
:LC_LOADFVMLIB => "LoadCommand", # obsolete
|
66
|
+
:LC_IDFVMLIB => "LoadCommand", # obsolete
|
67
|
+
:LC_IDENT => "LoadCommand", # obsolete
|
68
|
+
:LC_FVMFILE => "LoadCommand", # reserved for internal use only
|
69
|
+
:LC_PREPAGE => "LoadCommand", # reserved for internal use only
|
70
|
+
:LC_DYSYMTAB => "DysymtabCommand",
|
71
|
+
:LC_LOAD_DYLIB => "DylibCommand",
|
72
|
+
:LC_ID_DYLIB => "DylibCommand",
|
73
|
+
:LC_LOAD_DYLINKER => "DylinkerCommand",
|
74
|
+
:LC_ID_DYLINKER => "DylinkerCommand",
|
75
|
+
:LC_PREBOUND_DYLIB => "PreboundDylibCommand",
|
76
|
+
:LC_ROUTINES => "RoutinesCommand",
|
77
|
+
:LC_SUB_FRAMEWORK => "SubFrameworkCommand",
|
78
|
+
:LC_SUB_UMBRELLA => "SubUmbrellaCommand",
|
79
|
+
:LC_SUB_CLIENT => "SubClientCommand",
|
80
|
+
:LC_SUB_LIBRARY => "SubLibraryCommand",
|
81
|
+
:LC_TWOLEVEL_HINTS => "TwolevelHintsCommand",
|
82
|
+
:LC_PREBIND_CKSUM => "PrebindCksumCommand",
|
83
|
+
:LC_LOAD_WEAK_DYLIB => "DylibCommand",
|
84
|
+
:LC_SEGMENT_64 => "SegmentCommand64",
|
85
|
+
:LC_ROUTINES_64 => "RoutinesCommand64",
|
86
|
+
:LC_UUID => "UUIDCommand",
|
87
|
+
:LC_RPATH => "RpathCommand",
|
88
|
+
:LC_CODE_SIGNATURE => "LinkeditDataCommand",
|
89
|
+
:LC_SEGMENT_SPLIT_INFO => "LinkeditDataCommand",
|
90
|
+
:LC_REEXPORT_DYLIB => "DylibCommand",
|
91
|
+
:LC_LAZY_LOAD_DYLIB => "LoadCommand", # undoc, maybe DylibCommand?
|
92
|
+
:LC_ENCRYPTION_INFO => "EncryptionInfoCommand",
|
93
|
+
:LC_DYLD_INFO => "DyldInfoCommand",
|
94
|
+
:LC_DYLD_INFO_ONLY => "DyldInfoCommand",
|
95
|
+
:LC_LOAD_UPWARD_DYLIB => "LoadCommand", # undoc, maybe DylibCommand?
|
96
|
+
:LC_VERSION_MIN_MACOSX => "VersionMinCommand",
|
97
|
+
:LC_VERSION_MIN_IPHONEOS => "VersionMinCommand",
|
98
|
+
:LC_FUNCTION_STARTS => "LinkeditDataCommand",
|
99
|
+
:LC_DYLD_ENVIRONMENT => "DylinkerCommand",
|
100
|
+
:LC_MAIN => "EntryPointCommand",
|
101
|
+
:LC_DATA_IN_CODE => "LinkeditDataCommand",
|
102
|
+
:LC_SOURCE_VERSION => "SourceVersionCommand",
|
103
|
+
:LC_DYLIB_CODE_SIGN_DRS => "LinkeditDataCommand",
|
104
|
+
:LC_ENCRYPTION_INFO_64 => "EncryptionInfoCommand64",
|
105
|
+
:LC_LINKER_OPTION => "LinkerOptionCommand",
|
106
|
+
:LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand"
|
247
107
|
}
|
248
108
|
|
249
109
|
# pagezero segment name
|
@@ -319,9 +179,16 @@ module MachO
|
|
319
179
|
@cmdsize = cmdsize
|
320
180
|
end
|
321
181
|
|
182
|
+
# @return [Symbol] a symbol representation of the load command's identifying number
|
183
|
+
def type
|
184
|
+
LOAD_COMMANDS[cmd]
|
185
|
+
end
|
186
|
+
|
187
|
+
alias :to_sym :type
|
188
|
+
|
322
189
|
# @return [String] a string representation of the load command's identifying number
|
323
190
|
def to_s
|
324
|
-
|
191
|
+
type.to_s
|
325
192
|
end
|
326
193
|
|
327
194
|
# Represents a Load Command string. A rough analogue to the lc_str
|
@@ -382,7 +249,7 @@ module MachO
|
|
382
249
|
# A load command indicating that part of this file is to be mapped into
|
383
250
|
# the task's address space. Corresponds to LC_SEGMENT.
|
384
251
|
class SegmentCommand < LoadCommand
|
385
|
-
# @return [String] the name of the segment
|
252
|
+
# @return [String] the name of the segment
|
386
253
|
attr_reader :segname
|
387
254
|
|
388
255
|
# @return [Fixnum] the memory address of the segment
|
@@ -416,7 +283,7 @@ module MachO
|
|
416
283
|
def initialize(raw_data, offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
|
417
284
|
filesize, maxprot, initprot, nsects, flags)
|
418
285
|
super(raw_data, offset, cmd, cmdsize)
|
419
|
-
@segname = segname
|
286
|
+
@segname = segname.delete("\x00")
|
420
287
|
@vmaddr = vmaddr
|
421
288
|
@vmsize = vmsize
|
422
289
|
@fileoff = fileoff
|
@@ -426,17 +293,12 @@ module MachO
|
|
426
293
|
@nsects = nsects
|
427
294
|
@flags = flags
|
428
295
|
end
|
429
|
-
|
430
|
-
# @return [String] the segment's name, with any trailing NULL characters removed
|
431
|
-
def segment_name
|
432
|
-
@segname.delete("\x00")
|
433
|
-
end
|
434
296
|
end
|
435
297
|
|
436
298
|
# A load command indicating that part of this file is to be mapped into
|
437
299
|
# the task's address space. Corresponds to LC_SEGMENT_64.
|
438
300
|
class SegmentCommand64 < LoadCommand
|
439
|
-
# @return [String] the name of the segment
|
301
|
+
# @return [String] the name of the segment
|
440
302
|
attr_reader :segname
|
441
303
|
|
442
304
|
# @return [Fixnum] the memory address of the segment
|
@@ -470,7 +332,7 @@ module MachO
|
|
470
332
|
def initialize(raw_data, offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
|
471
333
|
filesize, maxprot, initprot, nsects, flags)
|
472
334
|
super(raw_data, offset, cmd, cmdsize)
|
473
|
-
@segname = segname
|
335
|
+
@segname = segname.delete("\x00")
|
474
336
|
@vmaddr = vmaddr
|
475
337
|
@vmsize = vmsize
|
476
338
|
@fileoff = fileoff
|
@@ -480,11 +342,6 @@ module MachO
|
|
480
342
|
@nsects = nsects
|
481
343
|
@flags = flags
|
482
344
|
end
|
483
|
-
|
484
|
-
# @return [String] the segment's name, with any trailing NULL characters removed
|
485
|
-
def segment_name
|
486
|
-
@segname.delete("\x00")
|
487
|
-
end
|
488
345
|
end
|
489
346
|
|
490
347
|
# A load command representing some aspect of shared libraries, depending
|
data/lib/macho/macho_file.rb
CHANGED
@@ -58,21 +58,56 @@ module MachO
|
|
58
58
|
MachO.magic64?(header.magic)
|
59
59
|
end
|
60
60
|
|
61
|
+
# @return [Boolean] true if the Mach-O is of type `MH_OBJECT`, false otherwise
|
62
|
+
def object?
|
63
|
+
header.filetype == MH_OBJECT
|
64
|
+
end
|
65
|
+
|
61
66
|
# @return [Boolean] true if the Mach-O is of type `MH_EXECUTE`, false otherwise
|
62
67
|
def executable?
|
63
68
|
header.filetype == MH_EXECUTE
|
64
69
|
end
|
65
70
|
|
71
|
+
# @return [Boolean] true if the Mach-O is of type `MH_FVMLIB`, false otherwise
|
72
|
+
def fvmlib?
|
73
|
+
header.filetype == MH_FVMLIB
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [Boolean] true if the Mach-O is of type `MH_CORE`, false otherwise
|
77
|
+
def core?
|
78
|
+
header.filetype == MH_CORE
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [Boolean] true if the Mach-O is of type `MH_PRELOAD`, false otherwise
|
82
|
+
def preload?
|
83
|
+
header.filetype == MH_PRELOAD
|
84
|
+
end
|
85
|
+
|
66
86
|
# @return [Boolean] true if the Mach-O is of type `MH_DYLIB`, false otherwise
|
67
87
|
def dylib?
|
68
88
|
header.filetype == MH_DYLIB
|
69
89
|
end
|
70
90
|
|
91
|
+
# @return [Boolean] true if the Mach-O is of type `MH_DYLINKER`, false otherwise
|
92
|
+
def dylinker?
|
93
|
+
header.filetype == MH_DYLINKER
|
94
|
+
end
|
95
|
+
|
71
96
|
# @return [Boolean] true if the Mach-O is of type `MH_BUNDLE`, false otherwise
|
72
97
|
def bundle?
|
73
98
|
header.filetype == MH_BUNDLE
|
74
99
|
end
|
75
100
|
|
101
|
+
# @return [Boolean] true if the Mach-O is of type `MH_DSYM`, false otherwise
|
102
|
+
def dsym?
|
103
|
+
header.filetype == MH_DSYM
|
104
|
+
end
|
105
|
+
|
106
|
+
# @return [Boolean] true if the Mach-O is of type `MH_KEXT_BUNDLE`, false otherwise
|
107
|
+
def kext?
|
108
|
+
header.filetype == MH_KEXT_BUNDLE
|
109
|
+
end
|
110
|
+
|
76
111
|
# @return [Fixnum] the Mach-O's magic number
|
77
112
|
def magic
|
78
113
|
header.magic
|
@@ -80,7 +115,7 @@ module MachO
|
|
80
115
|
|
81
116
|
# @return [String] a string representation of the Mach-O's magic number
|
82
117
|
def magic_string
|
83
|
-
MH_MAGICS[
|
118
|
+
MH_MAGICS[magic]
|
84
119
|
end
|
85
120
|
|
86
121
|
# @return [String] a string representation of the Mach-O's filetype
|
@@ -116,10 +151,11 @@ module MachO
|
|
116
151
|
# All load commands of a given name.
|
117
152
|
# @example
|
118
153
|
# file.command("LC_LOAD_DYLIB")
|
119
|
-
# file[
|
154
|
+
# file[:LC_LOAD_DYLIB]
|
155
|
+
# @param [String, Symbol] name the load command ID
|
120
156
|
# @return [Array<MachO::LoadCommand>] an array of LoadCommands corresponding to `name`
|
121
157
|
def command(name)
|
122
|
-
load_commands.select { |lc| lc.
|
158
|
+
load_commands.select { |lc| lc.type == name.to_sym }
|
123
159
|
end
|
124
160
|
|
125
161
|
alias :[] :command
|
@@ -129,9 +165,9 @@ module MachO
|
|
129
165
|
# @return [Array<MachO::SegmentCommand64>] if the Mach-O is 64-bit
|
130
166
|
def segments
|
131
167
|
if magic32?
|
132
|
-
command(
|
168
|
+
command(:LC_SEGMENT)
|
133
169
|
else
|
134
|
-
command(
|
170
|
+
command(:LC_SEGMENT_64)
|
135
171
|
end
|
136
172
|
end
|
137
173
|
|
@@ -144,7 +180,7 @@ module MachO
|
|
144
180
|
return nil
|
145
181
|
end
|
146
182
|
|
147
|
-
dylib_id_cmd = command(
|
183
|
+
dylib_id_cmd = command(:LC_ID_DYLIB).first
|
148
184
|
|
149
185
|
dylib_id_cmd.name.to_s
|
150
186
|
end
|
@@ -164,7 +200,7 @@ module MachO
|
|
164
200
|
return nil
|
165
201
|
end
|
166
202
|
|
167
|
-
dylib_cmd = command(
|
203
|
+
dylib_cmd = command(:LC_ID_DYLIB).first
|
168
204
|
old_id = dylib_id
|
169
205
|
|
170
206
|
set_name_in_dylib(dylib_cmd, old_id, new_id)
|
@@ -173,7 +209,7 @@ module MachO
|
|
173
209
|
# All shared libraries linked to the Mach-O.
|
174
210
|
# @return [Array<String>] an array of all shared libraries
|
175
211
|
def linked_dylibs
|
176
|
-
command(
|
212
|
+
command(:LC_LOAD_DYLIB).map(&:name).map(&:to_s)
|
177
213
|
end
|
178
214
|
|
179
215
|
# Changes the shared library `old_name` to `new_name`
|
@@ -184,7 +220,7 @@ module MachO
|
|
184
220
|
# @return [void]
|
185
221
|
# @raise [MachO::DylibUnknownError] if no shared library has the old name
|
186
222
|
def change_install_name(old_name, new_name)
|
187
|
-
dylib_cmd = command(
|
223
|
+
dylib_cmd = command(:LC_LOAD_DYLIB).find { |d| d.name.to_s == old_name }
|
188
224
|
raise DylibUnknownError.new(old_name) if dylib_cmd.nil?
|
189
225
|
|
190
226
|
set_name_in_dylib(dylib_cmd, old_name, new_name)
|
@@ -256,7 +292,7 @@ module MachO
|
|
256
292
|
ncmds = get_ncmds
|
257
293
|
sizeofcmds = get_sizeofcmds
|
258
294
|
flags = get_flags
|
259
|
-
|
295
|
+
|
260
296
|
if MachO.magic32?(magic)
|
261
297
|
MachHeader.new(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags)
|
262
298
|
else
|
@@ -347,12 +383,13 @@ module MachO
|
|
347
383
|
|
348
384
|
header.ncmds.times do
|
349
385
|
cmd = @raw_data.slice(offset, 4).unpack("V").first
|
386
|
+
cmd_sym = LOAD_COMMANDS[cmd]
|
350
387
|
|
351
|
-
raise LoadCommandError.new(cmd)
|
388
|
+
raise LoadCommandError.new(cmd) if cmd_sym.nil?
|
352
389
|
|
353
390
|
# why do I do this? i don't like declaring constants below
|
354
391
|
# classes, and i need them to resolve...
|
355
|
-
klass = MachO.const_get "#{LC_STRUCTURES[
|
392
|
+
klass = MachO.const_get "#{LC_STRUCTURES[cmd_sym]}"
|
356
393
|
command = klass.new_from_bin(@raw_data, offset, @raw_data.slice(offset, klass.bytesize))
|
357
394
|
|
358
395
|
load_commands << command
|
data/lib/macho/open.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module MachO
|
2
|
+
# Opens the given filename as a MachOFile or FatFile, depending on its magic.
|
3
|
+
# @param filename [String] the file being opened
|
4
|
+
# @return [MachO::MachOFile] if the file is a Mach-O
|
5
|
+
# @return [MachO::FatFile] if the file is a Fat file
|
6
|
+
def self.open(filename)
|
7
|
+
# open file and test magic instead of using exceptions for control?
|
8
|
+
begin
|
9
|
+
file = MachOFile.new(filename)
|
10
|
+
rescue FatBinaryError
|
11
|
+
file = FatFile.new(filename)
|
12
|
+
end
|
13
|
+
|
14
|
+
file
|
15
|
+
end
|
16
|
+
end
|
data/lib/macho/sections.rb
CHANGED
@@ -1,44 +1,110 @@
|
|
1
1
|
module MachO
|
2
|
-
#
|
3
|
-
SECTION_TYPE = 0x000000ff
|
4
|
-
SECTION_ATTRIBUTES = 0xffffff00 # attributes mask
|
5
|
-
SECTION_ATTRIBUTES_USR = 0xff000000 # user settable attributes mask
|
6
|
-
SECTION_ATTRIBUTES_SYS = 0x00ffff00 # system settable attributes mask
|
2
|
+
# type mask
|
3
|
+
SECTION_TYPE = 0x000000ff
|
7
4
|
|
8
|
-
#
|
5
|
+
# attributes mask
|
6
|
+
SECTION_ATTRIBUTES = 0xffffff00
|
7
|
+
|
8
|
+
# user settable attributes mask
|
9
|
+
SECTION_ATTRIBUTES_USR = 0xff000000
|
10
|
+
|
11
|
+
# system settable attributes mask
|
12
|
+
SECTION_ATTRIBUTES_SYS = 0x00ffff00
|
13
|
+
|
14
|
+
# a regular section
|
9
15
|
S_REGULAR = 0x0
|
16
|
+
|
17
|
+
# a zero fill on demand section
|
10
18
|
S_ZEROFILL = 0x1
|
19
|
+
|
20
|
+
# a section with only literal C strings
|
11
21
|
S_CSTRING_LITERALS = 0x2
|
22
|
+
|
23
|
+
# a section with only 4 byte literals
|
12
24
|
S_4BYTE_LITERALS = 0x3
|
25
|
+
|
26
|
+
# a section with only 8 byte literals
|
13
27
|
S_8BYTE_LITERALS = 0x4
|
28
|
+
|
29
|
+
# a section with only pointers to literals
|
14
30
|
S_LITERAL_POINTERS = 0x5
|
31
|
+
|
32
|
+
# a section with only non-lazy symbol pointers
|
15
33
|
S_NON_LAZY_SYMBOL_POINTERS = 0x6
|
34
|
+
|
35
|
+
# a section with only lazy symbol pointers
|
16
36
|
S_LAZY_SYMBOL_POINTERS = 0x7
|
37
|
+
|
38
|
+
# a section with only symbol stubs (byte size of stub in reserved2 field)
|
17
39
|
S_SYMBOL_STUBS = 0x8
|
40
|
+
|
41
|
+
# a section with only function pointers for initialization
|
18
42
|
S_MOD_INIT_FUNC_POINTERS = 0x9
|
43
|
+
|
44
|
+
# a section with only function pointers for termination
|
19
45
|
S_MOD_TERM_FUNC_POINTERS = 0xa
|
46
|
+
|
47
|
+
# a section with only symbols that are to be coalesced
|
20
48
|
S_COALESCED = 0xb
|
49
|
+
|
50
|
+
# a zero fill on demand section that can be larger than 4GB
|
21
51
|
S_GB_ZEROFILE = 0xc
|
52
|
+
|
53
|
+
# a section with only pairs of function pointers for interposing
|
22
54
|
S_INTERPOSING = 0xd
|
55
|
+
|
56
|
+
# a section with only 16 byte literals
|
23
57
|
S_16BYTE_LITERALS = 0xe
|
58
|
+
|
59
|
+
# a section containing DTrace Object Format
|
24
60
|
S_DTRACE_DOF = 0xf
|
61
|
+
|
62
|
+
# a section with only lazy symbol pointers to lazy loaded dylibs
|
25
63
|
S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10
|
64
|
+
|
65
|
+
# a template of initial values for thread local variables
|
26
66
|
S_THREAD_LOCAL_REGULAR = 0x11
|
67
|
+
|
68
|
+
# a template of initial values for thread local variables
|
27
69
|
S_THREAD_LOCAL_ZEROFILL = 0x12
|
70
|
+
|
71
|
+
# thread local variable descriptors
|
28
72
|
S_THREAD_LOCAL_VARIABLES = 0x13
|
73
|
+
|
74
|
+
# pointers to thread local variable descriptors
|
29
75
|
S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14
|
76
|
+
|
77
|
+
# functions to call to initialize thread local variable values
|
30
78
|
S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15
|
31
79
|
|
32
|
-
# section
|
80
|
+
# a section with only true machine instructions
|
33
81
|
S_ATTR_PURE_INSTRUCTIONS = 0x80000000
|
82
|
+
|
83
|
+
# a section with coalesced symbols that are not to be in a ranlib table of contents
|
34
84
|
S_ATTR_NO_TOC = 0x40000000
|
85
|
+
|
86
|
+
# static symbols in this section can be stripped in files with the MH_DYLDLINK flag
|
35
87
|
S_ATTR_STRIP_STATIC_SYMS = 0x20000000
|
88
|
+
|
89
|
+
# no dead stripping
|
36
90
|
S_ATTR_NO_DEAD_STRIP = 0x10000000
|
91
|
+
|
92
|
+
# blocks are live if they reference live blocks
|
37
93
|
S_ATTR_LIVE_SUPPORT = 0x08000000
|
94
|
+
|
95
|
+
# used with i386 code stubs written on by dyld
|
38
96
|
S_ATTR_SELF_MODIFYING_CODE = 0x04000000
|
97
|
+
|
98
|
+
# a debug section
|
39
99
|
S_ATTR_DEBUG = 0x02000000
|
100
|
+
|
101
|
+
# a section containing some machine instructions
|
40
102
|
S_ATTR_SOME_INSTRUCTIONS = 0x00000400
|
103
|
+
|
104
|
+
# a section containing external relocation entries
|
41
105
|
S_ATTR_EXT_RELOC = 0x00000200
|
106
|
+
|
107
|
+
# a section containing local relocation entries
|
42
108
|
S_ATTR_LOC_RELOC = 0x00000100
|
43
109
|
|
44
110
|
# currently known section names
|
data/lib/macho/tools.rb
CHANGED
@@ -13,6 +13,7 @@ module MachO
|
|
13
13
|
# @param filename [String] the Mach-O or Fat binary being modified
|
14
14
|
# @param new_id [String] the new dylib ID for the binary
|
15
15
|
# @return [void]
|
16
|
+
# @todo unstub for fat files
|
16
17
|
def self.change_dylib_id(filename, new_id)
|
17
18
|
file = MachO.open(filename)
|
18
19
|
|
@@ -29,6 +30,7 @@ module MachO
|
|
29
30
|
# @param old_name [String] the old shared library name
|
30
31
|
# @param new_name [String] the new shared library name
|
31
32
|
# @return [void]
|
33
|
+
# @todo unstub for fat files
|
32
34
|
def self.change_install_name(filename, old_name, new_name)
|
33
35
|
file = MachO.open(filename)
|
34
36
|
|
@@ -38,5 +40,33 @@ module MachO
|
|
38
40
|
raise MachOError.new("changing install names for fat binaries is incomplete")
|
39
41
|
end
|
40
42
|
end
|
43
|
+
|
44
|
+
# Changes a runtime path in a Mach-O or Fat binary, overwriting the source file.
|
45
|
+
# @param filename [String] the Mach-O or Fat binary being modified
|
46
|
+
# @param old_path [String] the old runtime path
|
47
|
+
# @param new_path [String] the new runtime path
|
48
|
+
# @return [void]
|
49
|
+
# @todo unstub
|
50
|
+
def self.change_rpath(filename, old_path, new_path)
|
51
|
+
raise "stub"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Add a runtime path to a Mach-O or Fat binary, overwriting the source file.
|
55
|
+
# @param filename [String] the Mach-O or Fat binary being modified
|
56
|
+
# @param new_path [String] the new runtime path
|
57
|
+
# @return [void]
|
58
|
+
# @todo unstub
|
59
|
+
def self.add_rpath(filename, new_path)
|
60
|
+
raise "stub"
|
61
|
+
end
|
62
|
+
|
63
|
+
# Delete a runtime path from a Mach-O or Fat binary, overwriting the source file.
|
64
|
+
# @param filename [String] the Mach-O or Fat binary being modified
|
65
|
+
# @param old_path [String] the old runtime path
|
66
|
+
# @return [void]
|
67
|
+
# @todo unstub
|
68
|
+
def self.delete_rpath(filename, old_path)
|
69
|
+
raise "stub"
|
70
|
+
end
|
41
71
|
end
|
42
72
|
end
|
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: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Woodruff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-04 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@tuffbizz.com
|
@@ -25,6 +25,7 @@ files:
|
|
25
25
|
- lib/macho/headers.rb
|
26
26
|
- lib/macho/load_commands.rb
|
27
27
|
- lib/macho/macho_file.rb
|
28
|
+
- lib/macho/open.rb
|
28
29
|
- lib/macho/sections.rb
|
29
30
|
- lib/macho/structure.rb
|
30
31
|
- lib/macho/tools.rb
|