ruby-macho 2.5.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -34,24 +34,24 @@ module MachO
34
34
  0x15 => :LC_SUB_LIBRARY,
35
35
  0x16 => :LC_TWOLEVEL_HINTS,
36
36
  0x17 => :LC_PREBIND_CKSUM,
37
- (0x18 | LC_REQ_DYLD) => :LC_LOAD_WEAK_DYLIB,
37
+ (LC_REQ_DYLD | 0x18) => :LC_LOAD_WEAK_DYLIB,
38
38
  0x19 => :LC_SEGMENT_64,
39
39
  0x1a => :LC_ROUTINES_64,
40
40
  0x1b => :LC_UUID,
41
- (0x1c | LC_REQ_DYLD) => :LC_RPATH,
41
+ (LC_REQ_DYLD | 0x1c) => :LC_RPATH,
42
42
  0x1d => :LC_CODE_SIGNATURE,
43
43
  0x1e => :LC_SEGMENT_SPLIT_INFO,
44
- (0x1f | LC_REQ_DYLD) => :LC_REEXPORT_DYLIB,
44
+ (LC_REQ_DYLD | 0x1f) => :LC_REEXPORT_DYLIB,
45
45
  0x20 => :LC_LAZY_LOAD_DYLIB,
46
46
  0x21 => :LC_ENCRYPTION_INFO,
47
47
  0x22 => :LC_DYLD_INFO,
48
- (0x22 | LC_REQ_DYLD) => :LC_DYLD_INFO_ONLY,
49
- (0x23 | LC_REQ_DYLD) => :LC_LOAD_UPWARD_DYLIB,
48
+ (LC_REQ_DYLD | 0x22) => :LC_DYLD_INFO_ONLY,
49
+ (LC_REQ_DYLD | 0x23) => :LC_LOAD_UPWARD_DYLIB,
50
50
  0x24 => :LC_VERSION_MIN_MACOSX,
51
51
  0x25 => :LC_VERSION_MIN_IPHONEOS,
52
52
  0x26 => :LC_FUNCTION_STARTS,
53
53
  0x27 => :LC_DYLD_ENVIRONMENT,
54
- (0x28 | LC_REQ_DYLD) => :LC_MAIN,
54
+ (LC_REQ_DYLD | 0x28) => :LC_MAIN,
55
55
  0x29 => :LC_DATA_IN_CODE,
56
56
  0x2a => :LC_SOURCE_VERSION,
57
57
  0x2b => :LC_DYLIB_CODE_SIGN_DRS,
@@ -62,8 +62,9 @@ module MachO
62
62
  0x30 => :LC_VERSION_MIN_WATCHOS,
63
63
  0x31 => :LC_NOTE,
64
64
  0x32 => :LC_BUILD_VERSION,
65
- (0x33 | LC_REQ_DYLD) => :LC_DYLD_EXPORTS_TRIE,
66
- (0x34 | LC_REQ_DYLD) => :LD_DYLD_CHAINED_FIXUPS,
65
+ (LC_REQ_DYLD | 0x33) => :LC_DYLD_EXPORTS_TRIE,
66
+ (LC_REQ_DYLD | 0x34) => :LC_DYLD_CHAINED_FIXUPS,
67
+ (LC_REQ_DYLD | 0x35) => :LC_FILESET_ENTRY,
67
68
  }.freeze
68
69
 
69
70
  # association of symbol representations to load command constants
@@ -150,7 +151,8 @@ module MachO
150
151
  :LC_NOTE => "NoteCommand",
151
152
  :LC_BUILD_VERSION => "BuildVersionCommand",
152
153
  :LC_DYLD_EXPORTS_TRIE => "LinkeditDataCommand",
153
- :LD_DYLD_CHAINED_FIXUPS => "LinkeditDataCommand",
154
+ :LC_DYLD_CHAINED_FIXUPS => "LinkeditDataCommand",
155
+ :LC_FILESET_ENTRY => "FilesetEntryCommand",
154
156
  }.freeze
155
157
 
156
158
  # association of segment name symbols to names
@@ -158,12 +160,27 @@ module MachO
158
160
  SEGMENT_NAMES = {
159
161
  :SEG_PAGEZERO => "__PAGEZERO",
160
162
  :SEG_TEXT => "__TEXT",
163
+ :SEG_TEXT_EXEC => "__TEXT_EXEC",
161
164
  :SEG_DATA => "__DATA",
165
+ :SEG_DATA_CONST => "__DATA_CONST",
162
166
  :SEG_OBJC => "__OBJC",
167
+ :SEG_OBJC_CONST => "__OBJC_CONST",
163
168
  :SEG_ICON => "__ICON",
164
169
  :SEG_LINKEDIT => "__LINKEDIT",
170
+ :SEG_LINKINFO => "__LINKINFO",
165
171
  :SEG_UNIXSTACK => "__UNIXSTACK",
166
172
  :SEG_IMPORT => "__IMPORT",
173
+ :SEG_KLD => "__KLD",
174
+ :SEG_KLDDATA => "__KLDDATA",
175
+ :SEG_HIB => "__HIB",
176
+ :SEG_VECTORS => "__VECTORS",
177
+ :SEG_LAST => "__LAST",
178
+ :SEG_LASTDATA_CONST => "__LASTDATA_CONST",
179
+ :SEG_PRELINK_TEXT => "__PRELINK_TEXT",
180
+ :SEG_PRELINK_INFO => "__PRELINK_INFO",
181
+ :SEG_CTF => "__CTF",
182
+ :SEG_AUTH => "__AUTH",
183
+ :SEG_AUTH_CONST => "__AUTH_CONST",
167
184
  }.freeze
168
185
 
169
186
  # association of segment flag symbols to values
@@ -173,6 +190,7 @@ module MachO
173
190
  :SG_FVMLIB => 0x2,
174
191
  :SG_NORELOC => 0x4,
175
192
  :SG_PROTECTED_VERSION_1 => 0x8,
193
+ :SG_READ_ONLY => 0x10,
176
194
  }.freeze
177
195
 
178
196
  # The top-level Mach-O load command structure.
@@ -182,21 +200,13 @@ module MachO
182
200
  class LoadCommand < MachOStructure
183
201
  # @return [MachO::MachOView, nil] the raw view associated with the load command,
184
202
  # or nil if the load command was created via {create}.
185
- attr_reader :view
203
+ field :view, :view
186
204
 
187
205
  # @return [Integer] the load command's type ID
188
- attr_reader :cmd
206
+ field :cmd, :uint32
189
207
 
190
208
  # @return [Integer] the size of the load command, in bytes
191
- attr_reader :cmdsize
192
-
193
- # @see MachOStructure::FORMAT
194
- # @api private
195
- FORMAT = "L=2"
196
-
197
- # @see MachOStructure::SIZEOF
198
- # @api private
199
- SIZEOF = 8
209
+ field :cmdsize, :uint32
200
210
 
