ruby-macho 1.2.0 → 1.3.0.pre.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd8e36f6bd2e8cd96c08b2c032ce8dd4b8a97249ae5363419e7930a7997cc03c
4
- data.tar.gz: 4ab73d409143e72912e1de7fa050b6debd02cc58bebfcfe92deb0c269cad9702
3
+ metadata.gz: 73711cb2c95bea44060fc6ab6ebd99a66b06ee1a6187b512ae68527e8dc4e8f7
4
+ data.tar.gz: fefdf5b471bbf158af6d8a1bf766f5b327ad737e09badc60d8adae723ef3d3b9
5
5
  SHA512:
6
- metadata.gz: f030168651f8882b7dc44f4ab8392e21222e4c9a3ecf3e78e08612e85a07da0bbd07bb46b93bd3e37509e9d8e296ad21f2f0bf196abb0fbfbe006c10c3bb38cf
7
- data.tar.gz: 4f4c53e171932244957261a7f28fdc129993decffcfc2c212d0b1b6d3c4c67290a609fe3fae91442553456ea38a99660d68eae79bb32e0c4b1fca9287c7b71c7
6
+ metadata.gz: ed466ba6c6c0c62f1cb7fa365401faef73a322c636f9a1e97f3e655457f1787b83ef134360168618849f0d3253f1d6b8ed41aa0f085a9a40b3ca966ef1d437e4
7
+ data.tar.gz: 61781f5efc71e38eff94704c09de7338e53918030189abe0f0bb2e1b442e5685a58076c431f112d27518e921fe5177666ccea7e6015fea65a5d8460da7632d13
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015, 2016 William Woodruff <william @ tuffbizz.com>
3
+ Copyright (c) 2015, 2016, 2017, 2018 William Woodruff <william @ yossarian.net>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -9,7 +9,7 @@ A Ruby library for examining and modifying Mach-O files.
9
9
 
10
10
  ### What is a Mach-O file?
11
11
 
12
- The [Mach-O file format](https://en.wikipedia.org/wiki/Mach-O) is used by OS X
12
+ The [Mach-O file format](https://en.wikipedia.org/wiki/Mach-O) is used by macOS
13
13
  and iOS (among others) as a general purpose binary format for object files,
14
14
  executables, dynamic libraries, and so forth.
15
15
 
@@ -12,7 +12,7 @@ require "#{File.dirname(__FILE__)}/macho/tools"
12
12
  # The primary namespace for ruby-macho.
13
13
  module MachO
14
14
  # release version
15
- VERSION = "1.2.0".freeze
15
+ VERSION = "1.3.0.pre.1".freeze
16
16
 
17
17
  # Opens the given filename as a MachOFile or FatFile, depending on its magic.
18
18
  # @param filename [String] the file being opened
@@ -265,6 +265,15 @@ module MachO
265
265
  File.open(@filename, "wb") { |f| f.write(@raw_data) }
266
266
  end
267
267
 
268
+ # @return [Hash] a hash representation of this {FatFile}
269
+ def to_h
270
+ {
271
+ "header" => header.to_h,
272
+ "fat_archs" => fat_archs.map(&:to_h),
273
+ "machos" => machos.map(&:to_h),
274
+ }
275
+ end
276
+
268
277
  private
269
278
 
270
279
  # Obtain the fat header from raw file data.
@@ -475,6 +475,15 @@ module MachO
475
475
  def serialize
476
476
  [magic, nfat_arch].pack(FORMAT)
477
477
  end
478
+
479
+ # @return [Hash] a hash representation of this {FatHeader}
480
+ def to_h
481
+ {
482
+ "magic" => magic,
483
+ "magic_sym" => MH_MAGICS[magic],
484
+ "nfat_arch" => nfat_arch,
485
+ }.merge super
486
+ end
478
487
  end
479
488
 
480
489
  # Fat binary header architecture structure. A Fat binary has one or more of
@@ -508,7 +517,7 @@ module MachO
508
517
  # @api private
509
518
  def initialize(cputype, cpusubtype, offset, size, align)
510
519
  @cputype = cputype
511
- @cpusubtype = cpusubtype
520
+ @cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK
512
521
  @offset = offset
513
522
  @size = size
514
523
  @align = align
@@ -518,6 +527,19 @@ module MachO
518
527
  def serialize
519
528
  [cputype, cpusubtype, offset, size, align].pack(FORMAT)
520
529
  end
530
+
531
+ # @return [Hash] a hash representation of this {FatArch}
532
+ def to_h
533
+ {
534
+ "cputype" => cputype,
535
+ "cputype_sym" => CPU_TYPES[cputype],
536
+ "cpusubtype" => cpusubtype,
537
+ "cpusubtype_sym" => CPU_SUBTYPES[cputype][cpusubtype],
538
+ "offset" => offset,
539
+ "size" => size,
540
+ "align" => align,
541
+ }.merge super
542
+ end
521
543
  end
522
544
 
523
545
  # 32-bit Mach-O file header structure
@@ -639,6 +661,24 @@ module MachO
639
661
  def alignment
640
662
  magic32? ? 4 : 8
641
663
  end
664
+
665
+ # @return [Hash] a hash representation of this {MachHeader}
666
+ def to_h
667
+ {
668
+ "magic" => magic,
669
+ "magic_sym" => MH_MAGICS[magic],
670
+ "cputype" => cputype,
671
+ "cputype_sym" => CPU_TYPES[cputype],
672
+ "cpusubtype" => cpusubtype,
673
+ "cpusubtype_sym" => CPU_SUBTYPES[cputype][cpusubtype],
674
+ "filetype" => filetype,
675
+ "filetype_sym" => MH_FILETYPES[filetype],
676
+ "ncmds" => ncmds,
677
+ "sizeofcmds" => sizeofcmds,
678
+ "flags" => flags,
679
+ "alignment" => alignment,
680
+ }.merge super
681
+ end
642
682
  end
643
683
 
644
684
  # 64-bit Mach-O file header structure
@@ -660,6 +700,13 @@ module MachO
660
700
  super(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags)
661
701
  @reserved = reserved
662
702
  end
703
+
704
+ # @return [Hash] a hash representation of this {MachHeader64}
705
+ def to_h
706
+ {
707
+ "reserved" => reserved,
708
+ }.merge super
709
+ end
663
710
  end
664
711
  end
665
712
  end
@@ -143,7 +143,7 @@ module MachO
143
143
  :LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand",
144
144
  :LC_VERSION_MIN_TVOS => "VersionMinCommand",
145
145
  :LC_VERSION_MIN_WATCHOS => "VersionMinCommand",
146
- :LC_NOTE => "LoadCommand",
146
+ :LC_NOTE => "NoteCommand",
147
147
  :LC_BUILD_VERSION => "BuildVersionCommand",
148
148
  }.freeze
149
149
 
@@ -169,15 +169,16 @@ module MachO
169
169
  :SG_PROTECTED_VERSION_1 => 0x8,
170
170
  }.freeze
