ruby-macho 1.2.0 → 1.3.0.pre.1

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
  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