ruby-macho 0.1.1 → 0.1.2
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/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
|