171
171
 
172
- # Mach-O load command structure
173
- # This is the most generic load command - only cmd ID and size are
174
- # represented, and no actual data. Used when a more specific class
175
- # isn't available/implemented.
172
+ # The top-level Mach-O load command structure.
173
+ #
174
+ # This is the most generic load command -- only the type ID and size are
175
+ # represented. Used when a more specific class isn't available or isn't implemented.
176
176
  class LoadCommand < MachOStructure
177
- # @return [MachO::MachOView] the raw view associated with the load command
177
+ # @return [MachO::MachOView, nil] the raw view associated with the load command,
178
+ # or nil if the load command was created via {create}.
178
179
  attr_reader :view
179
180
 
180
- # @return [Integer] the load command's identifying number
181
+ # @return [Integer] the load command's type ID
181
182
  attr_reader :cmd
182
183
 
183
184
  # @return [Integer] the size of the load command, in bytes
@@ -251,8 +252,8 @@ module MachO
251
252
  view.offset
252
253
  end
253
254
 
254
- # @return [Symbol] a symbol representation of the load command's
255
- # identifying number
255
+ # @return [Symbol, nil] a symbol representation of the load command's
256
+ # type ID, or nil if the ID doesn't correspond to a known load command class
256
257
  def type
257
258
  LOAD_COMMANDS[cmd]
258
259
  end
@@ -265,6 +266,17 @@ module MachO
265
266
  type.to_s
266
267
  end
267
268
 
269
+ # @return [Hash] a hash representation of this load command
270
+ # @note Children should override this to include additional information.
271
+ def to_h
272
+ {
273
+ "view" => view.to_h,
274
+ "cmd" => cmd,
275
+ "cmdsize" => cmdsize,
276
+ "type" => type,
277
+ }.merge super
278
+ end
279
+
268
280
  # Represents a Load Command string. A rough analogue to the lc_str
269
281
  # struct used internally by OS X. This class allows ruby-macho to
270
282
  # pretend that strings stored in LCs are immediately available without
@@ -304,6 +316,14 @@ module MachO
304
316
  def to_i
305
317
  @string_offset
306
318
  end
319
+
320
+ # @return [Hash] a hash representation of this {LCStr}.
321
+ def to_h
322
+ {
323
+ "string" => to_s,
324
+ "offset" => to_i,
325
+ }
326
+ end
307
327
  end
308
328
 
309
329
  # Represents the contextual information needed by a load command to
@@ -364,6 +384,14 @@ module MachO
364
384
 
365
385
  segs.join("-")
366
386
  end
387
+
388
+ # @return [Hash] returns a hash representation of this {UUIDCommand}
389
+ def to_h
390
+ {
391
+ "uuid" => uuid,
392
+ "uuid_string" => uuid_string,
393
+ }.merge super
394
+ end
367
395
  end
