ruby-macho 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/macho/macho_file.rb +81 -118
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 634d3249001bb3d3bf5782055392c8feea3d15c8
|
4
|
+
data.tar.gz: bd854ada089451f23d4b253642bbb3eebcbba25f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06436af8d8c711a2eaa40f396020a80e15ff8f8de474e162f7f3e41d7b1a984d1218bec862d54f18bb9fe20675908ea8dfe1bcdd08b3d4bd50c8d0405daf06a5
|
7
|
+
data.tar.gz: cc4846d66dc58873417d1baae77c95c7ee4678f5861e98211cb52c4a6363280490473261de8b0143080a7aae71b97e20c0d85b6e0dac5647f106918a3de68c85
|
data/lib/macho/macho_file.rb
CHANGED
@@ -158,8 +158,8 @@ module MachO
|
|
158
158
|
# Changes the Mach-O's dylib ID to `new_id`. Does nothing if not a dylib.
|
159
159
|
# @example
|
160
160
|
# file.dylib_id = "libFoo.dylib"
|
161
|
+
# @param new_id [String] the dylib's new ID
|
161
162
|
# @return [void]
|
162
|
-
# @todo refactor
|
163
163
|
def dylib_id=(new_id)
|
164
164
|
if !new_id.is_a?(String)
|
165
165
|
raise ArgumentError.new("argument must be a String")
|
@@ -169,70 +169,10 @@ module MachO
|
|
169
169
|
return nil
|
170
170
|
end
|
171
171
|
|
172
|
-
|
173
|
-
cmd_round = 4
|
174
|
-
else
|
175
|
-
cmd_round = 8
|
176
|
-
end
|
177
|
-
|
178
|
-
new_sizeofcmds = header[:sizeofcmds]
|
179
|
-
dylib_id_cmd = command('LC_ID_DYLIB').first
|
172
|
+
dylib_cmd = command('LC_ID_DYLIB').first
|
180
173
|
old_id = dylib_id
|
181
|
-
new_id = new_id.dup
|
182
|
-
|
183
|
-
new_pad = MachO.round(new_id.size, cmd_round) - new_id.size
|
184
|
-
old_pad = MachO.round(old_id.size, cmd_round) - old_id.size
|
185
|
-
|
186
|
-
# pad the old and new IDs with null bytes to meet command bounds
|
187
|
-
old_id << "\x00" * old_pad
|
188
|
-
new_id << "\x00" * new_pad
|
189
|
-
|
190
|
-
# calculate the new size of the DylibCommand and sizeofcmds in MH
|
191
|
-
new_size = DylibCommand.bytesize + new_id.size
|
192
|
-
new_sizeofcmds += new_size - dylib_id_cmd.cmdsize
|
193
|
-
|
194
|
-
# calculate the low file offset (offset to first section data)
|
195
|
-
low_fileoff = 2**64 # ULLONGMAX
|
196
|
-
|
197
|
-
segments.each do |seg|
|
198
|
-
sections(seg).each do |sect|
|
199
|
-
if sect.size != 0 && !sect.flag?(S_ZEROFILL) &&
|
200
|
-
!sect.flag?(S_THREAD_LOCAL_ZEROFILL) &&
|
201
|
-
sect.offset < low_fileoff
|
202
|
-
|
203
|
-
low_fileoff = sect.offset
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
if new_sizeofcmds + header.bytesize > low_fileoff
|
209
|
-
raise HeaderPadError.new(@filename)
|
210
|
-
end
|
211
|
-
|
212
|
-
# update sizeofcmds in mach_header
|
213
|
-
set_sizeofcmds(new_sizeofcmds)
|
214
|
-
|
215
|
-
# update cmdsize in the dylib_command
|
216
|
-
@raw_data[dylib_id_cmd.offset + 4, 4] = [new_size].pack("V")
|
217
|
-
|
218
|
-
# delete the old id
|
219
|
-
@raw_data.slice!(dylib_id_cmd.offset + dylib_id_cmd.name...dylib_id_cmd.offset + dylib_id_cmd.class.bytesize + old_id.size)
|
220
174
|
|
221
|
-
|
222
|
-
@raw_data.insert(dylib_id_cmd.offset + dylib_id_cmd.name, new_id)
|
223
|
-
|
224
|
-
# pad/unpad after new_sizeofcmds until offsets are corrected
|
225
|
-
null_pad = old_id.size - new_id.size
|
226
|
-
|
227
|
-
if null_pad < 0
|
228
|
-
@raw_data.slice!(new_sizeofcmds + header.bytesize, null_pad.abs)
|
229
|
-
else
|
230
|
-
@raw_data.insert(new_sizeofcmds + header.bytesize, "\x00" * null_pad)
|
231
|
-
end
|
232
|
-
|
233
|
-
# synchronize fields with the raw data
|
234
|
-
header = get_mach_header
|
235
|
-
load_commands = get_load_commands
|
175
|
+
set_name_in_dylib(dylib_cmd, old_id, new_id)
|
236
176
|
end
|
237
177
|
|
238
178
|
# All shared libraries linked to the Mach-O.
|
@@ -254,8 +194,12 @@ module MachO
|
|
254
194
|
dylibs
|
255
195
|
end
|
256
196
|
|
197
|
+
# Changes the shared library `old_name` to `new_name`
|
198
|
+
# @example
|
199
|
+
# file.change_install_name("/usr/lib/libWhatever.dylib", "/usr/local/lib/libWhatever2.dylib")
|
200
|
+
# @param old_name [String] the shared library's old name
|
201
|
+
# @param new_name [String] the shared library's new name
|
257
202
|
# @return [void]
|
258
|
-
# @todo refactor
|
259
203
|
def change_install_name(old_name, new_name)
|
260
204
|
idx = linked_dylibs.index(old_name)
|
261
205
|
raise DylibUnknownError.new(old_name) if idx.nil?
|
@@ -265,60 +209,7 @@ module MachO
|
|
265
209
|
# their indices interchangeably to avoid having to loop.
|
266
210
|
dylib_cmd = command('LC_LOAD_DYLIB')[idx]
|
267
211
|
|
268
|
-
|
269
|
-
cmd_round = 4
|
270
|
-
else
|
271
|
-
cmd_round = 8
|
272
|
-
end
|
273
|
-
|
274
|
-
new_sizeofcmds = header[:sizeofcmds]
|
275
|
-
old_install_name = old_name.dup
|
276
|
-
new_install_name = new_name.dup
|
277
|
-
|
278
|
-
old_pad = MachO.round(old_install_name.size, cmd_round) - old_install_name.size
|
279
|
-
new_pad = MachO.round(new_install_name.size, cmd_round) - new_install_name.size
|
280
|
-
|
281
|
-
old_install_name << "\x00" * old_pad
|
282
|
-
new_install_name << "\x00" * new_pad
|
283
|
-
|
284
|
-
new_size = DylibCommand.bytesize + new_install_name.size
|
285
|
-
new_sizeofcmds += new_size - dylib_cmd.cmdsize
|
286
|
-
|
287
|
-
low_fileoff = 2**64
|
288
|
-
|
289
|
-
segments.each do |seg|
|
290
|
-
sections(seg).each do |sect|
|
291
|
-
if sect.size != 0 && !sect.flag?(S_ZEROFILL) &&
|
292
|
-
!sect.flag?(S_THREAD_LOCAL_ZEROFILL) &&
|
293
|
-
sect.offset < low_fileoff
|
294
|
-
|
295
|
-
low_fileoff = sect.offset
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
if new_sizeofcmds + header.bytesize > low_fileoff
|
301
|
-
raise HeaderPadError.new(@filename)
|
302
|
-
end
|
303
|
-
|
304
|
-
set_sizeofcmds(new_sizeofcmds)
|
305
|
-
|
306
|
-
@raw_data[dylib_cmd.offset + 4, 4] = [new_size].pack("V")
|
307
|
-
|
308
|
-
@raw_data.slice!(dylib_cmd.offset + dylib_cmd.name...dylib_cmd.offset + dylib_cmd.class.bytesize + old_install_name.size)
|
309
|
-
|
310
|
-
@raw_data.insert(dylib_cmd.offset + dylib_cmd.name, new_install_name)
|
311
|
-
|
312
|
-
null_pad = old_install_name.size - new_install_name.size
|
313
|
-
|
314
|
-
if null_pad < 0
|
315
|
-
@raw_data.slice!(new_sizeofcmds + header.bytesize, null_pad.abs)
|
316
|
-
else
|
317
|
-
@raw_data.insert(new_sizeofcmds + header.bytesize, "\x00" * null_pad)
|
318
|
-
end
|
319
|
-
|
320
|
-
header = get_mach_header
|
321
|
-
load_commands = get_load_commands
|
212
|
+
set_name_in_dylib(dylib_cmd, old_name, new_name)
|
322
213
|
end
|
323
214
|
|
324
215
|
alias :change_dylib :change_install_name
|
@@ -520,5 +411,77 @@ module MachO
|
|
520
411
|
new_size = [size].pack("V")
|
521
412
|
@raw_data[20..23] = new_size
|
522
413
|
end
|
414
|
+
|
415
|
+
# Updates the `name` field in a DylibCommand, regardless of load command type
|
416
|
+
# @param dylib_cmd [MachO::DylibCommand] the dylib command
|
417
|
+
# @param old_name [String] the old dylib name
|
418
|
+
# @param new_name [String] the new dylib name
|
419
|
+
# @return [void]
|
420
|
+
# @private
|
421
|
+
def set_name_in_dylib(dylib_cmd, old_name, new_name)
|
422
|
+
if magic32?
|
423
|
+
cmd_round = 4
|
424
|
+
else
|
425
|
+
cmd_round = 8
|
426
|
+
end
|
427
|
+
|
428
|
+
new_sizeofcmds = header[:sizeofcmds]
|
429
|
+
old_name = old_name.dup
|
430
|
+
new_name = new_name.dup
|
431
|
+
|
432
|
+
old_pad = MachO.round(old_name.size, cmd_round) - old_name.size
|
433
|
+
new_pad = MachO.round(new_name.size, cmd_round) - new_name.size
|
434
|
+
|
435
|
+
# pad the old and new IDs with null bytes to meet command bounds
|
436
|
+
old_name << "\x00" * old_pad
|
437
|
+
new_name << "\x00" * new_pad
|
438
|
+
|
439
|
+
# calculate the new size of the DylibCommand and sizeofcmds in MH
|
440
|
+
new_size = DylibCommand.bytesize + new_name.size
|
441
|
+
new_sizeofcmds += new_size - dylib_cmd.cmdsize
|
442
|
+
|
443
|
+
low_fileoff = 2**64 # ULLONGMAX
|
444
|
+
|
445
|
+
# calculate the low file offset (offset to first section data)
|
446
|
+
segments.each do |seg|
|
447
|
+
sections(seg).each do |sect|
|
448
|
+
if sect.size != 0 && !sect.flag?(S_ZEROFILL) &&
|
449
|
+
!sect.flag?(S_THREAD_LOCAL_ZEROFILL) &&
|
450
|
+
sect.offset < low_fileoff
|
451
|
+
|
452
|
+
low_fileoff = sect.offset
|
453
|
+
end
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
if new_sizeofcmds + header.bytesize > low_fileoff
|
458
|
+
raise HeaderPadError.new(@filename)
|
459
|
+
end
|
460
|
+
|
461
|
+
# update sizeofcmds in mach_header
|
462
|
+
set_sizeofcmds(new_sizeofcmds)
|
463
|
+
|
464
|
+
# update cmdsize in the dylib_command
|
465
|
+
@raw_data[dylib_cmd.offset + 4, 4] = [new_size].pack("V")
|
466
|
+
|
467
|
+
# delete the old name
|
468
|
+
@raw_data.slice!(dylib_cmd.offset + dylib_cmd.name...dylib_cmd.offset + dylib_cmd.class.bytesize + old_name.size)
|
469
|
+
|
470
|
+
# insert the new id
|
471
|
+
@raw_data.insert(dylib_cmd.offset + dylib_cmd.name, new_name)
|
472
|
+
|
473
|
+
# pad/unpad after new_sizeofcmds until offsets are corrected
|
474
|
+
null_pad = old_name.size - new_name.size
|
475
|
+
|
476
|
+
if null_pad < 0
|
477
|
+
@raw_data.slice!(new_sizeofcmds + header.bytesize, null_pad.abs)
|
478
|
+
else
|
479
|
+
@raw_data.insert(new_sizeofcmds + header.bytesize, "\x00" * null_pad)
|
480
|
+
end
|
481
|
+
|
482
|
+
# synchronize fields with the raw data
|
483
|
+
@header = get_mach_header
|
484
|
+
@load_commands = get_load_commands
|
485
|
+
end
|
523
486
|
end
|
524
487
|
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.2
|
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-10-
|
11
|
+
date: 2015-10-25 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
|