PyNerva 0.0.7__py3-none-any.whl
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.
- nervapy/__init__.py +50 -0
- nervapy/abi.py +91 -0
- nervapy/arm/__init__.py +124 -0
- nervapy/arm/__main__.py +0 -0
- nervapy/arm/abi.py +138 -0
- nervapy/arm/formats.py +49 -0
- nervapy/arm/function.py +2465 -0
- nervapy/arm/generic.py +10796 -0
- nervapy/arm/instructions.py +519 -0
- nervapy/arm/isa.py +409 -0
- nervapy/arm/literal_pool.py +331 -0
- nervapy/arm/microarchitecture.py +211 -0
- nervapy/arm/pseudo.py +652 -0
- nervapy/arm/registers.py +1458 -0
- nervapy/arm/vfpneon.py +4092 -0
- nervapy/arm.py +13 -0
- nervapy/c/__init__.py +1 -0
- nervapy/c/types.py +436 -0
- nervapy/codegen.py +99 -0
- nervapy/common/__init__.py +4 -0
- nervapy/common/function.py +5 -0
- nervapy/common/regalloc.py +121 -0
- nervapy/constant_data.py +282 -0
- nervapy/encoder.py +246 -0
- nervapy/formats/__init__.py +2 -0
- nervapy/formats/elf/__init__.py +4 -0
- nervapy/formats/elf/file.py +178 -0
- nervapy/formats/elf/image.py +106 -0
- nervapy/formats/elf/section.py +422 -0
- nervapy/formats/elf/symbol.py +281 -0
- nervapy/formats/macho/__init__.py +2 -0
- nervapy/formats/macho/file.py +123 -0
- nervapy/formats/macho/image.py +143 -0
- nervapy/formats/macho/section.py +322 -0
- nervapy/formats/macho/symbol.py +158 -0
- nervapy/formats/mscoff/__init__.py +8 -0
- nervapy/formats/mscoff/image.py +132 -0
- nervapy/formats/mscoff/section.py +181 -0
- nervapy/formats/mscoff/symbol.py +148 -0
- nervapy/function.py +136 -0
- nervapy/literal.py +731 -0
- nervapy/loader.py +188 -0
- nervapy/name.py +159 -0
- nervapy/parse.py +52 -0
- nervapy/stream.py +58 -0
- nervapy/util.py +126 -0
- nervapy/writer.py +518 -0
- nervapy/x86_64/__init__.py +324 -0
- nervapy/x86_64/__main__.py +407 -0
- nervapy/x86_64/abi.py +517 -0
- nervapy/x86_64/amd.py +6464 -0
- nervapy/x86_64/avx.py +102029 -0
- nervapy/x86_64/crypto.py +1533 -0
- nervapy/x86_64/encoding.py +424 -0
- nervapy/x86_64/fma.py +19138 -0
- nervapy/x86_64/function.py +2707 -0
- nervapy/x86_64/generic.py +23384 -0
- nervapy/x86_64/instructions.py +500 -0
- nervapy/x86_64/isa.py +476 -0
- nervapy/x86_64/lower.py +126 -0
- nervapy/x86_64/mask.py +2593 -0
- nervapy/x86_64/meta.py +143 -0
- nervapy/x86_64/mmxsse.py +17265 -0
- nervapy/x86_64/nacl.py +327 -0
- nervapy/x86_64/operand.py +1204 -0
- nervapy/x86_64/options.py +21 -0
- nervapy/x86_64/pseudo.py +686 -0
- nervapy/x86_64/registers.py +1225 -0
- nervapy/x86_64/types.py +17 -0
- nervapy/x86_64/uarch.py +580 -0
- pynerva-0.0.7.dist-info/METADATA +310 -0
- pynerva-0.0.7.dist-info/RECORD +74 -0
- pynerva-0.0.7.dist-info/WHEEL +4 -0
- pynerva-0.0.7.dist-info/licenses/LICENSE.rst +15 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
# This file is part of PeachPy package and is licensed under the Simplified BSD license.
|
|
2
|
+
# See license.rst for the full text of the license.
|
|
3
|
+
|
|
4
|
+
from enum import IntEnum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MemoryProtection(IntEnum):
|
|
8
|
+
read = 0x01
|
|
9
|
+
write = 0x02
|
|
10
|
+
execute = 0x04
|
|
11
|
+
default = 0x07
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Segment:
|
|
15
|
+
def __init__(self, name):
|
|
16
|
+
self.name = name
|
|
17
|
+
self.sections = list()
|
|
18
|
+
self.flags = 0
|
|
19
|
+
|
|
20
|
+
def add_section(self, section):
|
|
21
|
+
assert isinstance(section, Section)
|
|
22
|
+
assert section.segment_name == self.name
|
|
23
|
+
|
|
24
|
+
self.sections.append(section)
|
|
25
|
+
|
|
26
|
+
def get_command_size(self, abi):
|
|
27
|
+
from nervapy.abi import ABI
|
|
28
|
+
|
|
29
|
+
assert isinstance(abi, ABI)
|
|
30
|
+
assert abi.pointer_size in [4, 8]
|
|
31
|
+
|
|
32
|
+
return {4: 56, 8: 72}[abi.pointer_size] + sum(
|
|
33
|
+
section.get_command_size(abi) for section in self.sections
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
def encode_command(
|
|
37
|
+
self, encoder, section_offset_map, section_address_map, section_relocations_map
|
|
38
|
+
):
|
|
39
|
+
import nervapy.encoder
|
|
40
|
+
|
|
41
|
+
assert isinstance(encoder, nervapy.encoder.Encoder)
|
|
42
|
+
|
|
43
|
+
offset = section_offset_map[self.sections[0]]
|
|
44
|
+
memory_size = (
|
|
45
|
+
section_address_map[self.sections[-1]] + self.sections[-1].content_size
|
|
46
|
+
)
|
|
47
|
+
file_size = sum(section.content_size for section in self.sections)
|
|
48
|
+
|
|
49
|
+
address = 0
|
|
50
|
+
if self.sections:
|
|
51
|
+
address = section_address_map[self.sections[0]]
|
|
52
|
+
# TODO: combine the two cases
|
|
53
|
+
if encoder.bitness == 32:
|
|
54
|
+
command_id = 0x1
|
|
55
|
+
command_size = 56 + len(self.sections) * 68
|
|
56
|
+
command = (
|
|
57
|
+
encoder.uint32(command_id)
|
|
58
|
+
+ encoder.uint32(command_size)
|
|
59
|
+
+ encoder.fixed_string(self.name, 16)
|
|
60
|
+
+ encoder.uint32(address)
|
|
61
|
+
+ encoder.uint32(memory_size)
|
|
62
|
+
+ encoder.uint32(offset)
|
|
63
|
+
+ encoder.uint32(file_size)
|
|
64
|
+
+ encoder.uint32(MemoryProtection.default)
|
|
65
|
+
+ encoder.uint32(MemoryProtection.default)
|
|
66
|
+
+ encoder.uint32(len(self.sections))
|
|
67
|
+
+ encoder.uint32(self.flags)
|
|
68
|
+
)
|
|
69
|
+
else:
|
|
70
|
+
command_id = 0x19
|
|
71
|
+
command_size = 72 + len(self.sections) * 80
|
|
72
|
+
command = (
|
|
73
|
+
encoder.uint32(command_id)
|
|
74
|
+
+ encoder.uint32(command_size)
|
|
75
|
+
+ encoder.fixed_string(self.name, 16)
|
|
76
|
+
+ encoder.uint64(address)
|
|
77
|
+
+ encoder.uint64(memory_size)
|
|
78
|
+
+ encoder.uint64(offset)
|
|
79
|
+
+ encoder.uint64(file_size)
|
|
80
|
+
+ encoder.uint32(MemoryProtection.default)
|
|
81
|
+
+ encoder.uint32(MemoryProtection.default)
|
|
82
|
+
+ encoder.uint32(len(self.sections))
|
|
83
|
+
+ encoder.uint32(self.flags)
|
|
84
|
+
)
|
|
85
|
+
for section in self.sections:
|
|
86
|
+
command += section.encode_command(
|
|
87
|
+
encoder,
|
|
88
|
+
section_offset_map[section],
|
|
89
|
+
section_address_map[section],
|
|
90
|
+
section_relocations_map.get(section),
|
|
91
|
+
)
|
|
92
|
+
from nervapy.x86_64.abi import system_v_x86_64_abi
|
|
93
|
+
|
|
94
|
+
return command
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class SectionIndex(IntEnum):
|
|
98
|
+
no_section = 0
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class SectionType(IntEnum):
|
|
102
|
+
regular = 0x00
|
|
103
|
+
zero_fill = 0x01
|
|
104
|
+
gb_zero_fill = 0x0C
|
|
105
|
+
cstring_literals = 0x02
|
|
106
|
+
four_byte_literals = 0x03
|
|
107
|
+
eight_byte_literals = 0x04
|
|
108
|
+
sixteen_byte_literals = 0x0E
|
|
109
|
+
literal_pointers = 0x05
|
|
110
|
+
non_lazy_symbol_pointers = 0x06
|
|
111
|
+
lazy_symbol_pointers = 0x07
|
|
112
|
+
symbol_stubs = 0x08
|
|
113
|
+
module_init_function_pointers = 0x09
|
|
114
|
+
module_terminate_function_pointers = 0x0A
|
|
115
|
+
coalesced_symbols = 0x0B
|
|
116
|
+
interposing = 0x0D
|
|
117
|
+
dtrace_object_format = 0x0F
|
|
118
|
+
lazy_dylib_symbol_pointers = 0x10
|
|
119
|
+
thread_local_regular = 0x11
|
|
120
|
+
thread_local_zero_fill = 0x12
|
|
121
|
+
thread_local_variable_descriptors = 0x13
|
|
122
|
+
thread_local_variable_pointers = 0x14
|
|
123
|
+
thread_local_function_pointers = 0x15
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class SectionAttributes(IntEnum):
|
|
127
|
+
only_instructions = 0x80000000
|
|
128
|
+
coalesced_symbols = 0x40000000
|
|
129
|
+
strip_static_symbols = 0x20000000
|
|
130
|
+
no_dead_stripping = 0x10000000
|
|
131
|
+
live_support = 0x08000000
|
|
132
|
+
self_modifying_code = 0x04000000
|
|
133
|
+
debug = 0x02000000
|
|
134
|
+
some_instructions = 0x00000400
|
|
135
|
+
external_relocations = 0x00000200
|
|
136
|
+
local_relocations = 0x00000100
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class Section(object):
|
|
140
|
+
def __init__(self, type, segment_name, section_name):
|
|
141
|
+
self.type = type
|
|
142
|
+
self.segment_name = segment_name
|
|
143
|
+
self.section_name = section_name
|
|
144
|
+
self.attributes = 0
|
|
145
|
+
self._alignment = 1
|
|
146
|
+
self.relocations = []
|
|
147
|
+
self.content = bytearray()
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def alignment(self):
|
|
151
|
+
return self._alignment
|
|
152
|
+
|
|
153
|
+
@alignment.setter
|
|
154
|
+
def alignment(self, alignment):
|
|
155
|
+
from nervapy.util import is_uint32
|
|
156
|
+
|
|
157
|
+
if not is_uint32(alignment):
|
|
158
|
+
raise TypeError(
|
|
159
|
+
"Section alignment %s is not representable as a 32-bit unsigned integer"
|
|
160
|
+
% str(alignment)
|
|
161
|
+
)
|
|
162
|
+
if alignment & (alignment - 1) != 0:
|
|
163
|
+
raise ValueError("Section alignment %d is not a power of 2" % alignment)
|
|
164
|
+
if alignment == 0:
|
|
165
|
+
alignment = 1
|
|
166
|
+
self._alignment = alignment
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def log2_alignment(self):
|
|
170
|
+
from nervapy.util import ilog2
|
|
171
|
+
|
|
172
|
+
return ilog2(self._alignment)
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def relocations_count(self):
|
|
176
|
+
return len(self.relocations)
|
|
177
|
+
|
|
178
|
+
@property
|
|
179
|
+
def content_size(self):
|
|
180
|
+
return len(self.content)
|
|
181
|
+
|
|
182
|
+
@staticmethod
|
|
183
|
+
def get_command_size(abi):
|
|
184
|
+
from nervapy.abi import ABI
|
|
185
|
+
|
|
186
|
+
assert isinstance(abi, ABI)
|
|
187
|
+
assert abi.pointer_size in [4, 8]
|
|
188
|
+
|
|
189
|
+
return {4: 68, 8: 80}[abi.pointer_size]
|
|
190
|
+
|
|
191
|
+
def encode_command(self, encoder, offset, address, relocations_offset):
|
|
192
|
+
import nervapy.encoder
|
|
193
|
+
|
|
194
|
+
assert isinstance(encoder, nervapy.encoder.Encoder)
|
|
195
|
+
|
|
196
|
+
if len(self.relocations) == 0:
|
|
197
|
+
relocations_offset = 0
|
|
198
|
+
if encoder.bitness == 32:
|
|
199
|
+
return (
|
|
200
|
+
encoder.fixed_string(self.section_name, 16)
|
|
201
|
+
+ encoder.fixed_string(self.segment_name, 16)
|
|
202
|
+
+ encoder.uint32(address)
|
|
203
|
+
+ encoder.uint32(self.content_size)
|
|
204
|
+
+ encoder.uint32(offset)
|
|
205
|
+
+ encoder.uint32(self.log2_alignment)
|
|
206
|
+
+ encoder.uint32(relocations_offset)
|
|
207
|
+
+ encoder.uint32(self.relocations_count)
|
|
208
|
+
+ encoder.uint32(self.type | self.attributes)
|
|
209
|
+
+ bytearray(8)
|
|
210
|
+
)
|
|
211
|
+
else:
|
|
212
|
+
return (
|
|
213
|
+
encoder.fixed_string(self.section_name, 16)
|
|
214
|
+
+ encoder.fixed_string(self.segment_name, 16)
|
|
215
|
+
+ encoder.uint64(address)
|
|
216
|
+
+ encoder.uint64(self.content_size)
|
|
217
|
+
+ encoder.uint32(offset)
|
|
218
|
+
+ encoder.uint32(self.log2_alignment)
|
|
219
|
+
+ encoder.uint32(relocations_offset)
|
|
220
|
+
+ encoder.uint32(self.relocations_count)
|
|
221
|
+
+ encoder.uint32(self.type | self.attributes)
|
|
222
|
+
+ bytearray(12)
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class RegularSection(Section):
|
|
227
|
+
def __init__(self, segment_name, section_name):
|
|
228
|
+
super(RegularSection, self).__init__(
|
|
229
|
+
SectionType.regular, segment_name, section_name
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
def align(self, alignment):
|
|
233
|
+
import nervapy.util
|
|
234
|
+
|
|
235
|
+
ilog2_alignment = nervapy.util.ilog2(alignment)
|
|
236
|
+
self.alignment = max(self.alignment, ilog2_alignment)
|
|
237
|
+
if len(self.content) % alignment != 0:
|
|
238
|
+
padding_length = alignment - len(self.content) % alignment
|
|
239
|
+
self.content += bytearray(padding_length)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class TextSection(RegularSection):
|
|
243
|
+
def __init__(self):
|
|
244
|
+
super(TextSection, self).__init__("__TEXT", "__text")
|
|
245
|
+
self.attributes = (
|
|
246
|
+
SectionAttributes.only_instructions | SectionAttributes.some_instructions
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class ConstSection(RegularSection):
|
|
251
|
+
def __init__(self):
|
|
252
|
+
super(ConstSection, self).__init__("__TEXT", "__const")
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class SymbolTable:
|
|
256
|
+
command_size = 24
|
|
257
|
+
|
|
258
|
+
def __init__(self, string_table):
|
|
259
|
+
assert isinstance(string_table, StringTable)
|
|
260
|
+
|
|
261
|
+
self.symbols = list()
|
|
262
|
+
self.string_table = string_table
|
|
263
|
+
|
|
264
|
+
def add_symbol(self, symbol):
|
|
265
|
+
from nervapy.formats.macho.symbol import Symbol
|
|
266
|
+
|
|
267
|
+
assert isinstance(symbol, Symbol)
|
|
268
|
+
|
|
269
|
+
self.symbols.append(symbol)
|
|
270
|
+
self.string_table.add(symbol.name)
|
|
271
|
+
|
|
272
|
+
def encode_command(self, encoder, symbol_offset_map, string_offset):
|
|
273
|
+
import nervapy.encoder
|
|
274
|
+
|
|
275
|
+
assert isinstance(encoder, nervapy.encoder.Encoder)
|
|
276
|
+
|
|
277
|
+
command_id = 0x2
|
|
278
|
+
symbols_offset = 0
|
|
279
|
+
if self.symbols:
|
|
280
|
+
symbols_offset = symbol_offset_map[self.symbols[0]]
|
|
281
|
+
return (
|
|
282
|
+
encoder.uint32(command_id)
|
|
283
|
+
+ encoder.uint32(SymbolTable.command_size)
|
|
284
|
+
+ encoder.uint32(symbols_offset)
|
|
285
|
+
+ encoder.uint32(len(self.symbols))
|
|
286
|
+
+ encoder.uint32(string_offset)
|
|
287
|
+
+ encoder.uint32(self.string_table.size)
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class StringTable:
|
|
292
|
+
def __init__(self):
|
|
293
|
+
self.string_index_map = dict()
|
|
294
|
+
self.size = 0
|
|
295
|
+
|
|
296
|
+
def add(self, string):
|
|
297
|
+
import codecs
|
|
298
|
+
|
|
299
|
+
if string is None or len(string) == 0:
|
|
300
|
+
return 0
|
|
301
|
+
if string in self.string_index_map:
|
|
302
|
+
return self.string_index_map[string]
|
|
303
|
+
else:
|
|
304
|
+
content_size = self.size
|
|
305
|
+
if content_size == 0:
|
|
306
|
+
content_size = 1
|
|
307
|
+
string_index = content_size
|
|
308
|
+
self.string_index_map[string] = string_index
|
|
309
|
+
bytestring = codecs.encode(string, "utf-8")
|
|
310
|
+
content_size += len(bytestring) + 1
|
|
311
|
+
self.size = content_size
|
|
312
|
+
|
|
313
|
+
def encode(self):
|
|
314
|
+
import codecs
|
|
315
|
+
|
|
316
|
+
if self.size != 0:
|
|
317
|
+
bytestring = b"\x00"
|
|
318
|
+
for string in sorted(self.string_index_map, key=self.string_index_map.get):
|
|
319
|
+
bytestring += codecs.encode(string, "utf8") + b"\x00"
|
|
320
|
+
return bytestring
|
|
321
|
+
else:
|
|
322
|
+
return bytearray()
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# This file is part of PeachPy package and is licensed under the Simplified BSD license.
|
|
2
|
+
# See license.rst for the full text of the license.
|
|
3
|
+
|
|
4
|
+
from enum import IntEnum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SymbolVisibility(IntEnum):
|
|
8
|
+
external = 0x01
|
|
9
|
+
private_external = 0x10
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SymbolType(IntEnum):
|
|
13
|
+
undefined = 0x00
|
|
14
|
+
prebound_undefined = 0x0C
|
|
15
|
+
absolute = 0x02
|
|
16
|
+
section_relative = 0x0E
|
|
17
|
+
indirect = 0x0A
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SymbolDescription(IntEnum):
|
|
21
|
+
undefined_lazy = 0x00
|
|
22
|
+
undefined_non_lazy = 0x01
|
|
23
|
+
defined = 0x02
|
|
24
|
+
private_defined = 0x03
|
|
25
|
+
private_undefined_lazy = 0x05
|
|
26
|
+
private_undefined_non_lazy = 0x04
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SymbolFlags(IntEnum):
|
|
30
|
+
referenced_dynamically = 0x10
|
|
31
|
+
no_dead_strip = 0x20
|
|
32
|
+
weak_reference = 0x40
|
|
33
|
+
weak_definition = 0x80
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Symbol:
|
|
37
|
+
def __init__(self, name, type, section, value=None):
|
|
38
|
+
self.name = name
|
|
39
|
+
self.visibility = 0
|
|
40
|
+
self.type = type
|
|
41
|
+
self.section = section
|
|
42
|
+
self.description = 0
|
|
43
|
+
self.flags = 0
|
|
44
|
+
self.value = value
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
def get_entry_size(abi):
|
|
48
|
+
from nervapy.abi import ABI
|
|
49
|
+
|
|
50
|
+
assert isinstance(abi, ABI)
|
|
51
|
+
assert abi.pointer_size in [4, 8]
|
|
52
|
+
|
|
53
|
+
return {4: 12, 8: 16}[abi.pointer_size]
|
|
54
|
+
|
|
55
|
+
def encode(self, encoder, name_index_map, section_index_map, section_address_map):
|
|
56
|
+
import nervapy.encoder
|
|
57
|
+
|
|
58
|
+
assert isinstance(encoder, nervapy.encoder.Encoder)
|
|
59
|
+
assert self.name in name_index_map
|
|
60
|
+
assert self.section is None or self.section in section_index_map
|
|
61
|
+
|
|
62
|
+
name_index = name_index_map[self.name]
|
|
63
|
+
section_index = 0
|
|
64
|
+
if self.section is not None:
|
|
65
|
+
section_index = section_index_map[self.section]
|
|
66
|
+
if encoder.bitness == 32:
|
|
67
|
+
return (
|
|
68
|
+
encoder.uint32(name_index)
|
|
69
|
+
+ encoder.uint8(self.type | self.visibility)
|
|
70
|
+
+ encoder.uint8(section_index)
|
|
71
|
+
+ encoder.uint16(self.description | self.flags)
|
|
72
|
+
+ encoder.uint32(self.value)
|
|
73
|
+
)
|
|
74
|
+
else:
|
|
75
|
+
return (
|
|
76
|
+
encoder.uint32(name_index)
|
|
77
|
+
+ encoder.uint8(self.type | self.visibility)
|
|
78
|
+
+ encoder.uint8(section_index)
|
|
79
|
+
+ encoder.uint16(self.description | self.flags)
|
|
80
|
+
+ encoder.uint64(self.value + section_address_map[self.section])
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class RelocationType(IntEnum):
|
|
85
|
+
x86_64_unsigned = 0
|
|
86
|
+
x86_64_signed = 1
|
|
87
|
+
# CALL or JMP instruction with 32-bit displacement.
|
|
88
|
+
x86_64_branch = 2
|
|
89
|
+
# Load (MOVQ) of a 64-bit Global Offset Table entry
|
|
90
|
+
x86_64_got_load = 3
|
|
91
|
+
x86_64_got = 4
|
|
92
|
+
x86_64_subtractor = 5
|
|
93
|
+
# Signed 32-bit displacement with a -1 addend
|
|
94
|
+
x86_64_signed_minus_1 = 6
|
|
95
|
+
# Signed 32-bit displacement with a -2 addend
|
|
96
|
+
x86_64_signed_minus_2 = 7
|
|
97
|
+
# Signed 32-bit displacement with a -4 addend
|
|
98
|
+
x86_64_signed_minus_4 = 8
|
|
99
|
+
|
|
100
|
+
arm_vanilla = 0
|
|
101
|
+
arm_pair = 1
|
|
102
|
+
arm_sectdiff = 2
|
|
103
|
+
arm_local_sectdiff = 3
|
|
104
|
+
arm_pb_la_ptr = 4
|
|
105
|
+
arm_br_24 = 5
|
|
106
|
+
arm_half = 6
|
|
107
|
+
arm_half_sectdiff = 7
|
|
108
|
+
|
|
109
|
+
arm64_unsigned = 0
|
|
110
|
+
arm64_subtractor = 1
|
|
111
|
+
arm64_branch26 = 2
|
|
112
|
+
arm64_page21 = 3
|
|
113
|
+
arm64_pageoff12 = 4
|
|
114
|
+
arm64_got_load_page21 = 5
|
|
115
|
+
arm64_got_load_pageoff12 = 6
|
|
116
|
+
arm64_pointer_to_got = 7
|
|
117
|
+
arm64_tlvp_load_page21 = 8
|
|
118
|
+
arm64_tlvp_load_pageoff12 = 9
|
|
119
|
+
arm64_reloc_addend = 10
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class Relocation:
|
|
123
|
+
size = 8
|
|
124
|
+
|
|
125
|
+
def __init__(self, type, offset, size, symbol, is_pc_relative=False):
|
|
126
|
+
from nervapy.util import is_sint32
|
|
127
|
+
|
|
128
|
+
assert is_sint32(offset)
|
|
129
|
+
assert offset >= 0
|
|
130
|
+
assert size in [1, 2, 4, 8]
|
|
131
|
+
from nervapy.formats.macho.section import Section
|
|
132
|
+
|
|
133
|
+
assert symbol is None or isinstance(symbol, (Section, Symbol))
|
|
134
|
+
|
|
135
|
+
self.type = type
|
|
136
|
+
self.offset = offset
|
|
137
|
+
self.size = size
|
|
138
|
+
self.symbol = symbol
|
|
139
|
+
self.is_pc_relative = is_pc_relative
|
|
140
|
+
|
|
141
|
+
def encode(self, encoder, section_index_map, symbol_index_map):
|
|
142
|
+
from nervapy.formats.macho.section import Section
|
|
143
|
+
from nervapy.util import ilog2
|
|
144
|
+
|
|
145
|
+
symbol = 0
|
|
146
|
+
if isinstance(self.symbol, Symbol):
|
|
147
|
+
# Set "external" bit (bit 27) if referencing an external symbol
|
|
148
|
+
symbol = symbol_index_map[self.symbol] | 0x8000000
|
|
149
|
+
elif isinstance(self.symbol, Section):
|
|
150
|
+
symbol = section_index_map[self.symbol]
|
|
151
|
+
if self.is_pc_relative:
|
|
152
|
+
# Set "pc_relative" bit (bit 24) if the relocation is relative to the program counter
|
|
153
|
+
symbol |= 0x1000000
|
|
154
|
+
log2_size = ilog2(self.size)
|
|
155
|
+
symbol |= log2_size << 25
|
|
156
|
+
symbol |= self.type << 28
|
|
157
|
+
|
|
158
|
+
return encoder.uint32(self.offset) + encoder.uint32(symbol)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# This file is part of PeachPy package and is licensed under the Simplified BSD license.
|
|
2
|
+
# See license.rst for the full text of the license.
|
|
3
|
+
|
|
4
|
+
from nervapy.formats.mscoff.image import Image, MachineType
|
|
5
|
+
from nervapy.formats.mscoff.section import (ReadOnlyDataSection, Section,
|
|
6
|
+
TextSection)
|
|
7
|
+
from nervapy.formats.mscoff.symbol import (Relocation, RelocationType,
|
|
8
|
+
StorageClass, Symbol, SymbolType)
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# This file is part of PeachPy package and is licensed under the Simplified BSD license.
|
|
2
|
+
# See license.rst for the full text of the license.
|
|
3
|
+
|
|
4
|
+
from enum import IntEnum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MachineType(IntEnum):
|
|
8
|
+
# Machine-independent
|
|
9
|
+
unknown = 0
|
|
10
|
+
# IA32 (x86)
|
|
11
|
+
x86 = 0x14C
|
|
12
|
+
# x86-64 (AMD64, Intel64, x64)
|
|
13
|
+
x86_64 = 0x8664
|
|
14
|
+
# IA64 (Itanium)
|
|
15
|
+
ia64 = 0x200
|
|
16
|
+
# ARM
|
|
17
|
+
arm = 0x1C0
|
|
18
|
+
# ARMv7 (Thumb mode only)
|
|
19
|
+
armnt = 0x1C4
|
|
20
|
+
# ARMv8 AArch64
|
|
21
|
+
arm64 = 0xAA64
|
|
22
|
+
# EFI bytecode
|
|
23
|
+
efi_bytecode = 0xEBC
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Image:
|
|
27
|
+
file_header_size = 20
|
|
28
|
+
|
|
29
|
+
def __init__(self, abi, source=None):
|
|
30
|
+
from nervapy.formats.mscoff.section import StringTable
|
|
31
|
+
|
|
32
|
+
self.abi = abi
|
|
33
|
+
self.sections = list()
|
|
34
|
+
self.symbols = list()
|
|
35
|
+
self.string_table = StringTable()
|
|
36
|
+
|
|
37
|
+
def add_section(self, section):
|
|
38
|
+
from nervapy.formats.mscoff.section import Section
|
|
39
|
+
|
|
40
|
+
assert isinstance(section, Section)
|
|
41
|
+
|
|
42
|
+
self.sections.append(section)
|
|
43
|
+
|
|
44
|
+
def add_symbol(self, symbol):
|
|
45
|
+
from nervapy.formats.mscoff.symbol import Symbol
|
|
46
|
+
|
|
47
|
+
assert isinstance(symbol, Symbol)
|
|
48
|
+
|
|
49
|
+
self.symbols.append(symbol)
|
|
50
|
+
|
|
51
|
+
def encode(self):
|
|
52
|
+
from nervapy.encoder import Encoder
|
|
53
|
+
|
|
54
|
+
encoder = Encoder(self.abi.endianness)
|
|
55
|
+
|
|
56
|
+
# Collect names that need to be encoded in the string table
|
|
57
|
+
import codecs
|
|
58
|
+
|
|
59
|
+
for section in self.sections:
|
|
60
|
+
if len(codecs.encode(section.name, "utf8")) > 8:
|
|
61
|
+
self.string_table.add(section.name)
|
|
62
|
+
for symbol in self.symbols:
|
|
63
|
+
if len(codecs.encode(symbol.name, "utf8")) > 8:
|
|
64
|
+
self.string_table.add(symbol.name)
|
|
65
|
+
|
|
66
|
+
# Layout sections offsets
|
|
67
|
+
from nervapy.formats.mscoff.section import Section
|
|
68
|
+
|
|
69
|
+
section_offset_map = dict()
|
|
70
|
+
symbol_table_offset = (
|
|
71
|
+
Image.file_header_size + len(self.sections) * Section.header_size
|
|
72
|
+
)
|
|
73
|
+
data_offset = symbol_table_offset + self.string_table.size
|
|
74
|
+
for symbol in self.symbols:
|
|
75
|
+
data_offset += symbol.entry_size
|
|
76
|
+
for section in self.sections:
|
|
77
|
+
section_offset_map[section] = data_offset
|
|
78
|
+
data_offset += section.content_size
|
|
79
|
+
|
|
80
|
+
# Layout section relocations
|
|
81
|
+
from nervapy.formats.mscoff.symbol import Relocation
|
|
82
|
+
|
|
83
|
+
section_relocations_map = dict()
|
|
84
|
+
for section in self.sections:
|
|
85
|
+
if section.relocations:
|
|
86
|
+
section_relocations_map[section] = data_offset
|
|
87
|
+
data_offset += Relocation.entry_size * len(section.relocations)
|
|
88
|
+
|
|
89
|
+
section_index_map = {
|
|
90
|
+
section: index + 1 for index, section in enumerate(self.sections)
|
|
91
|
+
}
|
|
92
|
+
symbol_index_map = {symbol: index for index, symbol in enumerate(self.symbols)}
|
|
93
|
+
|
|
94
|
+
# Write file header
|
|
95
|
+
timestamp = 0
|
|
96
|
+
file_flags = 0
|
|
97
|
+
data = (
|
|
98
|
+
encoder.uint16(self.abi.mscoff_machine_type)
|
|
99
|
+
+ encoder.uint16(len(self.sections))
|
|
100
|
+
+ encoder.uint32(timestamp)
|
|
101
|
+
+ encoder.uint32(symbol_table_offset)
|
|
102
|
+
+ encoder.uint32(len(self.symbols))
|
|
103
|
+
+ encoder.uint16(0)
|
|
104
|
+
+ encoder.uint16(file_flags)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Write section headers
|
|
108
|
+
for section in self.sections:
|
|
109
|
+
data += section.encode_header(
|
|
110
|
+
encoder,
|
|
111
|
+
self.string_table._strings,
|
|
112
|
+
section_offset_map[section],
|
|
113
|
+
section_relocations_map.get(section),
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Write symbol table and string table (immediately follows symbols table)
|
|
117
|
+
for symbol in self.symbols:
|
|
118
|
+
data += symbol.encode_entry(
|
|
119
|
+
encoder, self.string_table._strings, section_index_map
|
|
120
|
+
)
|
|
121
|
+
data += self.string_table.encode()
|
|
122
|
+
|
|
123
|
+
# Write section content
|
|
124
|
+
for section in self.sections:
|
|
125
|
+
data += section.content
|
|
126
|
+
|
|
127
|
+
# Write section relocations
|
|
128
|
+
for section in self.sections:
|
|
129
|
+
for relocation in section.relocations:
|
|
130
|
+
data += relocation.encode_entry(encoder, symbol_index_map)
|
|
131
|
+
|
|
132
|
+
return data
|