ruby-macho 4.1.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf1e87b27661d19099f8a7160c774dab716e37be7dec050f84c701e9fc6c1ea6
4
- data.tar.gz: 18d7705d4204bd10bd593b7ab8759058d2cea94eadeed9d7edce06b96d303a9b
3
+ metadata.gz: 848be7615c0a26614ffc950ffd7a70b3efe594a4c2608aeb776d2f7a0fca472d
4
+ data.tar.gz: e8e084691a090ddd084196567ee80848b2cb546f9bff70ec9d43b8a8a45b0cef
5
5
  SHA512:
6
- metadata.gz: 0c6007d3ef6a175bf58c6b900a42aacdfd557d1f283f3e144828c25a3207f4791ef031c3313ace7a4f807b62ecf05ffb7944ca39d746d6446d23d20c0c4a6166
7
- data.tar.gz: d7345efc2941999717f803ae9740067ee4a53cec738fd44c0ea5cee610f1b7d28bac8bf572f5558ff02f63a590ce323f024b9e2fd6e55977fc521dcb39ca2c03
6
+ metadata.gz: 2117ef6313e528a636b43b5c45c17729627cfae074957c6bfc7486040daf4c10b3f6ce74dc48a72a8375821f77de34d723c6c586eda27a5d0cc71d47a33cc42b
7
+ data.tar.gz: cc3a7f948e6d9f6ae71b7f0f96eef0945d5269c8e59ab09239a61ce8f8564c9faa8b4484940907dc6bb299435f54d9a1c5b89714c692b15a048b0c0c49f6f955
data/README.md CHANGED
@@ -3,7 +3,7 @@ ruby-macho
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/ruby-macho.svg)](http://badge.fury.io/rb/ruby-macho)
5
5
  [![CI](https://github.com/Homebrew/ruby-macho/actions/workflows/tests.yml/badge.svg)](https://github.com/Homebrew/ruby-macho/actions/workflows/tests.yml)
6
- [![Coverage Status](https://codecov.io/gh/Homebrew/ruby-macho/branch/master/graph/badge.svg)](https://codecov.io/gh/Homebrew/ruby-macho)
6
+ [![Coverage Status](https://codecov.io/gh/Homebrew/ruby-macho/branch/main/graph/badge.svg)](https://codecov.io/gh/Homebrew/ruby-macho)
7
7
 
8
8
  A Ruby library for examining and modifying Mach-O files.
9
9
 
@@ -37,7 +37,7 @@ module MachO
37
37
  # Raised when a file is too short to be a valid Mach-O file.
38
38
  class TruncatedFileError < NotAMachOError
39
39
  def initialize
40
- super "File is too short to be a valid Mach-O"
40
+ super("File is too short to be a valid Mach-O")
41
41
  end
42
42
  end
43
43
 
@@ -45,21 +45,21 @@ module MachO
45
45
  class MagicError < NotAMachOError
46
46
  # @param num [Integer] the unknown number
47
47
  def initialize(magic)
48
- super "Unrecognized Mach-O magic: 0x%02<magic>x" % { :magic => magic }
48
+ super("Unrecognized Mach-O magic: 0x%02<magic>x" % { :magic => magic })
49
49
  end
50
50
  end
51
51
 
52
52
  # Raised when a file is a Java classfile instead of a fat Mach-O.
53
53
  class JavaClassFileError < NotAMachOError
54
54
  def initialize
55
- super "File is a Java class file"
55
+ super("File is a Java class file")
56
56
  end
57
57
  end
58
58
 
59
59
  # Raised when a a fat Mach-O file has zero architectures
60
60
  class ZeroArchitectureError < NotAMachOError
61
61
  def initialize
62
- super "Fat file has zero internal architectures"
62
+ super("Fat file has zero internal architectures")
63
63
  end
64
64
  end
65
65
 
@@ -71,24 +71,24 @@ module MachO
71
71
  # @param cpusubtype_fat [Integer] the CPU subtype in the fat header
72
72
  # @param cputype_macho [Integer] the CPU type in the macho header
73
73
  # @param cpusubtype_macho [Integer] the CPU subtype in the macho header
74
- super ("Mismatch between cputypes >> 0x%08<fat_cputype>x and 0x%08<macho_cputype>x\n" \
75
- "and/or cpusubtypes >> 0x%08<fat_cpusubtype>x and 0x%08<macho_cpusubtype>x" %
76
- { :fat_cputype => fat_cputype, :macho_cputype => macho_cputype,
77
- :fat_cpusubtype => fat_cpusubtype, :macho_cpusubtype => macho_cpusubtype })
74
+ super("Mismatch between cputypes >> 0x%08<fat_cputype>x and 0x%08<macho_cputype>x\n" \
75
+ "and/or cpusubtypes >> 0x%08<fat_cpusubtype>x and 0x%08<macho_cpusubtype>x" %
76
+ { :fat_cputype => fat_cputype, :macho_cputype => macho_cputype,
77
+ :fat_cpusubtype => fat_cpusubtype, :macho_cpusubtype => macho_cpusubtype })
78
78
  end
79
79
  end
80
80
 
81
81
  # Raised when a fat binary is loaded with MachOFile.
82
82
  class FatBinaryError < MachOError
83
83
  def initialize
84
- super "Fat binaries must be loaded with MachO::FatFile"
84
+ super("Fat binaries must be loaded with MachO::FatFile")
85
85
  end
86
86
  end
87
87
 
88
88
  # Raised when a Mach-O is loaded with FatFile.
89
89
  class MachOBinaryError < MachOError
90
90
  def initialize
91
- super "Normal binaries must be loaded with MachO::MachOFile"
91
+ super("Normal binaries must be loaded with MachO::MachOFile")
92
92
  end
93
93
  end
94
94
 
@@ -96,7 +96,7 @@ module MachO
96
96
  class CPUTypeError < MachOError
97
97
  # @param cputype [Integer] the unknown CPU type
98
98
  def initialize(cputype)
99
- super "Unrecognized CPU type: 0x%08<cputype>x" % { :cputype => cputype }
99
+ super("Unrecognized CPU type: 0x%08<cputype>x" % { :cputype => cputype })
100
100
  end
101
101
  end
102
102
 
@@ -105,8 +105,8 @@ module MachO
105
105
  # @param cputype [Integer] the CPU type of the unknown pair
106
106
  # @param cpusubtype [Integer] the CPU sub-type of the unknown pair
107
107
  def initialize(cputype, cpusubtype)
108
- super "Unrecognized CPU sub-type: 0x%08<cpusubtype>x " \
109
- "(for CPU type: 0x%08<cputype>x" % { :cputype => cputype, :cpusubtype => cpusubtype }
108
+ super("Unrecognized CPU sub-type: 0x%08<cpusubtype>x " \
109
+ "(for CPU type: 0x%08<cputype>x" % { :cputype => cputype, :cpusubtype => cpusubtype })
110
110
  end
111
111
  end
112
112
 
@@ -114,7 +114,7 @@ module MachO
114
114
  class FiletypeError < MachOError
115
115
  # @param num [Integer] the unknown number
116
116
  def initialize(num)
117
- super "Unrecognized Mach-O filetype code: 0x%02<num>x" % { :num => num }
117
+ super("Unrecognized Mach-O filetype code: 0x%02<num>x" % { :num => num })
118
118
  end
119
119
  end
120
120
 
@@ -122,7 +122,7 @@ module MachO
122
122
  class LoadCommandError < MachOError
123
123
  # @param num [Integer] the unknown number
124
124
  def initialize(num)
125
- super "Unrecognized Mach-O load command: 0x%02<num>x" % { :num => num }
125
+ super("Unrecognized Mach-O load command: 0x%02<num>x" % { :num => num })
126
126
  end
127
127
  end
128
128
 
@@ -130,7 +130,7 @@ module MachO
130
130
  class LoadCommandNotCreatableError < MachOError
131
131
  # @param cmd_sym [Symbol] the uncreatable load command's symbol
132
132
  def initialize(cmd_sym)
133
- super "Load commands of type #{cmd_sym} cannot be created manually"
133
+ super("Load commands of type #{cmd_sym} cannot be created manually")
134
134
  end
135
135
  end
136
136
 
@@ -141,8 +141,8 @@ module MachO
141
141
  # @param expected_arity [Integer] the number of arguments expected
142
142
  # @param actual_arity [Integer] the number of arguments received
143
143
  def initialize(cmd_sym, expected_arity, actual_arity)
144
- super "Expected #{expected_arity} arguments for #{cmd_sym} creation, " \
145
- "got #{actual_arity}"
144
+ super("Expected #{expected_arity} arguments for #{cmd_sym} creation, " \
145
+ "got #{actual_arity}")
146
146
  end
147
147
  end
148
148
 
@@ -150,7 +150,7 @@ module MachO
150
150
  class LoadCommandNotSerializableError < MachOError
151
151
  # @param cmd_sym [Symbol] the load command's symbol
152
152
  def initialize(cmd_sym)
153
- super "Load commands of type #{cmd_sym} cannot be serialized"
153
+ super("Load commands of type #{cmd_sym} cannot be serialized")
154
154
  end
155
155
  end
156
156
 
@@ -158,8 +158,8 @@ module MachO
158
158
  class LCStrMalformedError < MachOError
159
159
  # @param lc [MachO::LoadCommand] the load command containing the string
160
160
  def initialize(lc)
161
- super "Load command #{lc.type} at offset #{lc.view.offset} contains a " \
162
- "malformed string"
161
+ super("Load command #{lc.type} at offset #{lc.view.offset} contains a " \
162
+ "malformed string")
163
163
  end
164
164
  end
165
165
 
@@ -167,7 +167,7 @@ module MachO
167
167
  class OffsetInsertionError < ModificationError
168
168
  # @param offset [Integer] the invalid offset
169
169
  def initialize(offset)
170
- super "Insertion at offset #{offset} is not valid"
170
+ super("Insertion at offset #{offset} is not valid")
171
171
  end
172
172
  end
173
173
 
@@ -175,9 +175,9 @@ module MachO
175
175
  class HeaderPadError < ModificationError
176
176
  # @param filename [String] the filename
177
177
  def initialize(filename)
178
- super "Updated load commands do not fit in the header of " \
178
+ super("Updated load commands do not fit in the header of " \
179
179
  "#{filename}. #{filename} needs to be relinked, possibly with " \
180
- "-headerpad or -headerpad_max_install_names"
180
+ "-headerpad or -headerpad_max_install_names")
181
181
  end
182
182
  end
183
183
 
@@ -185,14 +185,14 @@ module MachO
185
185
  class DylibUnknownError < RecoverableModificationError
186
186
  # @param dylib [String] the unknown shared library name
187
187
  def initialize(dylib)
188
- super "No such dylib name: #{dylib}"
188
+ super("No such dylib name: #{dylib}")
189
189
  end
190
190
  end
191
191
 
192
192
  # Raised when a dylib is missing an ID
193
193
  class DylibIdMissingError < RecoverableModificationError
194
194
  def initialize
195
- super "Dylib is missing a dylib ID"
195
+ super("Dylib is missing a dylib ID")
196
196
  end
197
197
  end
198
198
 
@@ -200,7 +200,7 @@ module MachO
200
200
  class RpathUnknownError < RecoverableModificationError
201
201
  # @param path [String] the unknown runtime path
202
202
  def initialize(path)
203
- super "No such runtime path: #{path}"
203
+ super("No such runtime path: #{path}")
204
204
  end
205
205
  end
206
206
 
@@ -208,7 +208,7 @@ module MachO
208
208
  class RpathExistsError < RecoverableModificationError
209
209
  # @param path [String] the extant path
210
210
  def initialize(path)
211
- super "#{path} already exists"
211
+ super("#{path} already exists")
212
212
  end
213
213
  end
214
214
 
@@ -216,7 +216,7 @@ module MachO
216
216
  class UnimplementedError < MachOError
217
217
  # @param thing [String] the thing that is unimplemented
218
218
  def initialize(thing)
219
- super "Unimplemented: #{thing}"
219
+ super("Unimplemented: #{thing}")
220
220
  end
221
221
  end
222
222
 
@@ -225,8 +225,8 @@ module MachO
225
225
  class FatArchOffsetOverflowError < MachOError
226
226
  # @param offset [Integer] the offending offset
227
227
  def initialize(offset)
228
- super "Offset #{offset} exceeds the 32-bit width of a fat_arch offset. " \
229
- "Consider merging with `fat64: true`"
228
+ super("Offset #{offset} exceeds the 32-bit width of a fat_arch offset. " \
229
+ "Consider merging with `fat64: true`")
230
230
  end
231
231
  end
232
232
 
data/lib/macho/headers.rb CHANGED
@@ -60,14 +60,14 @@ module MachO
60
60
  MH_CIGAM_64 => "MH_CIGAM_64",
61
61
  }.freeze
62
62
 
63
- # mask for CPUs with 64-bit architectures (when running a 64-bit ABI?)
63
+ # mask for 64-bit CPU architectures with 64-bit types
64
64
  # @api private
65
65
  CPU_ARCH_ABI64 = 0x01000000
66
66
 
67
- # mask for CPUs with 64-bit architectures (when running a 32-bit ABI?)
67
+ # mask for 64-bit CPU architectures with 32-bit types (ILP32)
68
68
  # @see https://github.com/Homebrew/ruby-macho/issues/113
69
69
  # @api private
70
- CPU_ARCH_ABI32 = 0x02000000
70
+ CPU_ARCH_ABI64_32 = 0x02000000
71
71
 
72
72
  # any CPU (unused?)
73
73
  # @api private
@@ -97,9 +97,10 @@ module MachO
97
97
  # @api private
98
98
  CPU_TYPE_ARM64 = (CPU_TYPE_ARM | CPU_ARCH_ABI64)
99
99
 
100
- # 64-bit ARM compatible CPUs (running in 32-bit mode?)
100
+ # 64-bit ARM compatible CPUs (with 32-bit types)
101
101
  # @see https://github.com/Homebrew/ruby-macho/issues/113
102
- CPU_TYPE_ARM64_32 = (CPU_TYPE_ARM | CPU_ARCH_ABI32)
102
+ # @api private
103
+ CPU_TYPE_ARM64_32 = (CPU_TYPE_ARM | CPU_ARCH_ABI64_32)
103
104
 
104
105
  # PowerPC compatible CPUs
105
106
  # @api private
@@ -450,6 +451,14 @@ module MachO
450
451
  # @api private
451
452
  MH_FILESET = 0xc
452
453
 
454
+ # gpu program
455
+ # @api private
456
+ MH_GPU_EXECUTE = 0xd
457
+
458
+ # gpu support functions
459
+ # @api private
460
+ MH_GPU_DYLIB = 0xe
461
+
453
462
  # association of filetypes to Symbol representations
454
463
  # @api private
455
464
  MH_FILETYPES = {
@@ -465,6 +474,8 @@ module MachO
465
474
  MH_DSYM => :dsym,
466
475
  MH_KEXT_BUNDLE => :kext_bundle,
467
476
  MH_FILESET => :fileset,
477
+ MH_GPU_EXECUTE => :gpu_execute,
478
+ MH_GPU_DYLIB => :gpu_dylib,
468
479
  }.freeze
469
480
 
470
481
  # association of mach header flag symbols to values
@@ -480,7 +491,7 @@ module MachO
480
491
  :MH_TWOLEVEL => 0x80,
481
492
  :MH_FORCE_FLAT => 0x100,
482
493
  :MH_NOMULTIDEFS => 0x200,
483
- :MH_NOPREFIXBINDING => 0x400,
494
+ :MH_NOFIXPREBINDING => 0x400,
484
495
  :MH_PREBINDABLE => 0x800,
485
496
  :MH_ALLMODSBOUND => 0x1000,
486
497
  :MH_SUBSECTIONS_VIA_SYMBOLS => 0x2000,
@@ -495,9 +506,10 @@ module MachO
495
506
  :MH_DEAD_STRIPPABLE_DYLIB => 0x400000,
496
507
  :MH_HAS_TLV_DESCRIPTORS => 0x800000,
497
508
  :MH_NO_HEAP_EXECUTION => 0x1000000,
498
- :MH_APP_EXTENSION_SAFE => 0x02000000,
499
- :MH_NLIST_OUTOFSYNC_WITH_DYLDINFO => 0x04000000,
500
- :MH_SIM_SUPPORT => 0x08000000,
509
+ :MH_APP_EXTENSION_SAFE => 0x2000000,
510
+ :MH_NLIST_OUTOFSYNC_WITH_DYLDINFO => 0x4000000,
511
+ :MH_SIM_SUPPORT => 0x8000000,
512
+ :MH_IMPLICIT_PAGEZERO => 0x10000000,
501
513
  :MH_DYLIB_IN_CACHE => 0x80000000,
502
514
  }.freeze
503
515
 
@@ -66,6 +66,9 @@ module MachO
66
66
  (LC_REQ_DYLD | 0x34) => :LC_DYLD_CHAINED_FIXUPS,
67
67
  (LC_REQ_DYLD | 0x35) => :LC_FILESET_ENTRY,
68
68
  0x36 => :LC_ATOM_INFO,
69
+ 0x37 => :LC_FUNCTION_VARIANTS,
70
+ 0x38 => :LC_FUNCTION_VARIANT_FIXUPS,
71
+ 0x39 => :LC_TARGET_TRIPLE,
69
72
  }.freeze
70
73
 
71
74
  # association of symbol representations to load command constants
@@ -155,6 +158,9 @@ module MachO
155
158
  :LC_DYLD_CHAINED_FIXUPS => "LinkeditDataCommand",
156
159
  :LC_FILESET_ENTRY => "FilesetEntryCommand",
157
160
  :LC_ATOM_INFO => "LinkeditDataCommand",
161
+ :LC_FUNCTION_VARIANTS => "LinkeditDataCommand",
162
+ :LC_FUNCTION_VARIANT_FIXUPS => "LinkeditDataCommand",
163
+ :LC_TARGET_TRIPLE => "TargetTripleCommand",
158
164
  }.freeze
159
165
 
160
166
  # association of segment name symbols to names
@@ -488,7 +494,7 @@ module MachO
488
494
  align = 0
489
495
  segalign = 1
490
496
 
491
- while (segalign & vmaddr).zero?
497
+ while segalign.nobits?(vmaddr)
492
498
  segalign <<= 1
493
499
  align += 1
494
500
  end
@@ -610,7 +616,7 @@ module MachO
610
616
 
611
617
  if dylib_command.timestamp == DYLIB_USE_MARKER &&
612
618
  dylib_command.name.to_i == DylibUseCommand.bytesize
613
- super(view)
619
+ super
614
620
  else
615
621
  dylib_command
616
622
  end
@@ -1053,11 +1059,26 @@ module MachO
1053
1059
  end
1054
1060
  end
1055
1061
 
1062
+ # A load command containing the target triple used when compiling the binary.
1063
+ # Corresponds to LC_TARGET_TRIPLE.
1064
+ class TargetTripleCommand < LoadCommand
1065
+ # @return [LCStr] the target triple used when compiling the binary
1066
+ field :triple, :lcstr, :to_s => true
1067
+
1068
+ # @return [Hash] a hash representation of this {TargetTripleCommand}
1069
+ def to_h
1070
+ {
1071
+ "triple" => triple.to_h,
1072
+ }.merge super
1073
+ end
1074
+ end
1075
+
1056
1076
  # A load command representing the offsets and sizes of a blob of data in
1057
1077
  # the __LINKEDIT segment. Corresponds to LC_CODE_SIGNATURE,
1058
1078
  # LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE,
1059
1079
  # LC_DYLIB_CODE_SIGN_DRS, LC_LINKER_OPTIMIZATION_HINT, LC_DYLD_EXPORTS_TRIE,
1060
- # LC_DYLD_CHAINED_FIXUPS, or LC_ATOM_INFO.
1080
+ # LC_DYLD_CHAINED_FIXUPS, LC_ATOM_INFO, LC_FUNCTION_VARIANTS,
1081
+ # or LC_FUNCTION_VARIANT_FIXUPS.
1061
1082
  class LinkeditDataCommand < LoadCommand
1062
1083
  # @return [Integer] offset to the data in the __LINKEDIT segment
1063
1084
  field :dataoff, :uint32
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MachO
4
- # A general purpose pseudo-structure. Described in detail in docs/machostructure-dsl.md.
4
+ # A general purpose pseudo-structure. Described in detail in machostructure-dsl-docs.md.
5
5
  # @abstract
6
6
  class MachOStructure
7
7
  # Constants used for parsing MachOStructure fields
data/lib/macho.rb CHANGED
@@ -16,7 +16,7 @@ require_relative "macho/tools"
16
16
  # The primary namespace for ruby-macho.
17
17
  module MachO
18
18
  # release version
19
- VERSION = "4.1.0"
19
+ VERSION = "5.0.0"
20
20
 
21
21
  # Opens the given filename as a MachOFile or FatFile, depending on its magic.
22
22
  # @param filename [String] the file being opened
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-macho
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Woodruff
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-06-11 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: A library for viewing and manipulating Mach-O files in Ruby.
14
13
  email: william@yossarian.net
@@ -35,7 +34,7 @@ licenses:
35
34
  - MIT
36
35
  metadata:
37
36
  rubygems_mfa_required: 'true'
38
- post_install_message:
37
+ funding_uri: https://github.com/sponsors/Homebrew
39
38
  rdoc_options: []
40
39
  require_paths:
41
40
  - lib
@@ -43,15 +42,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
43
42
  requirements:
44
43
  - - ">="
45
44
  - !ruby/object:Gem::Version
46
- version: '2.6'
45
+ version: '3.2'
47
46
  required_rubygems_version: !ruby/object:Gem::Requirement
48
47
  requirements:
49
48
  - - ">="
50
49
  - !ruby/object:Gem::Version
51
50
  version: '0'
52
51
  requirements: []
53
- rubygems_version: 3.4.10
54
- signing_key:
52
+ rubygems_version: 4.0.3
55
53
  specification_version: 4
56
54
  summary: ruby-macho - Mach-O file analyzer.
57
55
  test_files: []