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 +4 -4
- data/LICENSE +1 -1
- data/README.md +1 -1
- data/lib/macho.rb +1 -1
- data/lib/macho/fat_file.rb +9 -0
- data/lib/macho/headers.rb +48 -1
- data/lib/macho/load_commands.rb +372 -52
- data/lib/macho/macho_file.rb +10 -2
- data/lib/macho/sections.rb +30 -8
- data/lib/macho/structure.rb +10 -0
- data/lib/macho/view.rb +8 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73711cb2c95bea44060fc6ab6ebd99a66b06ee1a6187b512ae68527e8dc4e8f7
|
4
|
+
data.tar.gz: fefdf5b471bbf158af6d8a1bf766f5b327ad737e09badc60d8adae723ef3d3b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 @
|
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
|
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
|
|
data/lib/macho.rb
CHANGED
@@ -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.
|
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
|
data/lib/macho/fat_file.rb
CHANGED
@@ -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.
|
data/lib/macho/headers.rb
CHANGED
@@ -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
|
data/lib/macho/load_commands.rb
CHANGED
@@ -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 => "
|
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
|
-
#
|
174
|
-
#
|
175
|
-
# isn't available
|
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
|
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
|
-
#
|
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=
|
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
|
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=
|
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 <
|
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
|
-
#
|
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
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
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
|
data/lib/macho/macho_file.rb
CHANGED
@@ -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
|
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
|
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.
|
data/lib/macho/sections.rb
CHANGED
@@ -104,7 +104,7 @@ module MachO
|
|
104
104
|
attr_reader :reserved2
|
105
105
|
|
106
106
|
# @see MachOStructure::FORMAT
|
107
|
-
FORMAT = "
|
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
|
129
|
-
# removed
|
128
|
+
# @return [String] the section's name
|
130
129
|
def section_name
|
131
|
-
sectname
|
130
|
+
sectname
|
132
131
|
end
|
133
132
|
|
134
|
-
# @return [String] the parent segment's name
|
135
|
-
# characters removed
|
133
|
+
# @return [String] the parent segment's name
|
136
134
|
def segment_name
|
137
|
-
segname
|
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 = "
|
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
|
data/lib/macho/structure.rb
CHANGED
@@ -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
|
data/lib/macho/view.rb
CHANGED
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.
|
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-
|
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@
|
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.
|
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:
|
50
|
+
version: 1.3.1
|
51
51
|
requirements: []
|
52
52
|
rubyforge_project:
|
53
53
|
rubygems_version: 2.7.6
|