ruby-macho 0.1.9 → 0.2.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/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
|