368
396
 
369
397
  # A load command indicating that part of this file is to be mapped into
@@ -398,7 +426,7 @@ module MachO
398
426
 
399
427
  # @see MachOStructure::FORMAT
400
428
  # @api private
401
- FORMAT = "L=2a16L=4l=2L=2".freeze
429
+ FORMAT = "L=2Z16L=4l=2L=2".freeze
402
430
 
403
431
  # @see MachOStructure::SIZEOF
404
432
  # @api private
@@ -408,7 +436,7 @@ module MachO
408
436
  def initialize(view, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
409
437
  filesize, maxprot, initprot, nsects, flags)
410
438
  super(view, cmd, cmdsize)
411
- @segname = segname.delete("\x00")
439
+ @segname = segname
412
440
  @vmaddr = vmaddr
413
441
  @vmsize = vmsize
414
442
  @fileoff = fileoff
@@ -448,6 +476,22 @@ module MachO
448
476
  return false if flag.nil?
449
477
  flags & flag == flag
450
478
  end
479
+
480
+ # @return [Hash] a hash representation of this {SegmentCommand}
481
+ def to_h
482
+ {
483
+ "segname" => segname,
484
+ "vmaddr" => vmaddr,
485
+ "vmsize" => vmsize,
486
+ "fileoff" => fileoff,
487
+ "filesize" => filesize,
488
+ "maxprot" => maxprot,
489
+ "initprot" => initprot,
490
+ "nsects" => nsects,
491
+ "flags" => flags,
492
+ "sections" => sections.map(&:to_h),
493
+ }.merge super
494
+ end
451
495
  end
452
496
 
453
497
  # A load command indicating that part of this file is to be mapped into
@@ -455,7 +499,7 @@ module MachO
455
499
  class SegmentCommand64 < SegmentCommand
456
500
  # @see MachOStructure::FORMAT
457
501
  # @api private
458
- FORMAT = "L=2a16Q=4l=2L=2".freeze
502
+ FORMAT = "L=2Z16Q=4l=2L=2".freeze
459
503
 
460
504
  # @see MachOStructure::SIZEOF
461
505
  # @api private
@@ -510,6 +554,16 @@ module MachO
510
554
  [cmd, cmdsize, string_offsets[:name], timestamp, current_version,
511
555
  compatibility_version].pack(format) + string_payload
512
556
  end
557
+
558
+ # @return [Hash] a hash representation of this {DylibCommand}
559
+ def to_h
560
+ {
561
+ "name" => name.to_h,
562
+ "timestamp" => timestamp,
563
+ "current_version" => current_version,
564
+ "compatibility_version" => compatibility_version,
565
+ }.merge super
566
+ end
513
567
  end
514
568
 
515
569
  # A load command representing some aspect of the dynamic linker, depending
@@ -546,6 +600,13 @@ module MachO
546
600
  cmdsize = SIZEOF + string_payload.bytesize
547
601
  [cmd, cmdsize, string_offsets[:name]].pack(format) + string_payload
548
602
  end
603
+
604
+ # @return [Hash] a hash representation of this {DylinkerCommand}
605
+ def to_h
606
+ {
607
+ "name" => name.to_h,
608
+ }.merge super
609
+ end
549
610
  end
550
611
 
551
612
  # A load command used to indicate dynamic libraries used in prebinding.
@@ -576,6 +637,15 @@ module MachO
576
637
  @nmodules = nmodules
577
638
  @linked_modules = linked_modules
578
639
  end
640
+
641
+ # @return [Hash] a hash representation of this {PreboundDylibCommand}
642
+ def to_h
643
+ {
644
+ "name" => name.to_h,
645
+ "nmodules" => nmodules,
646
+ "linked_modules" => linked_modules,
647
+ }.merge super
648
+ end
579
649
  end
580
650
 
581
651
  # A load command used to represent threads.
@@ -641,6 +711,20 @@ module MachO
641
711
  @reserved5 = reserved5
642
712
  @reserved6 = reserved6
643
713
  end
714
+
715
+ # @return [Hash] a hash representation of this {RoutinesCommand}
716
+ def to_h
717
+ {
718
+ "init_address" => init_address,
719
+ "init_module" => init_module,
720
+ "reserved1" => reserved1,
721
+ "reserved2" => reserved2,
722
+ "reserved3" => reserved3,
723
+ "reserved4" => reserved4,
724
+ "reserved5" => reserved5,
725
+ "reserved6" => reserved6,
726
+ }.merge super
727
+ end
644
728
  end
645
729
 
646
730
  # A load command containing the address of the dynamic shared library
@@ -675,6 +759,13 @@ module MachO
675
759
  super(view, cmd, cmdsize)
676
760
  @umbrella = LCStr.new(self, umbrella)