201
211
  # Instantiates a new LoadCommand given a view into its origin Mach-O
202
212
  # @param view [MachO::MachOView] the load command's raw view
@@ -204,7 +214,7 @@ module MachO
204
214
  # @api private
205
215
  def self.new_from_bin(view)
206
216
  bin = view.raw_data.slice(view.offset, bytesize)
207
- format = Utils.specialize_format(self::FORMAT, view.endianness)
217
+ format = Utils.specialize_format(self.format, view.endianness)
208
218
 
209
219
  new(view, *bin.unpack(format))
210
220
  end
@@ -219,24 +229,13 @@ module MachO
219
229
  cmd = LOAD_COMMAND_CONSTANTS[cmd_sym]
220
230
 
221
231
  # cmd will be filled in, view and cmdsize will be left unpopulated
222
- klass_arity = klass.instance_method(:initialize).arity - 3
232
+ klass_arity = klass.min_args - 3
223
233
 
224
- raise LoadCommandCreationArityError.new(cmd_sym, klass_arity, args.size) if klass_arity != args.size
234
+ raise LoadCommandCreationArityError.new(cmd_sym, klass_arity, args.size) if klass_arity > args.size
225
235
 
226
236
  klass.new(nil, cmd, nil, *args)
227
237
  end
228
238
 
229
- # @param view [MachO::MachOView] the load command's raw view
230
- # @param cmd [Integer] the load command's identifying number
231
- # @param cmdsize [Integer] the size of the load command in bytes
232
- # @api private
233
- def initialize(view, cmd, cmdsize)
234
- super()
235
- @view = view
236
- @cmd = cmd
237
- @cmdsize = cmdsize
238
- end
239
-
240
239
  # @return [Boolean] whether the load command can be serialized
241
240
  def serializable?
242
241
  CREATABLE_LOAD_COMMANDS.include?(LOAD_COMMANDS[cmd])
@@ -250,8 +249,8 @@ module MachO
250
249
  def serialize(context)
251
250
  raise LoadCommandNotSerializableError, LOAD_COMMANDS[cmd] unless serializable?
252
251
 
253
- format = Utils.specialize_format(FORMAT, context.endianness)
254
- [cmd, SIZEOF].pack(format)
252
+ format = Utils.specialize_format(self.class.format, context.endianness)
253
+ [cmd, self.class.bytesize].pack(format)
255
254
  end
256
255
 
257
256
  # @return [Integer] the load command's offset in the source file
@@ -368,21 +367,7 @@ module MachO
368
367
  # LC_UUID.
369
368
  class UUIDCommand < LoadCommand
370
369
  # @return [Array<Integer>] the UUID
371
- attr_reader :uuid
372
-
373
- # @see MachOStructure::FORMAT
374
- # @api private
375
- FORMAT = "L=2a16"
376
-
377
- # @see MachOStructure::SIZEOF
378
- # @api private
379
- SIZEOF = 24
380
-
381
- # @api private
382
- def initialize(view, cmd, cmdsize, uuid)
383
- super(view, cmd, cmdsize)
384
- @uuid = uuid.unpack("C16") # re-unpack for the actual UUID array
385
- end
370
+ field :uuid, :string, :size => 16, :unpack => "C16"
386
371
 
387
372
  # @return [String] a string representation of the UUID
388
373
  def uuid_string
@@ -395,6 +380,11 @@ module MachO
395
380
  segs.join("-")
396
381
  end
397
382
 
383
+ # @return [String] an alias for uuid_string
384
+ def to_s
385
+ uuid_string
386
+ end
387
+
398
388
  # @return [Hash] returns a hash representation of this {UUIDCommand}
399
389
  def to_h
