-
-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathexceptions.rb
More file actions
258 lines (225 loc) · 8.62 KB
/
exceptions.rb
File metadata and controls
258 lines (225 loc) · 8.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# frozen_string_literal: true
module MachO
# A generic Mach-O error in execution.
class MachOError < RuntimeError
end
# Raised when a Mach-O file modification fails.
class ModificationError < MachOError
end
# Raised when codesigning fails. Certain environments
# may want to rescue this to treat it as non-fatal.
class CodeSigningError < MachOError
end
# Raised when a Mach-O file modification fails but can be recovered when
# operating on multiple Mach-O slices of a fat binary in non-strict mode.
class RecoverableModificationError < ModificationError
# @return [Integer, nil] The index of the Mach-O slice of a fat binary for
# which modification failed or `nil` if not a fat binary. This is used to
# make the error message more useful.
attr_accessor :macho_slice
# @return [String] The exception message.
def to_s
s = super.to_s
s = "While modifying Mach-O slice #{@macho_slice}: #{s}" if @macho_slice
s
end
end
# Raised when a file is not a Mach-O.
class NotAMachOError < MachOError
end
# Raised when a file is too short to be a valid Mach-O file.
class TruncatedFileError < NotAMachOError
def initialize
super "File is too short to be a valid Mach-O"
end
end
# Raised when a file's magic bytes are not valid Mach-O magic.
class MagicError < NotAMachOError
# @param num [Integer] the unknown number
def initialize(magic)
super "Unrecognized Mach-O magic: 0x%02<magic>x" % { :magic => magic }
end
end
# Raised when a file is a Java classfile instead of a fat Mach-O.
class JavaClassFileError < NotAMachOError
def initialize
super "File is a Java class file"
end
end
# Raised when a a fat Mach-O file has zero architectures
class ZeroArchitectureError < NotAMachOError
def initialize
super "Fat file has zero internal architectures"
end
end
# Raised when there is a mismatch between the fat arch
# and internal slice cputype or cpusubtype.
class CPUTypeMismatchError < NotAMachOError
def initialize(fat_cputype, fat_cpusubtype, macho_cputype, macho_cpusubtype)
# @param cputype_fat [Integer] the CPU type in the fat header
# @param cpusubtype_fat [Integer] the CPU subtype in the fat header
# @param cputype_macho [Integer] the CPU type in the macho header
# @param cpusubtype_macho [Integer] the CPU subtype in the macho header
super ("Mismatch between cputypes >> 0x%08<fat_cputype>x and 0x%08<macho_cputype>x\n" \
"and/or cpusubtypes >> 0x%08<fat_cpusubtype>x and 0x%08<macho_cpusubtype>x" %
{ :fat_cputype => fat_cputype, :macho_cputype => macho_cputype,
:fat_cpusubtype => fat_cpusubtype, :macho_cpusubtype => macho_cpusubtype })
end
end
# Raised when a fat binary is loaded with MachOFile.
class FatBinaryError < MachOError
def initialize
super "Fat binaries must be loaded with MachO::FatFile"
end
end
# Raised when a Mach-O is loaded with FatFile.
class MachOBinaryError < MachOError
def initialize
super "Normal binaries must be loaded with MachO::MachOFile"
end
end
# Raised when the CPU type is unknown.
class CPUTypeError < MachOError
# @param cputype [Integer] the unknown CPU type
def initialize(cputype)
super "Unrecognized CPU type: 0x%08<cputype>x" % { :cputype => cputype }
end
end
# Raised when the CPU type/sub-type pair is unknown.
class CPUSubtypeError < MachOError
# @param cputype [Integer] the CPU type of the unknown pair
# @param cpusubtype [Integer] the CPU sub-type of the unknown pair
def initialize(cputype, cpusubtype)
super "Unrecognized CPU sub-type: 0x%08<cpusubtype>x " \
"(for CPU type: 0x%08<cputype>x" % { :cputype => cputype, :cpusubtype => cpusubtype }
end
end
# Raised when a mach-o file's filetype field is unknown.
class FiletypeError < MachOError
# @param num [Integer] the unknown number
def initialize(num)
super "Unrecognized Mach-O filetype code: 0x%02<num>x" % { :num => num }
end
end
# Raised when an unknown load command is encountered.
class LoadCommandError < MachOError
# @param num [Integer] the unknown number
def initialize(num)
super "Unrecognized Mach-O load command: 0x%02<num>x" % { :num => num }
end
end
# Raised when a load command can't be created manually.
class LoadCommandNotCreatableError < MachOError
# @param cmd_sym [Symbol] the uncreatable load command's symbol
def initialize(cmd_sym)
super "Load commands of type #{cmd_sym} cannot be created manually"
end
end
# Raised when the number of arguments used to create a load command manually
# is wrong.
class LoadCommandCreationArityError < MachOError
# @param cmd_sym [Symbol] the load command's symbol
# @param expected_arity [Integer] the number of arguments expected
# @param actual_arity [Integer] the number of arguments received
def initialize(cmd_sym, expected_arity, actual_arity)
super "Expected #{expected_arity} arguments for #{cmd_sym} creation, " \
"got #{actual_arity}"
end
end
# Raised when a load command can't be serialized.
class LoadCommandNotSerializableError < MachOError
# @param cmd_sym [Symbol] the load command's symbol
def initialize(cmd_sym)
super "Load commands of type #{cmd_sym} cannot be serialized"
end
end
# Raised when a load command string is malformed in some way.
class LCStrMalformedError < MachOError
# @param lc [MachO::LoadCommand] the load command containing the string
def initialize(lc)
super "Load command #{lc.type} at offset #{lc.view.offset} contains a " \
"malformed string"
end
end
# Raised when a change at an offset is not valid.
class OffsetInsertionError < ModificationError
# @param offset [Integer] the invalid offset
def initialize(offset)
super "Insertion at offset #{offset} is not valid"
end
end
# Raised when load commands are too large to fit in the current file.
class HeaderPadError < ModificationError
# @param filename [String] the filename
def initialize(filename)
super "Updated load commands do not fit in the header of " \
"#{filename}. #{filename} needs to be relinked, possibly with " \
"-headerpad or -headerpad_max_install_names"
end
end
# Raised when attempting to change a dylib name that doesn't exist.
class DylibUnknownError < RecoverableModificationError
# @param dylib [String] the unknown shared library name
def initialize(dylib)
super "No such dylib name: #{dylib}"
end
end
# Raised when a dylib is missing an ID
class DylibIdMissingError < RecoverableModificationError
def initialize
super "Dylib is missing a dylib ID"
end
end
# Raised when attempting to change an rpath that doesn't exist.
class RpathUnknownError < RecoverableModificationError
# @param path [String] the unknown runtime path
def initialize(path)
super "No such runtime path: #{path}"
end
end
# Raised when attempting to add an rpath that already exists.
class RpathExistsError < RecoverableModificationError
# @param path [String] the extant path
def initialize(path)
super "#{path} already exists"
end
end
# Raised whenever unfinished code is called.
class UnimplementedError < MachOError
# @param thing [String] the thing that is unimplemented
def initialize(thing)
super "Unimplemented: #{thing}"
end
end
# Raised when attempting to create a {FatFile} from one or more {MachOFile}s
# whose offsets will not fit within the resulting 32-bit {Headers::FatArch#offset} fields.
class FatArchOffsetOverflowError < MachOError
# @param offset [Integer] the offending offset
def initialize(offset)
super "Offset #{offset} exceeds the 32-bit width of a fat_arch offset. " \
"Consider merging with `fat64: true`"
end
end
# TODO(ww): doc
class LinkeditTypeMismatchError < MachOError
# TODO(ww): doc
def initialize(meth, lc_sym)
super "Method #{meth} can't be used on __LINKEDIT data commands of type #{lc_sym}"
end
end
# TODO(ww): doc
class CSBlobUnknownError < MachOError
# TODO(ww): doc
def initialize(magic)
super "Unknown code signing blob magic: 0x#{magic.to_s 16}"
end
end
# Raised when attempting to parse a compressed Mach-O without explicitly
# requesting decompression.
class CompressedMachOError < MachOError
end
# Raised when attempting to decompress a compressed Mach-O without adequate
# dependencies, or on other decompression errors.
class DecompressionError < MachOError
end
end