677
761
  end
762
+
763
+ # @return [Hash] a hash representation of this {SubFrameworkCommand}
764
+ def to_h
765
+ {
766
+ "umbrella" => umbrella.to_h,
767
+ }.merge super
768
+ end
678
769
  end
679
770
 
680
771
  # A load command signifying membership of a subumbrella containing the name
@@ -696,6 +787,13 @@ module MachO
696
787
  super(view, cmd, cmdsize)
697
788
  @sub_umbrella = LCStr.new(self, sub_umbrella)
698
789
  end
790
+
791
+ # @return [Hash] a hash representation of this {SubUmbrellaCommand}
792
+ def to_h
793
+ {
794
+ "sub_umbrella" => sub_umbrella.to_h,
795
+ }.merge super
796
+ end
699
797
  end
700
798
 
701
799
  # A load command signifying a sublibrary of a shared library. Corresponds
@@ -717,6 +815,13 @@ module MachO
717
815
  super(view, cmd, cmdsize)
718
816
  @sub_library = LCStr.new(self, sub_library)
719
817
  end
818
+
819
+ # @return [Hash] a hash representation of this {SubLibraryCommand}
820
+ def to_h
821
+ {
822
+ "sub_library" => sub_library.to_h,
823
+ }.merge super
824
+ end
720
825
  end
721
826
 
722
827
  # A load command signifying a shared library that is a subframework of
@@ -738,6 +843,13 @@ module MachO
738
843
  super(view, cmd, cmdsize)
739
844
  @sub_client = LCStr.new(self, sub_client)
740
845
  end
846
+
847
+ # @return [Hash] a hash representation of this {SubClientCommand}
848
+ def to_h
849
+ {
850
+ "sub_client" => sub_client.to_h,
851
+ }.merge super
852
+ end
741
853
  end
742
854
 
743
855
  # A load command containing the offsets and sizes of the link-edit 4.3BSD
@@ -749,10 +861,10 @@ module MachO
749
861
  # @return [Integer] the number of symbol table entries
750
862
  attr_reader :nsyms
751
863
 
752
- # @return the string table's offset
864
+ # @return [Integer] the string table's offset
753
865
  attr_reader :stroff
754
866
 
755
- # @return the string table size in bytes
867
+ # @return [Integer] the string table size in bytes
756
868
  attr_reader :strsize
757
869
 
758
870
  # @see MachOStructure::FORMAT
@@ -771,6 +883,16 @@ module MachO
771
883
  @stroff = stroff
772
884
  @strsize = strsize
773
885
  end
886
+
887
+ # @return [Hash] a hash representation of this {SymtabCommand}
888
+ def to_h
889
+ {
890
+ "symoff" => symoff,
891
+ "nsyms" => nsyms,
892
+ "stroff" => stroff,
893
+ "strsize" => strsize,
894
+ }.merge super
895
+ end
774
896
  end
775
897
 
776
898
  # A load command containing symbolic information needed to support data
@@ -864,6 +986,30 @@ module MachO
864
986
  @locreloff = locreloff
865
987
  @nlocrel = nlocrel
866
988
  end
989
+
990
+ # @return [Hash] a hash representation of this {DysymtabCommand}
991
+ def to_h
992
+ {
993
+ "ilocalsym" => ilocalsym,
994
+ "nlocalsym" => nlocalsym,
995
+ "iextdefsym" => iextdefsym,
996
+ "nextdefsym" => nextdefsym,
997
+ "iundefsym" => iundefsym,
998
+ "nundefsym" => nundefsym,
999
+ "tocoff" => tocoff,
1000
+ "ntoc" => ntoc,
1001
+ "modtaboff" => modtaboff,
1002
+ "nmodtab" => nmodtab,
1003
+ "extrefsymoff" => extrefsymoff,
1004
+ "nextrefsyms" => nextrefsyms,
1005
+ "indirectsymoff" => indirectsymoff,
1006
+ "nindirectsyms" => nindirectsyms,
1007
+ "extreloff" => extreloff,
1008
+ "nextrel" => nextrel,
1009
+ "locreloff" => locreloff,
1010
+ "nlocrel" => nlocrel,
1011
+ }.merge super
1012
+ end
867
1013
  end
868
1014
 
869
1015
  # A load command containing the offset and number of hints in the two-level
@@ -895,6 +1041,15 @@ module MachO
895
1041
  @table = TwolevelHintsTable.new(view, htoffset, nhints)
896
1042
  end
897
1043
 
1044
+ # @return [Hash] a hash representation of this {TwolevelHintsCommand}
1045
+ def to_h
1046
+ {
1047
+ "htoffset" => htoffset,
1048
+ "nhints" => nhints,
1049
+ "table" => table.hints.map(&:to_h),
1050
+ }.merge super
1051
+ end
1052
+
898
1053
  # A representation of the two-level namespace lookup hints table exposed