400
390
  {
@@ -408,54 +398,31 @@ module MachO
408
398
  # the task's address space. Corresponds to LC_SEGMENT.
409
399
  class SegmentCommand < LoadCommand
410
400
  # @return [String] the name of the segment
411
- attr_reader :segname
401
+ field :segname, :string, :padding => :null, :size => 16, :to_s => true
412
402
 
413
403
  # @return [Integer] the memory address of the segment
414
- attr_reader :vmaddr
404
+ field :vmaddr, :uint32
415
405
 
416
406
  # @return [Integer] the memory size of the segment
417
- attr_reader :vmsize
407
+ field :vmsize, :uint32
418
408
 
419
409
  # @return [Integer] the file offset of the segment
420
- attr_reader :fileoff
410
+ field :fileoff, :uint32
421
411
 
422
412
  # @return [Integer] the amount to map from the file
423
- attr_reader :filesize
413
+ field :filesize, :uint32
424
414
 
425
415
  # @return [Integer] the maximum VM protection
426
- attr_reader :maxprot
416
+ field :maxprot, :int32
427
417
 
428
418
  # @return [Integer] the initial VM protection
429
- attr_reader :initprot
419
+ field :initprot, :int32
430
420
 
431
421
  # @return [Integer] the number of sections in the segment
432
- attr_reader :nsects
422
+ field :nsects, :uint32
433
423
 
434
424
  # @return [Integer] any flags associated with the segment
435
- attr_reader :flags
436
-
437
- # @see MachOStructure::FORMAT
438
- # @api private
439
- FORMAT = "L=2Z16L=4l=2L=2"
440
-
441
- # @see MachOStructure::SIZEOF
442
- # @api private
443
- SIZEOF = 56
444
-
445
- # @api private
446
- def initialize(view, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
447
- filesize, maxprot, initprot, nsects, flags)
448
- super(view, cmd, cmdsize)
449
- @segname = segname
450
- @vmaddr = vmaddr
451
- @vmsize = vmsize
452
- @fileoff = fileoff
453
- @filesize = filesize
454
- @maxprot = maxprot
455
- @initprot = initprot
456
- @nsects = nsects
457
- @flags = flags
458
- end
425
+ field :flags, :uint32
459
426
 
460
427
  # All sections referenced within this segment.
461
428
  # @return [Array<MachO::Sections::Section>] if the Mach-O is 32-bit
@@ -529,13 +496,17 @@ module MachO
529
496
  # A load command indicating that part of this file is to be mapped into
530
497
  # the task's address space. Corresponds to LC_SEGMENT_64.
531
498
  class SegmentCommand64 < SegmentCommand
532
- # @see MachOStructure::FORMAT
533
- # @api private
534
- FORMAT = "L=2Z16Q=4l=2L=2"
499
+ # @return [Integer] the memory address of the segment
500
+ field :vmaddr, :uint64
535
501
 
536
- # @see MachOStructure::SIZEOF
537
- # @api private
538
- SIZEOF = 72
502
+ # @return [Integer] the memory size of the segment
503
+ field :vmsize, :uint64
504
+
505
+ # @return [Integer] the file offset of the segment
506
+ field :fileoff, :uint64
507
+
508
+ # @return [Integer] the amount to map from the file
509
+ field :filesize, :uint64
539
510
  end
540
511
 
541
512
  # A load command representing some aspect of shared libraries, depending
@@ -544,45 +515,27 @@ module MachO
544
515
  class DylibCommand < LoadCommand
545
516
  # @return [LCStr] the library's path
546
517
  # name as an LCStr
547
- attr_reader :name
518
+ field :name, :lcstr, :to_s => true
548
519
 
549
520
  # @return [Integer] the library's build time stamp
550
- attr_reader :timestamp
521
+ field :timestamp, :uint32
551
522
 
552
523
  # @return [Integer] the library's current version number
553
- attr_reader :current_version
524
+ field :current_version, :uint32
554
525
 
555
526
  # @return [Integer] the library's compatibility version number
556
- attr_reader :compatibility_version
557
-
558
- # @see MachOStructure::FORMAT
559
- # @api private
560
- FORMAT = "L=6"
561
-
562
- # @see MachOStructure::SIZEOF
563
- # @api private
564
- SIZEOF = 24
565
-
566
- # @api private
567
- def initialize(view, cmd, cmdsize, name, timestamp, current_version,
568
- compatibility_version)
569
- super(view, cmd, cmdsize)
570
- @name = LCStr.new(self, name)
571
- @timestamp = timestamp
572
- @current_version = current_version
573
- @compatibility_version = compatibility_version
574
- end
527
+ field :compatibility_version, :uint32
575
528
 
576
529
  # @param context [SerializationContext]
577
530
  # the context
578
531
  # @return [String] the serialized fields of the load command
579
532
  # @api private
580
533
  def serialize(context)
581
- format = Utils.specialize_format(FORMAT, context.endianness)
582
- string_payload, string_offsets = Utils.pack_strings(SIZEOF,
534
+ format = Utils.specialize_format(self.class.format, context.endianness)
535
+ string_payload, string_offsets = Utils.pack_strings(self.class.bytesize,
583
536
  context.alignment,
584
537
  :name => name.to_s)
585
- cmdsize = SIZEOF + string_payload.bytesize
538
+ cmdsize = self.class.bytesize + string_payload.bytesize
586
539
  [cmd, cmdsize, string_offsets[:name], timestamp, current_version,
587
540
  compatibility_version].pack(format) + string_payload
588
541
  end
@@ -604,32 +557,18 @@ module MachO
604
557
  class DylinkerCommand < LoadCommand
605
558
  # @return [LCStr] the dynamic linker's
606
559
  # path name as an LCStr
607
- attr_reader :name
608
-
609
- # @see MachOStructure::FORMAT
610
- # @api private
611
- FORMAT = "L=3"
612
-
613
- # @see MachOStructure::SIZEOF
614
- # @api private
615
- SIZEOF = 12
616
-
617
- # @api private
618
- def initialize(view, cmd, cmdsize, name)
619
- super(view, cmd, cmdsize)
620
- @name = LCStr.new(self, name)
621
- end
560
+ field :name, :lcstr, :to_s => true
622
561
 
623
562
  # @param context [SerializationContext]
624
563
  # the context
625
564
  # @return [String] the serialized fields of the load command
626
565
  # @api private
627
566
  def serialize(context)
628
- format = Utils.specialize_format(FORMAT, context.endianness)
629
- string_payload, string_offsets = Utils.pack_strings(SIZEOF,
567
+ format = Utils.specialize_format(self.class.format, context.endianness)
568
+ string_payload, string_offsets = Utils.pack_strings(self.class.bytesize,
630
569
  context.alignment,
631
570
  :name => name.to_s)
632
- cmdsize = SIZEOF + string_payload.bytesize
571
+ cmdsize = self.class.bytesize + string_payload.bytesize
633
572
  [cmd, cmdsize, string_offsets[:name]].pack(format) + string_payload
634
573
  end
635
574
 
@@ -646,29 +585,13 @@ module MachO
646
585
  class PreboundDylibCommand < LoadCommand
647
586
  # @return [LCStr] the library's path
648
587
  # name as an LCStr
649
- attr_reader :name
588
+ field :name, :lcstr, :to_s => true
650
589
 
651
590
  # @return [Integer] the number of modules in the library
652
- attr_reader :nmodules
591
+ field :nmodules, :uint32
653
592
 
654
593
  # @return [Integer] a bit vector of linked modules
655
- attr_reader :linked_modules
656
-
657
- # @see MachOStructure::FORMAT
658
- # @api private
659
- FORMAT = "L=5"
660
-
661
- # @see MachOStructure::SIZEOF
662
- # @api private
663
- SIZEOF = 20
664
-
665
- # @api private
666
- def initialize(view, cmd, cmdsize, name, nmodules, linked_modules)
667
- super(view, cmd, cmdsize)
668
- @name = LCStr.new(self, name)
669
- @nmodules = nmodules
670
- @linked_modules = linked_modules
671
- end
594
+ field :linked_modules, :uint32
672
595
 
673
596
  # @return [Hash] a hash representation of this {PreboundDylibCommand}
674
597
  def to_h
@@ -684,13 +607,6 @@ module MachO
684
607
  # @note cctools-870 and onwards have all fields of thread_command commented
685
608
  # out except the common ones (cmd, cmdsize)
686
609
  class ThreadCommand < LoadCommand
687
- # @see MachOStructure::FORMAT
688
- # @api private
689
- FORMAT = "L=2"
690
-
691
- # @see MachOStructure::SIZEOF
692
- # @api private
693
- SIZEOF = 8
694
610
  end
695
611
 
696
612
  # A load command containing the address of the dynamic shared library
@@ -698,51 +614,29 @@ module MachO
698
614
  # that defines the routine. Corresponds to LC_ROUTINES.
699
615
  class RoutinesCommand < LoadCommand
700
616
  # @return [Integer] the address of the initialization routine
701
- attr_reader :init_address
617
+ field :init_address, :uint32
702
618
 
703
619
  # @return [Integer] the index into the module table that the init routine
704
620
  # is defined in
705
- attr_reader :init_module
621
+ field :init_module, :uint32
706
622
 
707
623
  # @return [void]
708
- attr_reader :reserved1
624
+ field :reserved1, :uint32
709
625
 
710
626
  # @return [void]
711
- attr_reader :reserved2
627
+ field :reserved2, :uint32
712
628
 
713
629
  # @return [void]
714
- attr_reader :reserved3
630
+ field :reserved3, :uint32
715
631
 
716
632
  # @return [void]
717
- attr_reader :reserved4
633
+ field :reserved4, :uint32
718
634
 
719
635
  # @return [void]
720
- attr_reader :reserved5
636
+ field :reserved5, :uint32
721
637
 
722
638
  # @return [void]
723
- attr_reader :reserved6
724
-
725
- # @see MachOStructure::FORMAT
726
- # @api private
727
- FORMAT = "L=10"
728
-
729
- # @see MachOStructure::SIZEOF
730
- # @api private
731
- SIZEOF = 40
732
-
733
- # @api private
734
- def initialize(view, cmd, cmdsize, init_address, init_module, reserved1,
735
- reserved2, reserved3, reserved4, reserved5, reserved6)
736
- super(view, cmd, cmdsize)
737
- @init_address = init_address
738
- @init_module = init_module
739
- @reserved1 = reserved1
740
- @reserved2 = reserved2
741
- @reserved3 = reserved3
742
- @reserved4 = reserved4
743
- @reserved5 = reserved5
744
- @reserved6 = reserved6
745
- end
639
+ field :reserved6, :uint32
746
640
 
747
641
  # @return [Hash] a hash representation of this {RoutinesCommand}
748
642
  def to_h
@@ -763,34 +657,37 @@ module MachO
763
657
  # initialization routine and an index into the module table for the module
764
658
  # that defines the routine. Corresponds to LC_ROUTINES_64.
765
659
  class RoutinesCommand64 < RoutinesCommand
766
- # @see MachOStructure::FORMAT
767
- # @api private
768
- FORMAT = "L=2Q=8"
660
+ # @return [Integer] the address of the initialization routine
661
+ field :init_address, :uint64
769
662
 
770
- # @see MachOStructure::SIZEOF
771
- # @api private
772
- SIZEOF = 72
663
+ # @return [Integer] the index into the module table that the init routine
664
+ # is defined in
665
+ field :init_module, :uint64
666
+
667
+ # @return [void]
668
+ field :reserved1, :uint64
669
+
670
+ # @return [void]
671
+ field :reserved2, :uint64
672
+
673
+ # @return [void]
674
+ field :reserved3, :uint64
675
+
676
+ # @return [void]
677
+ field :reserved4, :uint64
678
+
679
+ # @return [void]
680
+ field :reserved5, :uint64
681
+
682
+ # @return [void]
683
+ field :reserved6, :uint64
773
684
  end
774
685
 
775
686
  # A load command signifying membership of a subframework containing the name
776
687
  # of an umbrella framework. Corresponds to LC_SUB_FRAMEWORK.
777
688
  class SubFrameworkCommand < LoadCommand
778
689
  # @return [LCStr] the umbrella framework name as an LCStr
779
- attr_reader :umbrella
780
-
781
- # @see MachOStructure::FORMAT
782
- # @api private
783
- FORMAT = "L=3"
784
-
785
- # @see MachOStructure::SIZEOF
786
- # @api private
787
- SIZEOF = 12
788
-
789
- # @api private
790
- def initialize(view, cmd, cmdsize, umbrella)
791
- super(view, cmd, cmdsize)
792
- @umbrella = LCStr.new(self, umbrella)
793
- end
690
+ field :umbrella, :lcstr, :to_s => true
794
691
 
795
692
  # @return [Hash] a hash representation of this {SubFrameworkCommand}
796
693
  def to_h
@@ -804,21 +701,7 @@ module MachO
804
701
  # of an umbrella framework. Corresponds to LC_SUB_UMBRELLA.
805
702
  class SubUmbrellaCommand < LoadCommand
806
703
  # @return [LCStr] the subumbrella framework name as an LCStr
807
- attr_reader :sub_umbrella
808
-
809
- # @see MachOStructure::FORMAT
810
- # @api private
811
- FORMAT = "L=3"
812
-
813
- # @see MachOStructure::SIZEOF
814
- # @api private
815
- SIZEOF = 12
816
-
817
- # @api private
818
- def initialize(view, cmd, cmdsize, sub_umbrella)
819
- super(view, cmd, cmdsize)
820
- @sub_umbrella = LCStr.new(self, sub_umbrella)
821
- end
704
+ field :sub_umbrella, :lcstr, :to_s => true
822
705
 
823
706
  # @return [Hash] a hash representation of this {SubUmbrellaCommand}
824
707
  def to_h
@@ -832,21 +715,7 @@ module MachO
832
715
  # to LC_SUB_LIBRARY.
833
716
  class SubLibraryCommand < LoadCommand
834
717
  # @return [LCStr] the sublibrary name as an LCStr
835
- attr_reader :sub_library
836
-
837
- # @see MachOStructure::FORMAT
838
- # @api private
839
- FORMAT = "L=3"
840
-
841
- # @see MachOStructure::SIZEOF
842
- # @api private
843
- SIZEOF = 12
844
-
845
- # @api private
846
- def initialize(view, cmd, cmdsize, sub_library)
847
- super(view, cmd, cmdsize)
848
- @sub_library = LCStr.new(self, sub_library)
849
- end
718
+ field :sub_library, :lcstr, :to_s => true
850
719
 
851
720
  # @return [Hash] a hash representation of this {SubLibraryCommand}
852
721
  def to_h
@@ -860,21 +729,7 @@ module MachO
860
729
  # an umbrella framework. Corresponds to LC_SUB_CLIENT.
861
730
  class SubClientCommand < LoadCommand
862
731
  # @return [LCStr] the subclient name as an LCStr
863
- attr_reader :sub_client
864
-
865
- # @see MachOStructure::FORMAT
866
- # @api private
867
- FORMAT = "L=3"
868
-
869
- # @see MachOStructure::SIZEOF
870
- # @api private
871
- SIZEOF = 12
872
-
873
- # @api private
874
- def initialize(view, cmd, cmdsize, sub_client)
875
- super(view, cmd, cmdsize)
876
- @sub_client = LCStr.new(self, sub_client)
877
- end
732
+ field :sub_client, :lcstr, :to_s => true
878
733
 
879
734
  # @return [Hash] a hash representation of this {SubClientCommand}
880
735
  def to_h
@@ -888,33 +743,16 @@ module MachO
888
743
  # "stab" style symbol table information. Corresponds to LC_SYMTAB.
889
744
  class SymtabCommand < LoadCommand
890
745
  # @return [Integer] the symbol table's offset
891
- attr_reader :symoff
746
+ field :symoff, :uint32
892
747
 
893
748
  # @return [Integer] the number of symbol table entries
894
- attr_reader :nsyms
749
+ field :nsyms, :uint32
895
750
 
896
751
  # @return [Integer] the string table's offset
897
- attr_reader :stroff
752
+ field :stroff, :uint32
898
753
 
899
754
  # @return [Integer] the string table size in bytes
900
- attr_reader :strsize
901
-
902
- # @see MachOStructure::FORMAT
903
- # @api private
904
- FORMAT = "L=6"
905
-
906
- # @see MachOStructure::SIZEOF
907
- # @api private
908
- SIZEOF = 24
909
-
910
- # @api private
911
- def initialize(view, cmd, cmdsize, symoff, nsyms, stroff, strsize)
912
- super(view, cmd, cmdsize)
913
- @symoff = symoff
914
- @nsyms = nsyms
915
- @stroff = stroff
916
- @strsize = strsize
917
- end
755
+ field :strsize, :uint32
918
756
 
919
757
  # @return [Hash] a hash representation of this {SymtabCommand}
920
758
  def to_h
@@ -931,93 +769,58 @@ module MachO
931
769
  # structures used by the dynamic link editor. Corresponds to LC_DYSYMTAB.
932
770
  class DysymtabCommand < LoadCommand
933
771
  # @return [Integer] the index to local symbols
934
- attr_reader :ilocalsym
772
+ field :ilocalsym, :uint32
935
773
 
936
774
  # @return [Integer] the number of local symbols
937
- attr_reader :nlocalsym
775
+ field :nlocalsym, :uint32
938
776
 
939
777
  # @return [Integer] the index to externally defined symbols
940
- attr_reader :iextdefsym
778
+ field :iextdefsym, :uint32
941
779
 
942
780
  # @return [Integer] the number of externally defined symbols
943
- attr_reader :nextdefsym
781
+ field :nextdefsym, :uint32
944
782
 
945
783
  # @return [Integer] the index to undefined symbols
946
- attr_reader :iundefsym
784
+ field :iundefsym, :uint32
947
785
 
948
786
  # @return [Integer] the number of undefined symbols
949
- attr_reader :nundefsym
787
+ field :nundefsym, :uint32
950
788
 
951
789
  # @return [Integer] the file offset to the table of contents
952
- attr_reader :tocoff
790
+ field :tocoff, :uint32
953
791
 
954
792
  # @return [Integer] the number of entries in the table of contents
955
- attr_reader :ntoc
793
+ field :ntoc, :uint32
956
794
 
957
795
  # @return [Integer] the file offset to the module table
958
- attr_reader :modtaboff
796
+ field :modtaboff, :uint32
959
797
 
960
798
  # @return [Integer] the number of entries in the module table
961
- attr_reader :nmodtab
799
+ field :nmodtab, :uint32
962
800
 
963
801
  # @return [Integer] the file offset to the referenced symbol table
964
- attr_reader :extrefsymoff
802
+ field :extrefsymoff, :uint32
965
803
 
966
804
  # @return [Integer] the number of entries in the referenced symbol table
967
- attr_reader :nextrefsyms
805
+ field :nextrefsyms, :uint32
968
806
 
969
807
  # @return [Integer] the file offset to the indirect symbol table
970
- attr_reader :indirectsymoff
808
+ field :indirectsymoff, :uint32
971
809
 
972
810
  # @return [Integer] the number of entries in the indirect symbol table
973
- attr_reader :nindirectsyms
811
+ field :nindirectsyms, :uint32
974
812
 
975
813
  # @return [Integer] the file offset to the external relocation entries
976
- attr_reader :extreloff
814
+ field :extreloff, :uint32
977
815
 
978
816
  # @return [Integer] the number of external relocation entries
979
- attr_reader :nextrel
817
+ field :nextrel, :uint32
980
818
 
981
819
  # @return [Integer] the file offset to the local relocation entries
982
- attr_reader :locreloff
820
+ field :locreloff, :uint32
983
821
 
984
822
  # @return [Integer] the number of local relocation entries
985
- attr_reader :nlocrel
986
-
987
- # @see MachOStructure::FORMAT
988
- # @api private
989
- FORMAT = "L=20"
990
-
991
- # @see MachOStructure::SIZEOF
992
- # @api private
993
- SIZEOF = 80
994
-
995
- # ugh
996
- # @api private
997
- def initialize(view, cmd, cmdsize, ilocalsym, nlocalsym, iextdefsym,
998
- nextdefsym, iundefsym, nundefsym, tocoff, ntoc, modtaboff,
999
- nmodtab, extrefsymoff, nextrefsyms, indirectsymoff,
1000
- nindirectsyms, extreloff, nextrel, locreloff, nlocrel)
1001
- super(view, cmd, cmdsize)
1002
- @ilocalsym = ilocalsym
1003
- @nlocalsym = nlocalsym
1004
- @iextdefsym = iextdefsym
1005
- @nextdefsym = nextdefsym
1006
- @iundefsym = iundefsym
1007
- @nundefsym = nundefsym
1008
- @tocoff = tocoff
1009
- @ntoc = ntoc
1010
- @modtaboff = modtaboff
1011
- @nmodtab = nmodtab
1012
- @extrefsymoff = extrefsymoff
1013
- @nextrefsyms = nextrefsyms
1014
- @indirectsymoff = indirectsymoff
1015
- @nindirectsyms = nindirectsyms
1016
- @extreloff = extreloff
1017
- @nextrel = nextrel
1018
- @locreloff = locreloff
1019
- @nlocrel = nlocrel
1020
- end
823
+ field :nlocrel, :uint32
1021
824
 
1022
825
  # @return [Hash] a hash representation of this {DysymtabCommand}
1023
826
  def to_h
@@ -1048,30 +851,14 @@ module MachO
1048
851
  # namespace lookup hints table. Corresponds to LC_TWOLEVEL_HINTS.
1049
852
  class TwolevelHintsCommand < LoadCommand
1050
853
  # @return [Integer] the offset to the hint table
1051
- attr_reader :htoffset
854
+ field :htoffset, :uint32
1052
855
 
1053
856
  # @return [Integer] the number of hints in the hint table
1054
- attr_reader :nhints
857
+ field :nhints, :uint32
1055
858
 
1056
859
  # @return [TwolevelHintsTable]
1057
860
  # the hint table
1058
- attr_reader :table
1059
-
1060
- # @see MachOStructure::FORMAT
1061
- # @api private
1062
- FORMAT = "L=4"
1063
-
1064
- # @see MachOStructure::SIZEOF
1065
- # @api private
1066
- SIZEOF = 16
1067
-
1068
- # @api private
1069
- def initialize(view, cmd, cmdsize, htoffset, nhints)
1070
- super(view, cmd, cmdsize)
1071
- @htoffset = htoffset
1072
- @nhints = nhints
1073
- @table = TwolevelHintsTable.new(view, htoffset, nhints)
1074
- end
861
+ field :table, :two_level_hints_table
1075
862
 
1076
863
  # @return [Hash] a hash representation of this {TwolevelHintsCommand}
1077
864
  def to_h
@@ -1130,21 +917,7 @@ module MachO
1130
917
  # files, or zero. Corresponds to LC_PREBIND_CKSUM.
1131
918
  class PrebindCksumCommand < LoadCommand
1132
919
  # @return [Integer] the checksum or 0
1133
- attr_reader :cksum
1134
-
1135
- # @see MachOStructure::FORMAT
1136
- # @api private
1137
- FORMAT = "L=3"
1138
-
1139
- # @see MachOStructure::SIZEOF
1140
- # @api private
1141
- SIZEOF = 12
1142
-
1143
- # @api private
1144
- def initialize(view, cmd, cmdsize, cksum)
1145
- super(view, cmd, cmdsize)
1146
- @cksum = cksum
1147
- end
920
+ field :cksum, :uint32
1148
921
 
1149
922
  # @return [Hash] a hash representation of this {PrebindCksumCommand}
1150
923
  def to_h
@@ -1159,31 +932,17 @@ module MachO
1159
932
  # Corresponds to LC_RPATH.
1160
933
  class RpathCommand < LoadCommand
1161
934
  # @return [LCStr] the path to add to the run path as an LCStr
1162
- attr_reader :path
1163
-
1164
- # @see MachOStructure::FORMAT
1165
- # @api private
1166
- FORMAT = "L=3"
1167
-
1168
- # @see MachOStructure::SIZEOF
1169
- # @api private
1170
- SIZEOF = 12
1171
-
1172
- # @api private
1173
- def initialize(view, cmd, cmdsize, path)
1174
- super(view, cmd, cmdsize)
1175
- @path = LCStr.new(self, path)
1176
- end
935
+ field :path, :lcstr, :to_s => true
1177
936
 
1178
937
  # @param context [SerializationContext] the context
1179
938
  # @return [String] the serialized fields of the load command
1180
939
  # @api private
1181
940
  def serialize(context)
1182
- format = Utils.specialize_format(FORMAT, context.endianness)
1183
- string_payload, string_offsets = Utils.pack_strings(SIZEOF,
941
+ format = Utils.specialize_format(self.class.format, context.endianness)
942
+ string_payload, string_offsets = Utils.pack_strings(self.class.bytesize,
1184
943
  context.alignment,
1185
944
  :path => path.to_s)
1186
- cmdsize = SIZEOF + string_payload.bytesize
945
+ cmdsize = self.class.bytesize + string_payload.bytesize
1187
946
  [cmd, cmdsize, string_offsets[:path]].pack(format) + string_payload
1188
947
  end
1189
948
 
@@ -1202,25 +961,10 @@ module MachO
1202
961
  # or LC_DYLD_CHAINED_FIXUPS.
1203
962
  class LinkeditDataCommand < LoadCommand
1204
963
  # @return [Integer] offset to the data in the __LINKEDIT segment
1205
- attr_reader :dataoff
964
+ field :dataoff, :uint32
1206
965
 
1207
966
  # @return [Integer] size of the data in the __LINKEDIT segment
1208
- attr_reader :datasize
1209
-
1210
- # @see MachOStructure::FORMAT
1211
- # @api private
1212
- FORMAT = "L=4"
1213
-
1214
- # @see MachOStructure::SIZEOF
1215
- # @api private
1216
- SIZEOF = 16
1217
-
1218
- # @api private
1219
- def initialize(view, cmd, cmdsize, dataoff, datasize)
1220
- super(view, cmd, cmdsize)
1221
- @dataoff = dataoff
1222
- @datasize = datasize
1223
- end
967
+ field :datasize, :uint32
1224
968
 
1225
969
  # @return [Hash] a hash representation of this {LinkeditDataCommand}
1226
970
  def to_h
@@ -1235,29 +979,13 @@ module MachO
1235
979
  # segment. Corresponds to LC_ENCRYPTION_INFO.
1236
980
  class EncryptionInfoCommand < LoadCommand
1237
981
  # @return [Integer] the offset to the encrypted segment
1238
- attr_reader :cryptoff
982
+ field :cryptoff, :uint32
1239
983
 
1240
984
  # @return [Integer] the size of the encrypted segment
1241
- attr_reader :cryptsize
985
+ field :cryptsize, :uint32
1242
986
 
1243
987
  # @return [Integer] the encryption system, or 0 if not encrypted yet
1244
- attr_reader :cryptid
1245
-
1246
- # @see MachOStructure::FORMAT
1247
- # @api private
1248
- FORMAT = "L=5"
1249
-
1250
- # @see MachOStructure::SIZEOF
1251
- # @api private
1252
- SIZEOF = 20
1253
-
1254
- # @api private
1255
- def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid)
1256
- super(view, cmd, cmdsize)
1257
- @cryptoff = cryptoff
1258
- @cryptsize = cryptsize
1259
- @cryptid = cryptid
1260
- end
988
+ field :cryptid, :uint32
1261
989
 
1262
990
  # @return [Hash] a hash representation of this {EncryptionInfoCommand}
1263
991
  def to_h
@@ -1273,21 +1001,7 @@ module MachO
1273
1001
  # segment. Corresponds to LC_ENCRYPTION_INFO_64.
1274
1002
  class EncryptionInfoCommand64 < EncryptionInfoCommand
1275
1003
  # @return [Integer] 64-bit padding value
1276
- attr_reader :pad
1277
-
1278
- # @see MachOStructure::FORMAT
1279
- # @api private
1280
- FORMAT = "L=6"
1281
-
1282
- # @see MachOStructure::SIZEOF
1283
- # @api private
1284
- SIZEOF = 24
1285
-
1286
- # @api private
1287
- def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid, pad)
1288
- super(view, cmd, cmdsize, cryptoff, cryptsize, cryptid)
1289
- @pad = pad
1290
- end
1004
+ field :pad, :uint32
1291
1005
 
1292
1006
  # @return [Hash] a hash representation of this {EncryptionInfoCommand64}
1293
1007
  def to_h
@@ -1302,25 +1016,10 @@ module MachO
1302
1016
  # LC_VERSION_MIN_IPHONEOS.
1303
1017
  class VersionMinCommand < LoadCommand
1304
1018
  # @return [Integer] the version X.Y.Z packed as x16.y8.z8
1305
- attr_reader :version
1019
+ field :version, :uint32
1306
1020
 
1307
1021
  # @return [Integer] the SDK version X.Y.Z packed as x16.y8.z8
1308
- attr_reader :sdk
1309
-
1310
- # @see MachOStructure::FORMAT
1311
- # @api private
1312
- FORMAT = "L=4"
1313
-
1314
- # @see MachOStructure::SIZEOF
1315
- # @api private
1316
- SIZEOF = 16
1317
-
1318
- # @api private
1319
- def initialize(view, cmd, cmdsize, version, sdk)
1320
- super(view, cmd, cmdsize)
1321
- @version = version
1322
- @sdk = sdk
1323
- end
1022
+ field :sdk, :uint32
1324
1023
 
1325
1024
  # A string representation of the binary's minimum OS version.
1326
1025
  # @return [String] a string representing the minimum OS version.
@@ -1360,33 +1059,16 @@ module MachO
1360
1059
  # Corresponds to LC_BUILD_VERSION.
1361
1060
  class BuildVersionCommand < LoadCommand
1362
1061
  # @return [Integer]
1363
- attr_reader :platform
1062
+ field :platform, :uint32
1364
1063
 
1365
1064
  # @return [Integer] the minimum OS version X.Y.Z packed as x16.y8.z8
1366
- attr_reader :minos
1065
+ field :minos, :uint32
1367
1066
 
1368
1067
  # @return [Integer] the SDK version X.Y.Z packed as x16.y8.z8
1369
- attr_reader :sdk
1068
+ field :sdk, :uint32
1370
1069
 
1371
1070
  # @return [ToolEntries] tool entries
1372
- attr_reader :tool_entries
1373
-
1374
- # @see MachOStructure::FORMAT
1375
- # @api private
1376
- FORMAT = "L=6"
1377
-
1378
- # @see MachOStructure::SIZEOF
1379
- # @api private
1380
- SIZEOF = 24
1381
-
1382
- # @api private
1383
- def initialize(view, cmd, cmdsize, platform, minos, sdk, ntools)
1384
- super(view, cmd, cmdsize)
1385
- @platform = platform
1386
- @minos = minos
1387
- @sdk = sdk
1388
- @tool_entries = ToolEntries.new(view, ntools)
1389
- end
1071
+ field :tool_entries, :tool_entries
1390
1072
 
1391
1073
  # A string representation of the binary's minimum OS version.
1392
1074
  # @return [String] a string representing the minimum OS version.
@@ -1471,59 +1153,34 @@ module MachO
1471
1153
  # Corresponds to LC_DYLD_INFO and LC_DYLD_INFO_ONLY.
1472
1154
  class DyldInfoCommand < LoadCommand
1473
1155
  # @return [Integer] the file offset to the rebase information
1474
- attr_reader :rebase_off
1156
+ field :rebase_off, :uint32
1475
1157
 
1476
1158
  # @return [Integer] the size of the rebase information
1477
- attr_reader :rebase_size
1159
+ field :rebase_size, :uint32
1478
1160
 
1479
1161
  # @return [Integer] the file offset to the binding information
1480
- attr_reader :bind_off
1162
+ field :bind_off, :uint32
1481
1163
 
1482
1164
  # @return [Integer] the size of the binding information
1483
- attr_reader :bind_size
1165
+ field :bind_size, :uint32
1484
1166
 
1485
1167
  # @return [Integer] the file offset to the weak binding information
1486
- attr_reader :weak_bind_off
1168
+ field :weak_bind_off, :uint32
1487
1169
 
1488
1170
  # @return [Integer] the size of the weak binding information
1489
- attr_reader :weak_bind_size
1171
+ field :weak_bind_size, :uint32
1490
1172
 
1491
1173
  # @return [Integer] the file offset to the lazy binding information
1492
- attr_reader :lazy_bind_off
1174
+ field :lazy_bind_off, :uint32
1493
1175
 
1494
1176
  # @return [Integer] the size of the lazy binding information
1495
- attr_reader :lazy_bind_size
1177
+ field :lazy_bind_size, :uint32
1496
1178
 
1497
1179
  # @return [Integer] the file offset to the export information
1498
- attr_reader :export_off
1180
+ field :export_off, :uint32
1499
1181
 
1500
1182
  # @return [Integer] the size of the export information
1501
- attr_reader :export_size
1502
-
1503
- # @see MachOStructure::FORMAT
1504
- # @api private
1505
- FORMAT = "L=12"
1506
-
1507
- # @see MachOStructure::SIZEOF
1508
- # @api private
1509
- SIZEOF = 48
1510
-
1511
- # @api private
1512
- def initialize(view, cmd, cmdsize, rebase_off, rebase_size, bind_off,
1513
- bind_size, weak_bind_off, weak_bind_size, lazy_bind_off,
1514
- lazy_bind_size, export_off, export_size)
1515
- super(view, cmd, cmdsize)
1516
- @rebase_off = rebase_off
1517
- @rebase_size = rebase_size
1518
- @bind_off = bind_off
1519
- @bind_size = bind_size
1520
- @weak_bind_off = weak_bind_off
1521
- @weak_bind_size = weak_bind_size
1522
- @lazy_bind_off = lazy_bind_off
1523
- @lazy_bind_size = lazy_bind_size
1524
- @export_off = export_off
1525
- @export_size = export_size
1526
- end
1183
+ field :export_size, :uint32
1527
1184
 
1528
1185
  # @return [Hash] a hash representation of this {DyldInfoCommand}
1529
1186
  def to_h
@@ -1546,21 +1203,7 @@ module MachO
1546
1203
  # Corresponds to LC_LINKER_OPTION.
1547
1204
  class LinkerOptionCommand < LoadCommand
1548
1205
  # @return [Integer] the number of strings
1549
- attr_reader :count
1550
-
1551
- # @see MachOStructure::FORMAT
1552
- # @api private
1553
- FORMAT = "L=3"
1554
-
1555
- # @see MachOStructure::SIZEOF
1556
- # @api private
1557
- SIZEOF = 12
1558
-
1559
- # @api private
1560
- def initialize(view, cmd, cmdsize, count)
1561
- super(view, cmd, cmdsize)
1562
- @count = count
1563
- end
1206
+ field :count, :uint32
1564
1207
 
1565
1208
  # @return [Hash] a hash representation of this {LinkerOptionCommand}
1566
1209
  def to_h
@@ -1573,25 +1216,10 @@ module MachO
1573
1216
  # A load command specifying the offset of main(). Corresponds to LC_MAIN.
1574
1217
  class EntryPointCommand < LoadCommand
1575
1218
  # @return [Integer] the file (__TEXT) offset of main()
1576
- attr_reader :entryoff
1219
+ field :entryoff, :uint64
1577
1220
 
1578
1221
  # @return [Integer] if not 0, the initial stack size.
1579
- attr_reader :stacksize
1580
-
1581
- # @see MachOStructure::FORMAT
1582
- # @api private
1583
- FORMAT = "L=2Q=2"
1584
-
1585
- # @see MachOStructure::SIZEOF
1586
- # @api private
1587
- SIZEOF = 24
1588
-
1589
- # @api private
1590
- def initialize(view, cmd, cmdsize, entryoff, stacksize)
1591
- super(view, cmd, cmdsize)
1592
- @entryoff = entryoff
1593
- @stacksize = stacksize
1594
- end
1222
+ field :stacksize, :uint64
1595
1223
 
1596
1224
  # @return [Hash] a hash representation of this {EntryPointCommand}
1597
1225
  def to_h
@@ -1606,21 +1234,7 @@ module MachO
1606
1234
  # binary. Corresponds to LC_SOURCE_VERSION.
1607
1235
  class SourceVersionCommand < LoadCommand
1608
1236
  # @return [Integer] the version packed as a24.b10.c10.d10.e10
1609
- attr_reader :version
1610
-
1611
- # @see MachOStructure::FORMAT
1612
- # @api private
1613
- FORMAT = "L=2Q=1"
1614
-
1615
- # @see MachOStructure::SIZEOF
1616
- # @api private
1617
- SIZEOF = 16
1618
-
1619
- # @api private
1620
- def initialize(view, cmd, cmdsize, version)
1621
- super(view, cmd, cmdsize)
1622
- @version = version
1623
- end
1237
+ field :version, :uint64
1624
1238
 
1625
1239
  # A string representation of the sources used to build the binary.
1626
1240
  # @return [String] a string representation of the version
@@ -1647,25 +1261,10 @@ module MachO
1647
1261
  # symbol table information. Corresponds to LC_SYMSEG.
1648
1262
  class SymsegCommand < LoadCommand
1649
1263
  # @return [Integer] the offset to the symbol segment
1650
- attr_reader :offset
1264
+ field :offset, :uint32
1651
1265
 
1652
1266
  # @return [Integer] the size of the symbol segment in bytes
1653
- attr_reader :size
1654
-
1655
- # @see MachOStructure::FORMAT
1656
- # @api private
1657
- FORMAT = "L=4"
1658
-
1659
- # @see MachOStructure::SIZEOF
1660
- # @api private
1661
- SIZEOF = 16
1662
-
1663
- # @api private
1664
- def initialize(view, cmd, cmdsize, offset, size)
1665
- super(view, cmd, cmdsize)
1666
- @offset = offset
1667
- @size = size
1668
- end
1267
+ field :size, :uint32
1669
1268
 
1670
1269
  # @return [Hash] a hash representation of this {SymsegCommand}
1671
1270
  def to_h
@@ -1680,37 +1279,16 @@ module MachO
1680
1279
  # string is null-terminated and the command is zero-padded to a multiple of
1681
1280
  # 4. Corresponds to LC_IDENT.
1682
1281
  class IdentCommand < LoadCommand
1683
- # @see MachOStructure::FORMAT
1684
- # @api private
1685
- FORMAT = "L=2"
1686
-
1687
- # @see MachOStructure::SIZEOF
1688
- # @api private
1689
- SIZEOF = 8
1690
1282
  end
1691
1283
 
1692
1284
  # An obsolete load command containing the path to a file to be loaded into
1693
1285
  # memory. Corresponds to LC_FVMFILE.
1694
1286
  class FvmfileCommand < LoadCommand
1695
1287
  # @return [LCStr] the pathname of the file being loaded
1696
- attr_reader :name
1288
+ field :name, :lcstr, :to_s => true
1697
1289
 
1698
1290
  # @return [Integer] the virtual address being loaded at
1699
- attr_reader :header_addr
1700
-
1701
- # @see MachOStructure::FORMAT
1702
- # @api private
1703
- FORMAT = "L=4"
1704
-
1705
- # @see MachOStructure::SIZEOF
1706
- # @api private
1707
- SIZEOF = 16
1708
-
1709
- def initialize(view, cmd, cmdsize, name, header_addr)
1710
- super(view, cmd, cmdsize)
1711
- @name = LCStr.new(self, name)
1712
- @header_addr = header_addr
1713
- end
1291
+ field :header_addr, :uint32
1714
1292
 
1715
1293
  # @return [Hash] a hash representation of this {FvmfileCommand}
1716
1294
  def to_h
@@ -1725,28 +1303,13 @@ module MachO
1725
1303
  # into memory. Corresponds to LC_LOADFVMLIB and LC_IDFVMLIB.
1726
1304
  class FvmlibCommand < LoadCommand
1727
1305
  # @return [LCStr] the library's target pathname
1728
- attr_reader :name
1306
+ field :name, :lcstr, :to_s => true
1729
1307
 
1730
1308
  # @return [Integer] the library's minor version number
1731
- attr_reader :minor_version
1309
+ field :minor_version, :uint32
1732
1310
 
1733
1311
  # @return [Integer] the library's header address
1734
- attr_reader :header_addr
1735
-
1736
- # @see MachOStructure::FORMAT
1737
- # @api private
1738
- FORMAT = "L=5"
1739
-
1740
- # @see MachOStructure::SIZEOF
1741
- # @api private
1742
- SIZEOF = 20
1743
-
1744
- def initialize(view, cmd, cmdsize, name, minor_version, header_addr)
1745
- super(view, cmd, cmdsize)
1746
- @name = LCStr.new(self, name)
1747
- @minor_version = minor_version
1748
- @header_addr = header_addr
1749
- end
1312
+ field :header_addr, :uint32
1750
1313
 
1751
1314
  # @return [Hash] a hash representation of this {FvmlibCommand}
1752
1315
  def to_h
@@ -1762,28 +1325,13 @@ module MachO
1762
1325
  # Corresponds to LC_NOTE.
1763
1326
  class NoteCommand < LoadCommand
1764
1327
  # @return [String] the name of the owner for this note
1765
- attr_reader :data_owner
1328
+ field :data_owner, :string, :padding => :null, :size => 16, :to_s => true
1766
1329
 
1767
1330
  # @return [Integer] the offset, within the file, of the note
1768
- attr_reader :offset
1331
+ field :offset, :uint64
1769
1332
 
1770
1333
  # @return [Integer] the size, in bytes, of the note
1771
- attr_reader :size
1772
-
1773
- # @see MachOStructure::FORMAT
1774
- # @api private
1775
- FORMAT = "L=2Z16Q=2"
1776
-
1777
- # @see MachOStructure::SIZEOF
1778
- # @api private
1779
- SIZEOF = 48
1780
-
1781
- def initialize(view, cmd, cmdsize, data_owner, offset, size)
1782
- super(view, cmd, cmdsize)
1783
- @data_owner = data_owner
1784
- @offset = offset
1785
- @size = size
1786
- end
1334
+ field :size, :uint64
1787
1335
 
1788
1336
  # @return [Hash] a hash representation of this {NoteCommand}
1789
1337
  def to_h
@@ -1794,5 +1342,37 @@ module MachO
1794
1342
  }.merge super
1795
1343
  end
1796
1344
  end
1345
+
1346
+ # A load command containing a description of a Mach-O that is a constituent of a fileset.
1347
+ # Each entry is further described by its own Mach header.
1348
+ # Corresponds to LC_FILESET_ENTRY.
1349
+ class FilesetEntryCommand < LoadCommand
1350
+ # @return [Integer] the virtual memory address of the entry
1351
+ field :vmaddr, :uint64
1352
+
1353
+ # @return [Integer] the file offset of the entry
1354
+ field :fileoff, :uint64
1355
+
1356
+ # @return [LCStr] the entry's ID
1357
+ field :entry_id, :lcstr, :to_s => true
1358
+
1359
+ # @return [void]
1360
+ field :reserved, :uint32
1361
+
1362
+ # @return [Hash] a hash representation of this {FilesetEntryCommand}
1363
+ def to_h
1364
+ {
1365
+ "vmaddr" => vmaddr,
1366
+ "fileoff" => fileoff,
1367
+ "entry_id" => entry_id,
1368
+ "reserved" => reserved,
1369
+ }.merge super
1370
+ end
1371
+
1372
+ # @return [SegmentCommand64, nil] the matching segment command or nil if nothing matches
1373
+ def segment
1374
+ view.macho_file.command(:LC_SEGMENT_64).select { |cmd| cmd.fileoff == fileoff }.first
1375
+ end
1376
+ end
1797
1377
  end
1798
1378
  end