ruby-macho 0.1.2 → 0.1.3

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: 634d3249001bb3d3bf5782055392c8feea3d15c8
4
- data.tar.gz: bd854ada089451f23d4b253642bbb3eebcbba25f
3
+ metadata.gz: 18e0719447412b4c6fea5f4ca08f5f0e316e34c1
4
+ data.tar.gz: e42a6a11cc91a374693cd13d6d5ff8b07d5dec9c
5
5
  SHA512:
6
- metadata.gz: 06436af8d8c711a2eaa40f396020a80e15ff8f8de474e162f7f3e41d7b1a984d1218bec862d54f18bb9fe20675908ea8dfe1bcdd08b3d4bd50c8d0405daf06a5
7
- data.tar.gz: cc4846d66dc58873417d1baae77c95c7ee4678f5861e98211cb52c4a6363280490473261de8b0143080a7aae71b97e20c0d85b6e0dac5647f106918a3de68c85
6
+ metadata.gz: 6a77b43c73461ed816155a184230f27cb4a8130117f41c9f209033eb89cc09c1581849eb58b5fec55a58a7e8d444e1c0da16576fda19463b9d7c7843b0f21082
7
+ data.tar.gz: 80ac6b3e2c76001e7a61076b7a6cfc72be034f418636d1ac195ee7f24144749ad4453ec67b3d0382e325a9f99fe88e0618db92696d7881051d93f01a2ef1b8d6
@@ -15,10 +15,9 @@ module MachO
15
15
 
16
16
  # Creates a new FatFile from the given filename.
17
17
  # @param filename [String] the fat file to load from
18
- # @raise [MachO::MagicError] if the file does not have a Mach-O magic number.
19
- # @raise [MachO::MachOBinaryError] if the file is not a fat binary.
18
+ # @raise [ArgumentError] if the given filename does not exist
20
19
  def initialize(filename)
21
- raise ArgumentError.new("filename must be a String") unless filename.is_a? String
20
+ raise ArgumentError.new("#{filetype}: no such file") unless File.exist?(filename)
22
21
 
23
22
  @filename = filename
24
23
  @raw_data = open(@filename, "rb") { |f| f.read }
@@ -33,29 +32,26 @@ module MachO
33
32
  @raw_data
34
33
  end
35
34
 
35
+ # The file's type. Assumed to be the same for every Mach-O within.
36
+ # @return [String] the filetype
37
+ def filetype
38
+ machos.first.filetype
39
+ end
40
+
36
41
  # The file's dylib ID. If the file is not a dylib, returns `nil`.
37
42
  # @example
38
43
  # file.dylib_id # => 'libBar.dylib'
39
- # @return [String] the file's dylib ID
44
+ # @return [String, nil] the file's dylib ID
40
45
  def dylib_id
41
- if !machos.all?(&:dylib?)
42
- return nil
43
- end
44
-
45
- ids = machos.map(&:dylib_id)
46
-
47
- # this should never be the case, but let's be defensive
48
- if !ids.uniq!.size == 1
49
- return nil
50
- end
51
-
52
- ids.first
46
+ machos.first.dylib_id
53
47
  end
54
48
 
55
49
  # Changes the file's dylib ID to `new_id`. If the file is not a dylib, does nothing.
56
50
  # @example
57
51
  # file.dylib_id = 'libFoo.dylib'
58
52
  # @param new_id [String] the new dylib ID
53
+ # @return [void]
54
+ # @raise [ArgumentError] if `new_id` is not a String
59
55
  def dylib_id=(new_id)
60
56
  if !new_id.is_a?(String)
61
57
  raise ArgumentError.new("argument must be a String")
@@ -303,16 +303,17 @@ module MachO
303
303
  # @param offset [Fixnum] the offset to initialize with
304
304
  # @param bin [String] the binary string to initialize with
305
305
  # @return [MachO::LoadCommand] the new load command
306
- # @private
307
- def self.new_from_bin(offset, bin)
308
- self.new(offset, *bin.unpack(@format))
306
+ # @api private
307
+ def self.new_from_bin(raw_data, offset, bin)
308
+ self.new(raw_data, offset, *bin.unpack(@format))
309
309
  end
310
310
 
311
- # @param offset [Fixnum] the offset to initialize iwth
311
+ # @param offset [Fixnum] the offset to initialize with
312
312
  # @param cmd [Fixnum] the load command's identifying number
313
313
  # @param cmdsize [Fixnum] the size of the load command in bytes
314
- # @private
315
- def initialize(offset, cmd, cmdsize)
314
+ # @api private
315
+ def initialize(raw_data, offset, cmd, cmdsize)
316
+ @raw_data = raw_data
316
317
  @offset = offset