899
1054
  # by a {TwolevelHintsCommand} (`LC_TWOLEVEL_HINTS`).
900
1055
  class TwolevelHintsTable
@@ -927,6 +1082,14 @@ module MachO
927
1082
  @isub_image = blob >> 24
928
1083
  @itoc = blob & 0x00FFFFFF
929
1084
  end
1085
+
1086
+ # @return [Hash] a hash representation of this {TwolevelHint}
1087
+ def to_h
1088
+ {
1089
+ "isub_image" => isub_image,
1090
+ "itoc" => itoc,
1091
+ }
1092
+ end
930
1093
  end
931
1094
  end
932
1095
  end
@@ -950,6 +1113,13 @@ module MachO
950
1113
  super(view, cmd, cmdsize)
951
1114
  @cksum = cksum
952
1115
  end
1116
+
1117
+ # @return [Hash] a hash representation of this {PrebindCksumCommand}
1118
+ def to_h
1119
+ {
1120
+ "cksum" => cksum,
1121
+ }.merge super
1122
+ end
953
1123
  end
954
1124
 
955
1125
  # A load command representing an rpath, which specifies a path that should
@@ -984,6 +1154,13 @@ module MachO
984
1154
  cmdsize = SIZEOF + string_payload.bytesize
985
1155
  [cmd, cmdsize, string_offsets[:path]].pack(format) + string_payload
986
1156
  end
1157
+
1158
+ # @return [Hash] a hash representation of this {RpathCommand}
1159
+ def to_h
1160
+ {
1161
+ "path" => path.to_h,
1162
+ }.merge super
1163
+ end
987
1164
  end
988
1165
 
989
1166
  # A load command representing the offsets and sizes of a blob of data in
@@ -1011,6 +1188,14 @@ module MachO
1011
1188
  @dataoff = dataoff
1012
1189
  @datasize = datasize
1013
1190
  end
1191
+
1192
+ # @return [Hash] a hash representation of this {LinkeditDataCommand}
1193
+ def to_h
1194
+ {
1195
+ "dataoff" => dataoff,
1196
+ "datasize" => datasize,
1197
+ }.merge super
1198
+ end
1014
1199
  end
1015
1200
 
1016
1201
  # A load command representing the offset to and size of an encrypted
@@ -1040,20 +1225,20 @@ module MachO
1040
1225
  @cryptsize = cryptsize
1041
1226
  @cryptid = cryptid
1042
1227
  end
1228
+
1229
+ # @return [Hash] a hash representation of this {EncryptionInfoCommand}
1230
+ def to_h
1231
+ {
1232
+ "cryptoff" => cryptoff,
1233
+ "cryptsize" => cryptsize,
1234
+ "cryptid" => cryptid,
1235
+ }.merge super
1236
+ end
1043
1237
  end
1044
1238
 
1045
1239
  # A load command representing the offset to and size of an encrypted
1046
1240
  # segment. Corresponds to LC_ENCRYPTION_INFO_64.
1047
- class EncryptionInfoCommand64 < LoadCommand
1048
- # @return [Integer] the offset to the encrypted segment
1049
- attr_reader :cryptoff
1050
-
1051
- # @return [Integer] the size of the encrypted segment
1052
- attr_reader :cryptsize
1053
-
1054
- # @return [Integer] the encryption system, or 0 if not encrypted yet
1055
- attr_reader :cryptid
1056
-
1241
+ class EncryptionInfoCommand64 < EncryptionInfoCommand
1057
1242
  # @return [Integer] 64-bit padding value
1058
1243
  attr_reader :pad
1059
1244
 
@@ -1067,12 +1252,16 @@ module MachO
1067
1252
 
1068
1253
  # @api private
1069
1254
  def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid, pad)
1070
- super(view, cmd, cmdsize)
1071
- @cryptoff = cryptoff
1072
- @cryptsize = cryptsize
1073
- @cryptid = cryptid
1255
+ super(view, cmd, cmdsize, cryptoff, cryptsize, cryptid)
1074
1256
  @pad = pad
1075
1257
  end
1258
+
1259
+ # @return [Hash] a hash representation of this {EncryptionInfoCommand64}
1260
+ def to_h
1261
+ {
1262
+ "pad" => pad,
1263
+ }.merge super
1264
+ end
1076
1265
  end
1077
1266
 
1078
1267
  # A load command containing the minimum OS version on which the binary
@@ -1121,6 +1310,16 @@ module MachO
1121
1310
 
1122
1311
  segs.join(".")
1123
1312
  end
1313
+
1314
+ # @return [Hash] a hash representation of this {VersionMinCommand}
1315
+ def to_h
1316
+ {
1317
+ "version" => version,
1318
+ "version_string" => version_string,
1319
+ "sdk" => sdk,
1320
+ "sdk_string" => sdk_string,
1321
+ }.merge super
1322
+ end
1124
1323
  end
