ruby-macho 0.1.9 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/macho/exceptions.rb +8 -0
- data/lib/macho/macho_file.rb +59 -18
- data/lib/macho/tools.rb +4 -11
- data/lib/macho.rb +1 -1
- 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: 513849997d23e143113243138d5924dc483a2a0b
|
4
|
+
data.tar.gz: 2e2d1256e5b42be47cdcb81c8981e35021c5fe6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e1bb350afe1cbbbfff4a50197886c4c7c6f4675f0de8e5480deafce7ee4986febd3b7d59c067753cea95ed4dc4a92b8e38d8c486344e3c7b2937bcaff22b800
|
7
|
+
data.tar.gz: dba7611dadf4672c0929bc5f3c8f70c60051b01c278cb0383209304526a780008a2b19c0e50848a42d962b78c43c11174dd7c0913f123bff88b8392c30acc9fe
|
data/lib/macho/exceptions.rb
CHANGED
@@ -74,4 +74,12 @@ module MachO
|
|
74
74
|
super "No such dylib name: #{dylib}"
|
75
75
|
end
|
76
76
|
end
|
77
|
+
|
78
|
+
# Raised when attempting to change an rpath that doesn't exist.
|
79
|
+
class RpathUnknownError < MachOError
|
80
|
+
# @param path [String] the unknown runtime path
|
81
|
+
def initialize(path)
|
82
|
+
super "No such runtime path: #{path}"
|
83
|
+
end
|
84
|
+
end
|
77
85
|
end
|
data/lib/macho/macho_file.rb
CHANGED
@@ -228,6 +228,27 @@ module MachO
|
|
228
228
|
|
229
229
|
alias :change_dylib :change_install_name
|
230
230
|
|
231
|
+
# All runtime paths searched by the dynamic linker for the Mach-O.
|
232
|
+
# @return [Array<String>] an array of all runtime paths
|
233
|
+
def rpaths
|
234
|
+
command(:LC_RPATH).map(&:path).map(&:to_s)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Changes the runtime path `old_path` to `new_path`
|
238
|
+
# @example
|
239
|
+
# file.change_rpath("/usr/lib", "/usr/local/lib")
|
240
|
+
# @param old_path [String] the old runtime path
|
241
|
+
# @param new_path [String] the new runtime path
|
242
|
+
# @return [void]
|
243
|
+
# @raise [MachO::RpathUnknownError] if no such old runtime path exists
|
244
|
+
# @api private
|
245
|
+
def change_rpath(old_path, new_path)
|
246
|
+
rpath_cmd = command(:LC_RPATH).find { |r| r.path.to_s == old_path }
|
247
|
+
raise RpathUnknownError.new(old_path) if rpath_cmd.nil?
|
248
|
+
|
249
|
+
set_path_in_rpath(rpath_cmd, old_path, new_path)
|
250
|
+
end
|
251
|
+
|
231
252
|
# All sections of the segment `segment`.
|
232
253
|
# @param segment [MachO::SegmentCommand, MachO::SegmentCommand64] the segment being inspected
|
233
254
|
# @return [Array<MachO::Section>] if the Mach-O is 32-bit
|
@@ -408,14 +429,34 @@ module MachO
|
|
408
429
|
@raw_data[20..23] = new_size
|
409
430
|
end
|
410
431
|
|
411
|
-
# Updates the `name` field in a DylibCommand
|
432
|
+
# Updates the `name` field in a DylibCommand.
|
412
433
|
# @param dylib_cmd [MachO::DylibCommand] the dylib command
|
413
434
|
# @param old_name [String] the old dylib name
|
414
435
|
# @param new_name [String] the new dylib name
|
415
436
|
# @return [void]
|
416
|
-
# @raise [MachO::HeaderPadError] if the new name exceeds the header pad buffer
|
417
437
|
# @private
|
418
438
|
def set_name_in_dylib(dylib_cmd, old_name, new_name)
|
439
|
+
set_lc_str_in_cmd(dylib_cmd, dylib_cmd.name, old_name, new_name)
|
440
|
+
end
|
441
|
+
|
442
|
+
# Updates the `path` field in an RpathCommand.
|
443
|
+
# @param rpath_cmd [MachO::RpathCommand] the rpath command
|
444
|
+
# @param old_path [String] the old runtime name
|
445
|
+
# @param new_path [String] the new runtime name
|
446
|
+
# @return [void]
|
447
|
+
# @private
|
448
|
+
def set_path_in_rpath(rpath_cmd, old_path, new_path)
|
449
|
+
set_lc_str_in_cmd(rpath_cmd, rpath_cmd.path, old_path, new_path)
|
450
|
+
end
|
451
|
+
|
452
|
+
# Updates a generic LCStr field in any LoadCommand.
|
453
|
+
# @param cmd [MachO::LoadCommand] the load command
|
454
|
+
# @param lc_str [MachO::LoadCommand::LCStr] the load command string
|
455
|
+
# @param old_str [String] the old string
|
456
|
+
# @param new_str [String] the new string
|
457
|
+
# @raise [MachO::HeaderPadError] if the new name exceeds the header pad buffer
|
458
|
+
# @private
|
459
|
+
def set_lc_str_in_cmd(cmd, lc_str, old_str, new_str)
|
419
460
|
if magic32?
|
420
461
|
cmd_round = 4
|
421
462
|
else
|
@@ -423,19 +464,19 @@ module MachO
|
|
423
464
|
end
|
424
465
|
|
425
466
|
new_sizeofcmds = header.sizeofcmds
|
426
|
-
|
427
|
-
|
467
|
+
old_str = old_str.dup
|
468
|
+
new_str = new_str.dup
|
428
469
|
|
429
|
-
old_pad = MachO.round(
|
430
|
-
new_pad = MachO.round(
|
470
|
+
old_pad = MachO.round(old_str.size + 1, cmd_round) - old_str.size
|
471
|
+
new_pad = MachO.round(new_str.size + 1, cmd_round) - new_str.size
|
431
472
|
|
432
473
|
# pad the old and new IDs with null bytes to meet command bounds
|
433
|
-
|
434
|
-
|
474
|
+
old_str << "\x00" * old_pad
|
475
|
+
new_str << "\x00" * new_pad
|
435
476
|
|
436
|
-
# calculate the new size of the
|
437
|
-
new_size =
|
438
|
-
new_sizeofcmds += new_size -
|
477
|
+
# calculate the new size of the cmd and sizeofcmds in MH
|
478
|
+
new_size = cmd.class.bytesize + new_str.size
|
479
|
+
new_sizeofcmds += new_size - cmd.cmdsize
|
439
480
|
|
440
481
|
low_fileoff = 2**64 # ULLONGMAX
|
441
482
|
|
@@ -458,17 +499,17 @@ module MachO
|
|
458
499
|
# update sizeofcmds in mach_header
|
459
500
|
set_sizeofcmds(new_sizeofcmds)
|
460
501
|
|
461
|
-
# update cmdsize in the
|
462
|
-
@raw_data[
|
502
|
+
# update cmdsize in the cmd
|
503
|
+
@raw_data[cmd.offset + 4, 4] = [new_size].pack("V")
|
463
504
|
|
464
|
-
# delete the old
|
465
|
-
@raw_data.slice!(
|
505
|
+
# delete the old str
|
506
|
+
@raw_data.slice!(cmd.offset + lc_str.to_i...cmd.offset + cmd.class.bytesize + old_str.size)
|
466
507
|
|
467
|
-
# insert the new
|
468
|
-
@raw_data.insert(
|
508
|
+
# insert the new str
|
509
|
+
@raw_data.insert(cmd.offset + lc_str.to_i, new_str)
|
469
510
|
|
470
511
|
# pad/unpad after new_sizeofcmds until offsets are corrected
|
471
|
-
null_pad =
|
512
|
+
null_pad = old_str.size - new_str.size
|
472
513
|
|
473
514
|
if null_pad < 0
|
474
515
|
@raw_data.slice!(new_sizeofcmds + header.class.bytesize, null_pad.abs)
|
data/lib/macho/tools.rb
CHANGED
@@ -17,12 +17,8 @@ module MachO
|
|
17
17
|
def self.change_dylib_id(filename, new_id)
|
18
18
|
file = MachO.open(filename)
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
file.write!
|
23
|
-
else
|
24
|
-
raise MachOError.new("changing dylib ids for fat binaries is incomplete")
|
25
|
-
end
|
20
|
+
file.dylib_id = new_id
|
21
|
+
file.write!
|
26
22
|
end
|
27
23
|
|
28
24
|
# Changes a shared library install name in a Mach-O or Fat binary, overwriting the source file.
|
@@ -34,11 +30,8 @@ module MachO
|
|
34
30
|
def self.change_install_name(filename, old_name, new_name)
|
35
31
|
file = MachO.open(filename)
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
else
|
40
|
-
raise MachOError.new("changing install names for fat binaries is incomplete")
|
41
|
-
end
|
33
|
+
file.change_install_name(old_name, new_name)
|
34
|
+
file.write!
|
42
35
|
end
|
43
36
|
|
44
37
|
# Changes a runtime path in a Mach-O or Fat binary, overwriting the source file.
|
data/lib/macho.rb
CHANGED
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.
|
4
|
+
version: 0.2.0
|
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-
|
11
|
+
date: 2015-11-11 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
|