317
318
  @cmd = cmd
318
319
  @cmdsize = cmdsize
@@ -322,6 +323,33 @@ module MachO
322
323
  def to_s
323
324
  LOAD_COMMANDS[cmd]
324
325
  end
326
+
327
+ # Represents a Load Command string. A rough analogue to the lc_str
328
+ # struct used internally by OS X. This class allows ruby-macho to
329
+ # pretend that strings stored in LCs are immediately available without
330
+ # explicit operations on the raw Mach-O data.
331
+ class LCStr
332
+ # @param raw_data [String] the raw Mach-O data.
333
+ # @param lc [MachO::LoadCommand] the load command
334
+ # @param lc_str [Fixnum] the offset to the beginning of the string
335
+ # @api private
336
+ def initialize(raw_data, lc, lc_str)
337
+ @raw_data = raw_data
338
+ @lc = lc
339
+ @lc_str = lc_str
340
+ @str = @raw_data.slice(@lc.offset + @lc_str...@lc.offset + @lc.cmdsize).delete("\x00")
341
+ end
342
+
343
+ # @return [String] a string representation of the LCStr
344
+ def to_s
345
+ @str
346
+ end
347
+
348
+ # @return [Fixnum] the offset to the beginning of the string in the load command
349
+ def to_i
350
+ @lc_str
351
+ end
352
+ end
325
353
  end
326
354
 
327
355
  # A load command containing a single 128-bit unique random number identifying
@@ -333,9 +361,9 @@ module MachO
333
361
  @format = "VVa16"
334
362
  @sizeof = 24
335
363
 
336
- # @private
337
- def initialize(offset, cmd, cmdsize, uuid)
338
- super(offset, cmd, cmdsize)
364
+ # @api private
365
+ def initialize(raw_data, offset, cmd, cmdsize, uuid)
366
+ super(raw_data, offset, cmd, cmdsize)
339
367
  @uuid = uuid.unpack("C16") # re-unpack for the actual UUID array
340
368
  end
341
369
 
@@ -384,10 +412,10 @@ module MachO
384
412
  @format = "VVa16VVVVVVVV"
385
413
  @sizeof = 56
386
414
 