1125
1324
 
1126
1325
  # A load command containing the minimum OS version on which
@@ -1156,6 +1355,40 @@ module MachO
1156
1355
  @tool_entries = ToolEntries.new(view, ntools)
1157
1356
  end
1158
1357
 
1358
+ # A string representation of the binary's minimum OS version.
1359
+ # @return [String] a string representing the minimum OS version.
1360
+ def minos_string
1361
+ binary = "%032b" % minos
1362
+ segs = [
1363
+ binary[0..15], binary[16..23], binary[24..31]
1364
+ ].map { |s| s.to_i(2) }
1365
+
1366
+ segs.join(".")
1367
+ end
1368
+
1369
+ # A string representation of the binary's SDK version.
1370
+ # @return [String] a string representing the SDK version.
1371
+ def sdk_string
1372
+ binary = "%032b" % sdk
1373
+ segs = [
1374
+ binary[0..15], binary[16..23], binary[24..31]
1375
+ ].map { |s| s.to_i(2) }
1376
+
1377
+ segs.join(".")
1378
+ end
1379
+
1380
+ # @return [Hash] a hash representation of this {BuildVersionCommand}
1381
+ def to_h
1382
+ {
1383
+ "platform" => platform,
1384
+ "minos" => minos,
1385
+ "minos_string" => minos_string,
1386
+ "sdk" => sdk,
1387
+ "sdk_string" => sdk_string,
1388
+ "tool_entries" => tool_entries.tools.map(&:to_h),
1389
+ }.merge super
1390
+ end
1391
+
1159
1392
  # A representation of the tool versions exposed
1160
1393
  # by a {BuildVersionCommand} (`LC_BUILD_VERSION`).
1161
1394
  class ToolEntries
@@ -1181,36 +1414,22 @@ module MachO
1181
1414
  # @return [Integer] the tool's version number
1182
1415
  attr_reader :version
1183
1416
 
1184
- # @param tool 32-bit integer
1185
- # # @param version 32-bit integer
1417
+ # @param tool [Integer] 32-bit integer
1418
+ # @param version [Integer] 32-bit integer
1186
1419
  # @api private
1187
1420
  def initialize(tool, version)
1188
1421
  @tool = tool
1189
1422
  @version = version
1190
1423
  end
1191
- end
1192
- end
1193
1424
 
1194
- # A string representation of the binary's minimum OS version.
1195
- # @return [String] a string representing the minimum OS version.
1196
- def minos_string
1197
- binary = "%032b" % minos
1198
- segs = [
1199
- binary[0..15], binary[16..23], binary[24..31]
1200
- ].map { |s| s.to_i(2) }
1201
-
1202
- segs.join(".")
1203
- end
1204
-
1205
- # A string representation of the binary's SDK version.
1206
- # @return [String] a string representing the SDK version.
1207
- def sdk_string
1208
- binary = "%032b" % sdk
1209
- segs = [
1210
- binary[0..15], binary[16..23], binary[24..31]
1211
- ].map { |s| s.to_i(2) }
1212
-
1213
- segs.join(".")
1425
+ # @return [Hash] a hash representation of this {Tool}
1426
+ def to_h
1427
+ {
1428
+ "tool" => tool,
1429
+ "version" => version,
1430
+ }
1431
+ end
1432
+ end
1214
1433
  end
1215
1434
  end
1216
1435
 
@@ -1272,6 +1491,22 @@ module MachO
1272
1491
  @export_off = export_off
1273
1492
  @export_size = export_size
1274
1493
  end
1494
+
1495
+ # @return [Hash] a hash representation of this {DyldInfoCommand}
1496
+ def to_h
1497
+ {
1498
+ "rebase_off" => rebase_off,
1499
+ "rebase_size" => rebase_size,
1500
+ "bind_off" => bind_off,
1501
+ "bind_size" => bind_size,
1502
+ "weak_bind_off" => weak_bind_off,
1503
+ "weak_bind_size" => weak_bind_size,
1504
+ "lazy_bind_off" => lazy_bind_off,
1505
+ "lazy_bind_size" => lazy_bind_size,
1506
+ "export_off" => export_off,
1507
+ "export_size" => export_size,
1508
+ }.merge super
1509
+ end
1275
1510
  end
1276
1511
 
1277
1512
  # A load command containing linker options embedded in object files.
@@ -1293,6 +1528,13 @@ module MachO
1293
1528
  super(view, cmd, cmdsize)
1294
1529
  @count = count
1295
1530
  end
1531
+
1532
+ # @return [Hash] a hash representation of this {LinkerOptionCommand}
1533
+ def to_h
1534
+ {
1535
+ "count" => count,
1536
+ }.merge super
1537
+ end
1296
1538
  end
1297
1539
 
1298
1540
  # A load command specifying the offset of main(). Corresponds to LC_MAIN.
