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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 939f8d565fc3d98bd633414e797b2f8cd70c0df6
4
- data.tar.gz: 3ab244e120eba39d1f84a8b495de6c221f4fc8f0
3
+ metadata.gz: 513849997d23e143113243138d5924dc483a2a0b
4
+ data.tar.gz: 2e2d1256e5b42be47cdcb81c8981e35021c5fe6a
5
5
  SHA512:
6
- metadata.gz: bb2d31798f5d4b6fefd00a2c3e5c562595331015f9a44b9d3b5bcce84b43db3c473236222412bc1b26e358161df2451e15c8ea292c1c0fc433292afc9871772c
7
- data.tar.gz: 39bd050a693d85cd48e7ce3594d5cfd199732e171df7026474af03723bdd3c1a58108df08c078333fc0304ed84691c14a76bb15b6a168f8411f993e4e7b0b5d2
6
+ metadata.gz: 3e1bb350afe1cbbbfff4a50197886c4c7c6f4675f0de8e5480deafce7ee4986febd3b7d59c067753cea95ed4dc4a92b8e38d8c486344e3c7b2937bcaff22b800
7
+ data.tar.gz: dba7611dadf4672c0929bc5f3c8f70c60051b01c278cb0383209304526a780008a2b19c0e50848a42d962b78c43c11174dd7c0913f123bff88b8392c30acc9fe
@@ -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
@@ -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, regardless of load command type
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
- old_name = old_name.dup
427
- new_name = new_name.dup
467
+ old_str = old_str.dup
468
+ new_str = new_str.dup
428
469
 
429
- old_pad = MachO.round(old_name.size, cmd_round) - old_name.size
430
- new_pad = MachO.round(new_name.size, cmd_round) - new_name.size
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
- old_name << "\x00" * old_pad
434
- new_name << "\x00" * new_pad
474
+ old_str << "\x00" * old_pad
475
+ new_str << "\x00" * new_pad
435
476
 
436
- # calculate the new size of the DylibCommand and sizeofcmds in MH
437
- new_size = DylibCommand.bytesize + new_name.size
438
- new_sizeofcmds += new_size - dylib_cmd.cmdsize
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 dylib_command
462
- @raw_data[dylib_cmd.offset + 4, 4] = [new_size].pack("V")
502
+ # update cmdsize in the cmd
503
+ @raw_data[cmd.offset + 4, 4] = [new_size].pack("V")
463
504
 
464
- # delete the old name
465
- @raw_data.slice!(dylib_cmd.offset + dylib_cmd.name.to_i...dylib_cmd.offset + dylib_cmd.class.bytesize + old_name.size)
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 id
468
- @raw_data.insert(dylib_cmd.offset + dylib_cmd.name.to_i, new_name)
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 = old_name.size - new_name.size
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
- if File.is_a? MachO::MachOFile
21
- file.dylib_id = new_id
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
- if File.is_a? MachO::MachOFile
38
- file.change_install_name(old_name, new_name)
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
@@ -12,5 +12,5 @@ require "#{File.dirname(__FILE__)}/macho/tools"
12
12
  # The primary namespace for ruby-macho.
13
13
  module MachO
14
14
  # release version
15
- VERSION = "0.1.9".freeze
15
+ VERSION = "0.2.0".freeze
16
16
  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.9
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-07 00:00:00.000000000 Z
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