387
- # @private
388
- def initialize(offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
415
+ # @api private
416
+ def initialize(raw_data, offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
389
417
  filesize, maxprot, initprot, nsects, flags)
390
- super(offset, cmd, cmdsize)
418
+ super(raw_data, offset, cmd, cmdsize)
391
419
  @segname = segname
392
420
  @vmaddr = vmaddr
393
421
  @vmsize = vmsize
@@ -438,10 +466,10 @@ module MachO
438
466
  @format = "VVa16QQQQVVVV"
439
467
  @sizeof = 72
440
468
 
441
- # @private
442
- def initialize(offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
469
+ # @api private
470
+ def initialize(raw_data, offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
443
471
  filesize, maxprot, initprot, nsects, flags)
444
- super(offset, cmd, cmdsize)
472
+ super(raw_data, offset, cmd, cmdsize)
445
473
  @segname = segname
446
474
  @vmaddr = vmaddr
447
475
  @vmsize = vmsize
@@ -463,7 +491,7 @@ module MachO
463
491
  # on filetype. Corresponds to LC_ID_DYLIB, LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB,
464
492
  # and LC_REEXPORT_DYLIB.
465
493
  class DylibCommand < LoadCommand
466
- # @return [Fixnum] the library's path name (lc_str)
494
+ # @return [MachO::LoadCommand::LCStr] the library's path name as an LCStr
467
495
  attr_reader :name
468
496
 
469
497
  # @return [Fixnum] the library's build time stamp
@@ -478,11 +506,11 @@ module MachO
478
506
  @format = "VVVVVV"
479
507
  @sizeof = 24
480
508
 
481
- # @private
482
- def initialize(offset, cmd, cmdsize, name, timestamp, current_version,
509
+ # @api private
510
+ def initialize(raw_data, offset, cmd, cmdsize, name, timestamp, current_version,
483
511
  compatibility_version)
484
- super(offset, cmd, cmdsize)
485
- @name = name
512
+ super(raw_data, offset, cmd, cmdsize)
513
+ @name = LCStr.new(raw_data, self, name)
486
514
  @timestamp = timestamp
487
515
  @current_version = current_version
488
516
  @compatibility_version = compatibility_version
@@ -493,23 +521,23 @@ module MachO
493
521
  # on filetype. Corresponds to LC_ID_DYLINKER, LC_LOAD_DYLINKER, and
494
522
  # LC_DYLD_ENVIRONMENT.
495
523
  class DylinkerCommand < LoadCommand
496
- # @return [Fixnum] the dynamic linker's path name (lc_str)
524
+ # @return [MachO::LoadCommand::LCStr] the dynamic linker's path name as an LCStr
497
525
  attr_reader :name
498
526
 
499
527
  @format = "VVV"
500
528
  @sizeof = 12
501
529
 
502
- # @private
503
- def initialize(offset, cmd, cmdsize, name)
504
- super(offset, cmd, cmdsize)
505
- @name = name
530
+ # @api private
531
+ def initialize(raw_data, offset, cmd, cmdsize, name)
532
+ super(raw_data, offset, cmd, cmdsize)
533
+ @name = LCStr.new(raw_data, self, name)
506
534
  end
507
535
  end
508
536
 
509
537
  # A load command used to indicate dynamic libraries used in prebinding.
510
538
  # Corresponds to LC_PREBOUND_DYLIB.
511
539
  class PreboundDylibCommand < LoadCommand
512
- # @return [Fixnum] the library's path name (lc_str)
540
+ # @return [MachO::LoadCommand::LCStr] the library's path name as an LCStr
513
541
  attr_reader :name
514
542
 
515
543
  # @return [Fixnum] the number of modules in the library
@@ -521,10 +549,10 @@ module MachO
521
549
  @format = "VVVVV"
522
550
  @sizeof = 20
523
551
 
524
- # @private
525
- def initialize(offset, cmd, cmdsize, name, nmodules, linked_modules)
526
- super(offset, cmd, cmdsize)
527
- @name = name
552
+ # @api private
553
+ def initialize(raw_data, offset, cmd, cmdsize, name, nmodules, linked_modules)
554
+ super(raw_data, offset, cmd, cmdsize)
555
+ @name = LCStr.new(raw_data, self, name)
528
556
  @nmodules = nmodules
529
557
  @linked_modules = linked_modules
530
558
  end
@@ -567,11 +595,11 @@ module MachO
567
595
  @format = "VVVVVVVVVV"
568
596
  @sizeof = 40
569
597
 
570
- # @private
571
- def initialize(offset, cmd, cmdsize, init_address, init_module,
598
+ # @api private
599
+ def initialize(raw_data, offset, cmd, cmdsize, init_address, init_module,
572
600
  reserved1, reserved2, reserved3, reserved4, reserved5,
573
601
  reserved6)
574
- super(offset, cmd, cmdsize)
602
+ super(raw_data, offset, cmd, cmdsize)
575
603
  @init_address = init_address
576
604
  @init_module = init_module
577
605
  @reserved1 = reserved1
@@ -614,11 +642,11 @@ module MachO
614
642
  @format = "VVQQQQQQQQ"
615
643
  @sizeof = 72
616
644
 
617
- # @private
618
- def initialize(offset, cmd, cmdsize, init_address, init_module,
645
+ # @api private
646
+ def initialize(raw_data, offset, cmd, cmdsize, init_address, init_module,
619
647
  reserved1, reserved2, reserved3, reserved4, reserved5,
620
648
  reserved6)
621
- super(offset, cmd, cmdsize)
649
+ super(raw_data, offset, cmd, cmdsize)
622
650
  @init_address = init_address
623
651
  @init_module = init_module
624
652
  @reserved1 = reserved1
@@ -633,64 +661,64 @@ module MachO
633
661
  # A load command signifying membership of a subframework containing the name
634
662
  # of an umbrella framework. Corresponds to LC_SUB_FRAMEWORK.
635
663
  class SubFrameworkCommand < LoadCommand
636
- # @return [Fixnum] the umbrella framework name (lc_str)
664
+ # @return [MachO::LoadCommand::LCStr] the umbrella framework name as an LCStr
637
665
  attr_reader :umbrella
638
666
 
639
667
  @format = "VVV"
640
668
  @sizeof = 12
641
669
 
642
- # @private
643
- def initialize(offset, cmd, cmdsize, umbrella)
644
- super(offset, cmd, cmdsize)
645
- @umbrella = umbrella
670
+ # @api private
671
+ def initialize(raw_data, offset, cmd, cmdsize, umbrella)
672
+ super(raw_data, offset, cmd, cmdsize)
673
+ @umbrella = LCStr.new(raw_data, self, umbrella)
646
674
  end
647
675
  end
648
676
 
649
677
  # A load command signifying membership of a subumbrella containing the name
650
678
  # of an umbrella framework. Corresponds to LC_SUB_UMBRELLA.
651
679
  class SubUmbrellaCommand < LoadCommand
652
- # @return [Fixnum] the subumbrella framework name (lc_str)
680
+ # @return [MachO::LoadCommand::LCStr] the subumbrella framework name as an LCStr
653
681
  attr_reader :sub_umbrella
654
682
 
655
683
  @format = "VVV"
656
684
  @sizeof = 12
657
685
 
658
- # @private
659
- def initialize(offset, cmd, cmdsize, sub_umbrella)
660
- super(offset, cmd, cmdsize)
661
- @sub_umbrella = sub_umbrella
686
+ # @api private
687
+ def initialize(raw_data, offset, cmd, cmdsize, sub_umbrella)
688
+ super(raw_data, offset, cmd, cmdsize)
689
+ @sub_umbrella = LCStr.new(raw_data, self, sub_umbrella)
662
690
  end
663
691
  end
664
692
 
665
693
  # A load command signifying a sublibrary of a shared library. Corresponds
666
694
  # to LC_SUB_LIBRARY.
667
695
  class SubLibraryCommand < LoadCommand
668
- # @return [Fixnum] the sublibrary name (lc_str)
696
+ # @return [MachO::LoadCommand::LCStr] the sublibrary name as an LCStr
669
697
  attr_reader :sub_library
670
698
 
671
699
  @format = "VVV"
672
700
  @sizeof = 12
673
701
 
674
- # @private
675
- def initialize(offset, cmd, cmdsize, sub_library)
676
- super(offset, cmd, cmdsize)
677
- @sub_library = sub_library
702
+ # @api private
703
+ def initialize(raw_data, offset, cmd, cmdsize, sub_library)
704
+ super(raw_data, offset, cmd, cmdsize)
705
+ @sub_library = LCStr.new(raw_data, self, sub_library)
678
706
  end
679
707
  end
680
708
 
681
709
  # A load command signifying a shared library that is a subframework of
682
710
  # an umbrella framework. Corresponds to LC_SUB_CLIENT.
683
711
  class SubClientCommand < LoadCommand
684
- # @return [Fixnum] the subclient name (lc_str)
712
+ # @return [MachO::LoadCommand::LCStr] the subclient name as an LCStr
685
713
  attr_reader :sub_client
686
714
 
687
715
  @format = "VVV"
688
716
  @sizeof = 12
689
717
 
690
- # @private
691
- def initialize(offset, cmd, cmdsize, sub_client)
692
- super(offset, cmd, cmdsize)
693
- @sub_client = sub_client
718
+ # @api private
719
+ def initialize(raw_data, offset, cmd, cmdsize, sub_client)
720
+ super(raw_data, offset, cmd, cmdsize)
721
+ @sub_client = LCStr.new(raw_data, self, sub_client)
694
722
  end
695
723
  end
696
724
 
@@ -712,9 +740,9 @@ module MachO
712
740
  @format = "VVVVVV"
713
741
  @sizeof = 24
714
742
 
715
- # @private
716
- def initialize(offset, cmd, cmdsize, symoff, nsyms, stroff, strsize)
717
- super(offset, cmd, cmdsize)
743
+ # @api private
744
+ def initialize(raw_data, offset, cmd, cmdsize, symoff, nsyms, stroff, strsize)
745
+ super(raw_data, offset, cmd, cmdsize)
718
746
  @symoff = symoff
719
747
  @nsyms = nsyms
720
748
  @stroff = stroff
@@ -784,12 +812,12 @@ module MachO
784
812
  @sizeof = 80
785
813
 
786
814
  # ugh
787
- # @private
788
- def initialize(offset, cmd, cmdsize, ilocalsym, nlocalsym, iextdefsym,
815
+ # @api private
816
+ def initialize(raw_data, offset, cmd, cmdsize, ilocalsym, nlocalsym, iextdefsym,
789
817
  nextdefsym, iundefsym, nundefsym, tocoff, ntoc, modtaboff,
790
818
  nmodtab, extrefsymoff, nextrefsyms, indirectsymoff,
791
819
  nindirectsyms, extreloff, nextrel, locreloff, nlocrel)
792
- super(offset, cmd, cmdsize)
820
+ super(raw_data, offset, cmd, cmdsize)
793
821
  @ilocalsym = ilocalsym
794
822
  @nlocalsym = nlocalsym
795
823
  @iextdefsym = iextdefsym
@@ -823,9 +851,9 @@ module MachO
823
851
  @format = "VVVV"
824
852
  @sizeof = 16
825
853
 
826
- # @private
827
- def initialize(offset, cmd, cmdsize, htoffset, nhints)
828
- super(offset, cmd, cmdsize)
854
+ # @api private
855
+ def initialize(raw_data, offset, cmd, cmdsize, htoffset, nhints)
856
+ super(raw_data, offset, cmd, cmdsize)
829
857
  @htoffset = htoffset
830
858
  @nhints = nhints
831
859
  end
@@ -840,9 +868,9 @@ module MachO
840
868
  @format = "VVV"
841
869
  @sizeof = 12
842
870
 
843
- # @private
844
- def initialize(offset, cmd, cmdsize, cksum)
845
- super(offset, cmd, cmdsize)
871
+ # @api private
872
+ def initialize(raw_data, offset, cmd, cmdsize, cksum)
873
+ super(raw_data, offset, cmd, cmdsize)
846
874
  @cksum = cksum
847
875
  end
848
876
  end
@@ -851,16 +879,16 @@ module MachO
851
879
  # be added to the current run path used to find @rpath prefixed dylibs.
852
880
  # Corresponds to LC_RPATH.
853
881
  class RpathCommand < LoadCommand
854
- # @return [Fixnum] the oath to add to the run path (lc_str)
882
+ # @return [MachO::LoadCommand::LCStr] the path to add to the run path as an LCStr
855
883
  attr_reader :path
856
884
 
857
885
  @format = "VVV"
858
886
  @sizeof = 12
859
887
 
860
- # @private
861
- def initialize(offset, cmd, cmdsize, path)
862
- super(offset, cmd, cmdsize)
863
- @path = path
888
+ # @api private
889
+ def initialize(raw_data, offset, cmd, cmdsize, path)
890
+ super(raw_data, offset, cmd, cmdsize)
891
+ @path = LCStr.new(raw_data, self, path)
864
892
  end
865
893
  end
866
894
 
@@ -877,9 +905,9 @@ module MachO
877
905
  @format = "VVVV"
878
906
  @sizeof = 16
879
907
 
880
- # @private
881
- def initialize(offset, cmd, cmdsize, dataoff, datasize)
882
- super(offset, cmd, cmdsize)
908
+ # @api private
909
+ def initialize(raw_data, offset, cmd, cmdsize, dataoff, datasize)
910
+ super(raw_data, offset, cmd, cmdsize)
883
911
  @dataoff = dataoff
884
912
  @datasize = datasize
885
913
  end
@@ -900,9 +928,9 @@ module MachO
900
928
  @format = "VVVVV"
901
929
  @sizeof = 20
902
930
 
903
- # @private
904
- def initialize(offset, cmd, cmdsize, cryptoff, cryptsize, cryptid)
905
- super(offset, cmd, cmdsize)
931
+ # @api private
932
+ def initialize(raw_data, offset, cmd, cmdsize, cryptoff, cryptsize, cryptid)
933
+ super(raw_data, offset, cmd, cmdsize)
906
934
  @cryptoff = cryptoff
907
935
  @cryptsize = cryptsize
908
936
  @cryptid = cryptid
@@ -927,9 +955,9 @@ module MachO
927
955
  @format = "VVVVVV"
928
956
  @sizeof = 24
929
957
 
930
- # @private
931
- def initialize(offset, cmd, cmdsize, cryptoff, cryptsize, cryptid)
932
- super(offset, cmd, cmdsize)
958
+ # @api private
959
+ def initialize(raw_data, offset, cmd, cmdsize, cryptoff, cryptsize, cryptid)
960
+ super(raw_data, offset, cmd, cmdsize)
933
961
  @cryptoff = cryptoff
934
962
  @cryptsize = cryptsize
935
963
  @cryptid = cryptid
@@ -949,9 +977,9 @@ module MachO
949
977
  @format = "VVVV"
950
978
  @sizeof = 16
951
979
 
952
- # @private
953
- def initialize(offset, cmd, cmdsize, version, sdk)
954
- super(offset, cmd, cmdsize)
980
+ # @api private
981
+ def initialize(raw_data, offset, cmd, cmdsize, version, sdk)
982
+ super(raw_data, offset, cmd, cmdsize)
955
983
  @version = version
956
984
  @sdk = sdk
957
985
  end
@@ -1016,11 +1044,11 @@ module MachO
1016
1044
  @format = "VVVVVVVVVVVV"
1017
1045
  @sizeof = 48
1018
1046
 
1019
- # @private
1020
- def initialize(offset, cmd, cmdsize, rebase_off, rebase_size, bind_off,
1047
+ # @api private
1048
+ def initialize(raw_data, offset, cmd, cmdsize, rebase_off, rebase_size, bind_off,
1021
1049
  bind_size, weak_bind_off, weak_bind_size, lazy_bind_off,
1022
1050
  lazy_bind_size, export_off, export_size)
1023
- super(offset, cmd, cmdsize)
1051
+ super(raw_data, offset, cmd, cmdsize)
1024
1052
  @rebase_off = rebase_off
1025
1053
  @rebase_size = rebase_size
1026
1054
  @bind_off = bind_off
@@ -1043,9 +1071,9 @@ module MachO
1043
1071
  @format = "VVV"
1044
1072
  @sizeof = 12
1045
1073
 
1046
- # @private
1047
- def initialize(offset, cmd, cmdsize, count)
1048
- super(offset, cmd, cmdsize)
1074
+ # @api private
1075
+ def initialize(raw_data, offset, cmd, cmdsize, count)
1076
+ super(raw_data, offset, cmd, cmdsize)
1049
1077
  @count = count
1050
1078
  end
1051
1079
  end
@@ -1061,9 +1089,9 @@ module MachO
1061
1089
  @format = "VVQQ"
1062
1090
  @sizeof = 24
1063
1091
 
1064
- # @private
1065
- def initialize(offset, cmd, cmdsize, entryoff, stacksize)
1066
- super(offset, cmd, cmdsize)
1092
+ # @api private
1093
+ def initialize(raw_data, offset, cmd, cmdsize, entryoff, stacksize)
1094
+ super(raw_data, offset, cmd, cmdsize)
1067
1095
  @entryoff = entryoff
1068
1096
  @stacksize = stacksize
1069
1097
  end
@@ -1078,9 +1106,9 @@ module MachO
1078
1106
  @format = "VVQ"
1079
1107
  @sizeof = 16
1080
1108
 
1081
- # @private
1082
- def initialize(offset, cmd, cmdsize, version)
1083
- super(offset, cmd, cmdsize)
1109
+ # @api private
1110
+ def initialize(raw_data, offset, cmd, cmdsize, version)
1111
+ super(raw_data, offset, cmd, cmdsize)
1084
1112
  @version = version
1085
1113
  end
1086
1114
 
@@ -24,9 +24,9 @@ module MachO
24
24
 
25
25
  # Creates a new FatFile from the given filename.
26
26
  # @param filename [String] the Mach-O file to load from
27
- # @todo document all the exceptions propagated here
27
+ # @raise [ArgumentError] if the given filename does not exist
28
28
  def initialize(filename)
29
- raise ArgumentError.new("filename must be a String") unless filename.is_a? String
29
+ raise ArgumentError.new("#{filetype}: no such file") unless File.exist?(filename)
30
30
 
31
31
  @filename = filename
32
32
  @raw_data = open(@filename, "rb") { |f| f.read }
@@ -34,7 +34,7 @@ module MachO
34
34
  @load_commands = get_load_commands
35
35
  end
36
36
 
37
- # @private
37
+ # @api private
38
38
  def initialize_from_bin(bin)
39
39
  @filename = nil
40
40
  @raw_data = bin
@@ -138,21 +138,15 @@ module MachO
138
138
  # The Mach-O's dylib ID, or `nil` if not a dylib.
139
139
  # @example
140
140
  # file.dylib_id # => 'libBar.dylib'
141
- # @return [String] the Mach-O's dylib ID
141
+ # @return [String, nil] the Mach-O's dylib ID
142
142
  def dylib_id
143
143
  if !dylib?
144
144
  return nil
145
145
  end
146
146
 
147
- dylib_id_cmd = command('LC_ID_DYLIB').first
148
-
149
- cmdsize = dylib_id_cmd.cmdsize
150
- offset = dylib_id_cmd.offset
151
- stroffset = dylib_id_cmd.name
147
+ dylib_id_cmd = command("LC_ID_DYLIB").first
152
148
 
153
- dylib_id = @raw_data.slice(offset + stroffset...offset + cmdsize).unpack("Z*").first
154
-
155
- dylib_id.delete("\x00")
149
+ dylib_id_cmd.name.to_s
156
150
  end
157
151
 
158
152
  # Changes the Mach-O's dylib ID to `new_id`. Does nothing if not a dylib.
@@ -160,6 +154,7 @@ module MachO
160
154
  # file.dylib_id = "libFoo.dylib"
161
155
  # @param new_id [String] the dylib's new ID
162
156
  # @return [void]
157
+ # @raise [ArgumentError] if `new_id` is not a String
163
158
  def dylib_id=(new_id)
164
159
  if !new_id.is_a?(String)
165
160
  raise ArgumentError.new("argument must be a String")
@@ -169,7 +164,7 @@ module MachO
169
164
  return nil
170
165
  end
171
166
 
172
- dylib_cmd = command('LC_ID_DYLIB').first
167
+ dylib_cmd = command("LC_ID_DYLIB").first
173
168
  old_id = dylib_id
174
169
 
175
170
  set_name_in_dylib(dylib_cmd, old_id, new_id)
@@ -179,14 +174,10 @@ module MachO
179
174
  # @return [Array<String>] an array of all shared libraries
180
175
  def linked_dylibs
181
176
  dylibs = []
182
- dylib_cmds = command('LC_LOAD_DYLIB')
177
+ dylib_cmds = command("LC_LOAD_DYLIB")
183
178
 
184
179
  dylib_cmds.each do |dylib_cmd|
185
- cmdsize = dylib_cmd.cmdsize
186
- offset = dylib_cmd.offset
187
- stroffset = dylib_cmd.name
188
-
189
- dylib = @raw_data.slice(offset + stroffset...offset + cmdsize).unpack("Z*").first
180
+ dylib = dylib_cmd.name.to_s
190
181
 
191
182
  dylibs << dylib
192
183
  end
@@ -200,6 +191,7 @@ module MachO
200
191
  # @param old_name [String] the shared library's old name
201
192
  # @param new_name [String] the shared library's new name
202
193
  # @return [void]
194
+ # @raise [MachO::DylibUnknownError] if no shared library has the old name
203
195
  def change_install_name(old_name, new_name)
204
196
  idx = linked_dylibs.index(old_name)
205
197
  raise DylibUnknownError.new(old_name) if idx.nil?
@@ -207,7 +199,7 @@ module MachO
207
199
  # this is a bit of a hack - since there is a 1-1 ordered association
208
200
  # between linked_dylibs and command('LC_LOAD_DYLIB'), we can use
209
201
  # their indices interchangeably to avoid having to loop.
210
- dylib_cmd = command('LC_LOAD_DYLIB')[idx]
202
+ dylib_cmd = command("LC_LOAD_DYLIB")[idx]
211
203
 
212
204
  set_name_in_dylib(dylib_cmd, old_name, new_name)
213
205
  end
@@ -215,6 +207,7 @@ module MachO
215
207
  alias :change_dylib :change_install_name
216
208
 
217
209
  # All sections of the segment `segment`.
210
+ # @param segment [MachO::SegmentCommand, MachO::SegmentCommand64] the segment being inspected
218
211
  # @return [Array<MachO::Section>] if the Mach-O is 32-bit
219
212
  # @return [Array<MachO::Section64>] if the Mach-O is 64-bit
220
213
  def sections(segment)
@@ -253,6 +246,7 @@ module MachO
253
246
  # Write all Mach-O data to the file used to initialize the instance.
254
247
  # @raise [MachOError] if the instance was created from a binary string
255
248
  # @return [void]
249
+ # @raise [MachO::MachOError] if the instance was initialized without a file
256
250
  # @note Overwrites all data in the file!
257
251
  def write!
258
252
  if @filename.nil?
@@ -394,7 +388,7 @@ module MachO
394
388
  # why do I do this? i don't like declaring constants below
395
389
  # classes, and i need them to resolve...
396
390
  klass = MachO.const_get "#{LC_STRUCTURES[cmd]}"
397
- command = klass.new_from_bin(offset, @raw_data.slice(offset, klass.bytesize))
391
+ command = klass.new_from_bin(@raw_data, offset, @raw_data.slice(offset, klass.bytesize))
398
392
 
399
393
  load_commands << command
400
394
  offset += command.cmdsize
@@ -417,6 +411,7 @@ module MachO
417
411
  # @param old_name [String] the old dylib name
418
412
  # @param new_name [String] the new dylib name
419
413
  # @return [void]
414
+ # @raise [MachO::HeaderPadError] if the new name exceeds the header pad buffer
420
415
  # @private
421
416
  def set_name_in_dylib(dylib_cmd, old_name, new_name)
422
417
  if magic32?
@@ -465,10 +460,10 @@ module MachO
465
460
  @raw_data[dylib_cmd.offset + 4, 4] = [new_size].pack("V")
466
461
 
467
462
  # delete the old name
468
- @raw_data.slice!(dylib_cmd.offset + dylib_cmd.name...dylib_cmd.offset + dylib_cmd.class.bytesize + old_name.size)
463
+ @raw_data.slice!(dylib_cmd.offset + dylib_cmd.name.to_i...dylib_cmd.offset + dylib_cmd.class.bytesize + old_name.size)
469
464
 
470
465
  # insert the new id
471
- @raw_data.insert(dylib_cmd.offset + dylib_cmd.name, new_name)
466
+ @raw_data.insert(dylib_cmd.offset + dylib_cmd.name.to_i, new_name)
472
467
 
473
468
  # pad/unpad after new_sizeofcmds until offsets are corrected
474
469
  null_pad = old_name.size - new_name.size
@@ -58,13 +58,43 @@ module MachO
58
58
 
59
59
  # Represents a section of a segment for 32-bit architectures.
60
60
  class Section < MachOStructure
61
- attr_reader :sectname, :segname, :addr, :size, :offset, :align, :reloff
62
- attr_reader :nreloc, :flags, :reserved1, :reserved2
61
+ # @return [String] the name of the section, including null pad bytes
62
+ attr_reader :sectname
63
+
64
+ # @return [String] the name of the segment's section, including null pad bytes
65
+ attr_reader :segname
66
+
67
+ # @return [Fixnum] the memory address of the section
68
+ attr_reader :addr
69
+
70
+ # @return [Fixnum] the size, in bytes, of the section
71
+ attr_reader :size
72
+
73
+ # @return [Fixnum] the file offset of the section
74
+ attr_reader :offset
75
+
76
+ # @return [Fixnum] the section alignment (power of 2) of the section
77
+ attr_reader :align
78
+
79
+ # @return [Fixnum] the file offset of the section's relocation entries
80
+ attr_reader :reloff
81
+
82
+ # @return [Fixnum] the number of relocation entries
83
+ attr_reader :nreloc
84
+
85
+ # @return [Fixnum] flags for type and addrributes of the section
86
+ attr_reader :flags
87
+
88
+ # @return [void] reserved (for offset or index)
89
+ attr_reader :reserved1
90
+
91
+ # @return [void] reserved (for count or sizeof)
92
+ attr_reader :reserved2
63
93
 
64
94
  @format = "a16a16VVVVVVVVV"
65
95
  @sizeof = 68
66
96
 
67
- # @private
97
+ # @api private
68
98
  def initialize(sectname, segname, addr, size, offset, align, reloff,
69
99
  nreloc, flags, reserved1, reserved2)
70
100
  @sectname = sectname
@@ -101,13 +131,46 @@ module MachO
101
131
 
102
132
  # Represents a section of a segment for 64-bit architectures.
103
133
  class Section64 < MachOStructure
104
- attr_reader :sectname, :segname, :addr, :size, :offset, :align, :reloff
105
- attr_reader :nreloc, :flags, :reserved1, :reserved2, :reserved3
134
+ # @return [String] the name of the section, including null pad bytes
135
+ attr_reader :sectname
136
+
137
+ # @return [String] the name of the segment's section, including null pad bytes
138
+ attr_reader :segname
139
+
140
+ # @return [Fixnum] the memory address of the section
141
+ attr_reader :addr
142
+
143
+ # @return [Fixnum] the size, in bytes, of the section
144
+ attr_reader :size
145
+
146
+ # @return [Fixnum] the file offset of the section
147
+ attr_reader :offset
148
+
149
+ # @return [Fixnum] the section alignment (power of 2) of the section
150
+ attr_reader :align
151
+
152
+ # @return [Fixnum] the file offset of the section's relocation entries
153
+ attr_reader :reloff
154
+
155
+ # @return [Fixnum] the number of relocation entries
156
+ attr_reader :nreloc
157
+
158
+ # @return [Fixnum] flags for type and addrributes of the section
159
+ attr_reader :flags
160
+
161
+ # @return [void] reserved (for offset or index)
162
+ attr_reader :reserved1
163
+
164
+ # @return [void] reserved (for count or sizeof)
165
+ attr_reader :reserved2
166
+
167
+ # @return [void] reserved
168
+ attr_reader :reserved3
106
169
 
107
170
  @format = "a16a16QQVVVVVVVV"
108
171
  @sizeof = 80
109
172
 
110
- # @private
173
+ # @api private
111
174
  def initialize(sectname, segname, addr, size, offset, align, reloff,
112
175
  nreloc, flags, reserved1, reserved2, reserved3)
113
176
  @sectname = sectname
@@ -12,6 +12,7 @@ module MachO
12
12
  end
13
13
 
14
14
  # @return [MachO::MachOStructure] a new MachOStructure initialized with `bin`
15
+ # @api private
15
16
  def self.new_from_bin(bin)
16
17
  self.new(*bin.unpack(@format))
17
18
  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.2
4
+ version: 0.1.3
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-25 00:00:00.000000000 Z
11
+ date: 2015-10-27 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