@@ -1317,6 +1559,14 @@ module MachO
1317
1559
  @entryoff = entryoff
1318
1560
  @stacksize = stacksize
1319
1561
  end
1562
+
1563
+ # @return [Hash] a hash representation of this {EntryPointCommand}
1564
+ def to_h
1565
+ {
1566
+ "entryoff" => entryoff,
1567
+ "stacksize" => stacksize,
1568
+ }.merge super
1569
+ end
1320
1570
  end
1321
1571
 
1322
1572
  # A load command specifying the version of the sources used to build the
@@ -1350,6 +1600,14 @@ module MachO
1350
1600
 
1351
1601
  segs.join(".")
1352
1602
  end
1603
+
1604
+ # @return [Hash] a hash representation of this {SourceVersionCommand}
1605
+ def to_h
1606
+ {
1607
+ "version" => version,
1608
+ "version_string" => version_string,
1609
+ }.merge super
1610
+ end
1353
1611
  end
1354
1612
 
1355
1613
  # An obsolete load command containing the offset and size of the (GNU style)
@@ -1375,6 +1633,14 @@ module MachO
1375
1633
  @offset = offset
1376
1634
  @size = size
1377
1635
  end
1636
+
1637
+ # @return [Hash] a hash representation of this {SymsegCommand}
1638
+ def to_h
1639
+ {
1640
+ "offset" => offset,
1641
+ "size" => size,
1642
+ }.merge super
1643
+ end
1378
1644
  end
1379
1645
 
1380
1646
  # An obsolete load command containing a free format string table. Each
@@ -1412,6 +1678,14 @@ module MachO
1412
1678
  @name = LCStr.new(self, name)
1413
1679
  @header_addr = header_addr
1414
1680
  end
1681
+
1682
+ # @return [Hash] a hash representation of this {FvmfileCommand}
1683
+ def to_h
1684
+ {
1685
+ "name" => name.to_h,
1686
+ "header_addr" => header_addr,
1687
+ }.merge super
1688
+ end
1415
1689
  end
1416
1690
 
1417
1691
  # An obsolete load command containing the path to a library to be loaded
@@ -1440,6 +1714,52 @@ module MachO
1440
1714
  @minor_version = minor_version
1441
1715
  @header_addr = header_addr
1442
1716
  end
1717
+
1718
+ # @return [Hash] a hash representation of this {FvmlibCommand}
1719
+ def to_h
1720
+ {
1721
+ "name" => name.to_h,
1722
+ "minor_version" => minor_version,
1723
+ "header_addr" => header_addr,
1724
+ }.merge super
1725
+ end
1726
+ end
1727
+
1728
+ # A load command containing an owner name and offset/size for an arbitrary data region.
1729
+ # Corresponds to LC_NOTE.
1730
+ class NoteCommand < LoadCommand
1731
+ # @return [String] the name of the owner for this note
1732
+ attr_reader :data_owner
1733
+
1734
+ # @return [Integer] the offset, within the file, of the note
1735
+ attr_reader :offset
1736
+
1737
+ # @return [Integer] the size, in bytes, of the note
1738
+ attr_reader :size
1739
+
1740
+ # @see MachOStructure::FORMAT
1741
+ # @api private
1742
+ FORMAT = "L=2Z16Q=2".freeze
1743
+
1744
+ # @see MachOStructure::SIZEOF
1745
+ # @api private
1746
+ SIZEOF = 48
1747
+
1748
+ def initialize(view, cmd, cmdsize, data_owner, offset, size)
1749
+ super(view, cmd, cmdsize)
1750
+ @data_owner = data_owner
1751
+ @offset = offset
1752
+ @size = size
1753
+ end
1754
+
1755
+ # @return [Hash] a hash representation of this {NoteCommand}
1756
+ def to_h
1757
+ {
1758
+ "data_owner" => data_owner,
1759
+ "offset" => offset,
1760
+ "size" => size,
1761
+ }.merge super
1762
+ end
1443
1763
  end
1444
1764
  end
1445
1765
  end
@@ -25,7 +25,7 @@ module MachO
25
25
  # @note load commands are provided in order of ascending offset.
26
26
  attr_reader :load_commands
27
27
 
28
- # Creates a new MachOFile instance from a binary string.
28
+ # Creates a new instance from a binary string.
29
29
  # @param bin [String] a binary string containing raw Mach-O data
30
30
  # @return [MachOFile] a new MachOFile
31
31
  def self.new_from_bin(bin)
@@ -35,7 +35,7 @@ module MachO
35
35
  instance
36
36
  end
37
37
 
38
- # Creates a new FatFile from the given filename.
38
+ # Creates a new instance from data read from the given filename.
39
39
  # @param filename [String] the Mach-O file to load from
40
40
  # @raise [ArgumentError] if the given file does not exist
41
41
  def initialize(filename)
@@ -408,6 +408,14 @@ module MachO
408
408
  File.open(@filename, "wb") { |f| f.write(@raw_data) }
409
409
  end
410
410
 
411
+ # @return [Hash] a hash representation of this {MachOFile}
412
+ def to_h
413
+ {
414
+ "header" => header.to_h,
415
+ "load_commands" => load_commands.map(&:to_h),
416
+ }
417
+ end
418
+
411
419
  private
412
420
 
413
421
  # The file's Mach-O header structure.
@@ -104,7 +104,7 @@ module MachO
104
104
  attr_reader :reserved2
105
105
 
106
106
  # @see MachOStructure::FORMAT
107
- FORMAT = "a16a16L=9".freeze
107
+ FORMAT = "Z16Z16L=9".freeze
108
108
 
109
109
  # @see MachOStructure::SIZEOF
110
110
  SIZEOF = 68
@@ -125,16 +125,14 @@ module MachO
125
125
  @reserved2 = reserved2
126
126
  end
127
127
 
128
- # @return [String] the section's name, with any trailing NULL characters
129
- # removed
128
+ # @return [String] the section's name
130
129
  def section_name
131
- sectname.delete("\x00")
130
+ sectname
132
131
  end
133
132
 
134
- # @return [String] the parent segment's name, with any trailing NULL
135
- # characters removed
133
+ # @return [String] the parent segment's name
136
134
  def segment_name
137
- segname.delete("\x00")
135
+ segname
138
136
  end
139
137
 
140
138
  # @return [Boolean] whether the section is empty (i.e, {size} is 0)
@@ -151,6 +149,23 @@ module MachO
151
149
  return false if flag.nil?
152
150
  flags & flag == flag
153
151
  end
152
+
153
+ # @return [Hash] a hash representation of this {Section}
154
+ def to_h
155
+ {
156
+ "sectname" => sectname,
157
+ "segname" => segname,
158
+ "addr" => addr,
159
+ "size" => size,
160
+ "offset" => offset,
161
+ "align" => align,
162
+ "reloff" => reloff,
163
+ "nreloc" => nreloc,
164
+ "flags" => flags,
165
+ "reserved1" => reserved1,
166
+ "reserved2" => reserved2,
167
+ }.merge super
168
+ end
154
169
  end
155
170
 
156
171
  # Represents a section of a segment for 64-bit architectures.
@@ -159,7 +174,7 @@ module MachO
159
174
  attr_reader :reserved3
160
175
 
161
176
  # @see MachOStructure::FORMAT
162
- FORMAT = "a16a16Q=2L=8".freeze
177
+ FORMAT = "Z16Z16Q=2L=8".freeze
163
178
 
164
179
  # @see MachOStructure::SIZEOF
165
180
  SIZEOF = 80
@@ -171,6 +186,13 @@ module MachO
171
186
  nreloc, flags, reserved1, reserved2)
172
187
  @reserved3 = reserved3
173
188
  end
189
+
190
+ # @return [Hash] a hash representation of this {Section64}
191
+ def to_h
192
+ {
193
+ "reserved3" => reserved3,
194
+ }.merge super
195
+ end
174
196
  end
175
197
  end
176
198
  end
@@ -26,5 +26,15 @@ module MachO
26
26
 
27
27
  new(*bin.unpack(format))
28
28
  end
29
+
30
+ # @return [Hash] a hash representation of this {MachOStructure}.
31
+ def to_h
32
+ {
33
+ "structure" => {
34
+ "format" => self.class::FORMAT,
35
+ "bytesize" => self.class.bytesize,
36
+ },
37
+ }
38
+ end
29
39
  end
30
40
  end
@@ -19,5 +19,13 @@ module MachO
19
19
  @endianness = endianness
20
20
  @offset = offset
21
21
  end
22
+
23
+ # @return [Hash] a hash representation of this {MachOView}.
24
+ def to_h
25
+ {
26
+ "endianness" => endianness,
27
+ "offset" => offset,
28
+ }
29
+ end
22
30
  end
23
31
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-macho
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Woodruff
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-06 00:00:00.000000000 Z
11
+ date: 2018-06-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A library for viewing and manipulating Mach-O files in Ruby.
14
- email: william@tuffbizz.com
14
+ email: william@yossarian.net
15
15
  executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
@@ -42,12 +42,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
42
42
  requirements:
43
43
  - - ">="
44
44
  - !ruby/object:Gem::Version
45
- version: 2.0.0
45
+ version: '2.1'
46
46
  required_rubygems_version: !ruby/object:Gem::Requirement
47
47
  requirements:
48
- - - ">="
48
+ - - ">"
49
49
  - !ruby/object:Gem::Version
50
- version: '0'
50
+ version: 1.3.1
51
51
  requirements: []
52
52
  rubyforge_project:
53
53
  rubygems_version: 2.7.6