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,178 @@
|
|
|
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 FileType(IntEnum):
|
|
8
|
+
# No file type
|
|
9
|
+
null = 0
|
|
10
|
+
# Relocatable file
|
|
11
|
+
object = 1
|
|
12
|
+
# Executable file
|
|
13
|
+
executable = 2
|
|
14
|
+
# Shared object file
|
|
15
|
+
dynamic_shared_object = 3
|
|
16
|
+
# Core dump file
|
|
17
|
+
core_dump = 4
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MachineType(IntEnum):
|
|
21
|
+
# Not specified
|
|
22
|
+
unspecified = 0
|
|
23
|
+
# SPARC
|
|
24
|
+
sparc = 2
|
|
25
|
+
# IA32 (x86)
|
|
26
|
+
x86 = 3
|
|
27
|
+
# MIPS
|
|
28
|
+
mips = 8
|
|
29
|
+
# 32-bit subset of SPARC V9
|
|
30
|
+
sparc32plus = 18
|
|
31
|
+
# IBM POWER and PowerPC
|
|
32
|
+
ppc = 20
|
|
33
|
+
# IBM PowerPC 64
|
|
34
|
+
ppc64 = 21
|
|
35
|
+
# ARM
|
|
36
|
+
arm = 40
|
|
37
|
+
# SPARC V9 (64-bit)
|
|
38
|
+
sparc64 = 43
|
|
39
|
+
# IA64 (Itanium)
|
|
40
|
+
ia64 = 50
|
|
41
|
+
# x86-64 (AMD64, Intel64, x64)
|
|
42
|
+
x86_64 = 62
|
|
43
|
+
# Intel Knights Ferry
|
|
44
|
+
l1om = 180
|
|
45
|
+
# Intel Knights Corner
|
|
46
|
+
k1om = 181
|
|
47
|
+
# ARMv8 AArch64
|
|
48
|
+
arm64 = 183
|
|
49
|
+
# ATI/AMD GPU code (for any GPU arch)
|
|
50
|
+
cal = 125
|
|
51
|
+
# nVidia CUDA GPU code (for any GPU arch)
|
|
52
|
+
cuda = 190
|
|
53
|
+
# HSAIL code (32-bit ELF)
|
|
54
|
+
hsail32 = 0xAF5A
|
|
55
|
+
# HSAIL code (64-bit ELF)
|
|
56
|
+
hsail64 = 0xAF5B
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class FormatVersion(IntEnum):
|
|
60
|
+
# Invalid version
|
|
61
|
+
invalid = 0
|
|
62
|
+
# Current version
|
|
63
|
+
current = 1
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ElfClass(IntEnum):
|
|
67
|
+
# Invalid class
|
|
68
|
+
invalid = 0
|
|
69
|
+
# 32-bit ELF
|
|
70
|
+
class32 = 1
|
|
71
|
+
# 64-bit ELF
|
|
72
|
+
class64 = 2
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class DataEncoding(IntEnum):
|
|
76
|
+
# Invalid data encoding
|
|
77
|
+
invalid = 0
|
|
78
|
+
# Least significant byte first (Little-Endian)
|
|
79
|
+
little_endian = 1
|
|
80
|
+
# Most significant byte first (Big-Endian)
|
|
81
|
+
big_endian = 2
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class OSABI(IntEnum):
|
|
85
|
+
# No extensions or unspecified
|
|
86
|
+
none = 0
|
|
87
|
+
# GNU Linux
|
|
88
|
+
gnu = 3
|
|
89
|
+
# FreeBSD
|
|
90
|
+
freebsd = 9
|
|
91
|
+
# ATI/AMD GPU ABI
|
|
92
|
+
cal = 100
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class FileIdentification:
|
|
96
|
+
def __init__(self, abi):
|
|
97
|
+
self.abi = abi
|
|
98
|
+
self.file_version = FormatVersion.current
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def as_bytearray(self):
|
|
102
|
+
identification = bytearray(16)
|
|
103
|
+
identification[0] = 0x7F
|
|
104
|
+
identification[1] = ord("E")
|
|
105
|
+
identification[2] = ord("L")
|
|
106
|
+
identification[3] = ord("F")
|
|
107
|
+
identification[4] = self.abi.elf_class
|
|
108
|
+
identification[5] = self.abi.elf_data_encoding
|
|
109
|
+
identification[6] = self.file_version
|
|
110
|
+
return identification
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class FileHeader:
|
|
114
|
+
def __init__(self, abi):
|
|
115
|
+
import nervapy.abi
|
|
116
|
+
import nervapy.formats.elf.section
|
|
117
|
+
|
|
118
|
+
if not isinstance(abi, nervapy.abi.ABI):
|
|
119
|
+
raise TypeError("ABI %s must be represented by an ABI object" % str(abi))
|
|
120
|
+
if not abi.is_elf_compatible:
|
|
121
|
+
raise ValueError("ABI %s is not compatible with ELF" % str(abi))
|
|
122
|
+
self.abi = abi
|
|
123
|
+
|
|
124
|
+
self.identification = FileIdentification(self.abi)
|
|
125
|
+
if self.abi.elf_class == ElfClass.class32:
|
|
126
|
+
# Size of ELF32 file header, in bytes
|
|
127
|
+
self.file_header_size = 52
|
|
128
|
+
# Size of program header, in bytes. All program headers have the same size.
|
|
129
|
+
self.program_header_entry_size = 32
|
|
130
|
+
# Size of a section header, in bytes. All sections have the same size.
|
|
131
|
+
self.section_header_entry_size = 40
|
|
132
|
+
else:
|
|
133
|
+
# Size of ELF64 file header, in bytes
|
|
134
|
+
self.file_header_size = 64
|
|
135
|
+
# Size of program header, in bytes. All program headers have the same size.
|
|
136
|
+
self.program_header_entry_size = 56
|
|
137
|
+
# Size of a section header, in bytes. All sections have the same size.
|
|
138
|
+
self.section_header_entry_size = 64
|
|
139
|
+
|
|
140
|
+
self.size = self.file_header_size
|
|
141
|
+
self.file_type = FileType.object
|
|
142
|
+
self.file_version = FormatVersion.current
|
|
143
|
+
self.entry_address = None
|
|
144
|
+
self.program_header_table_offset = None
|
|
145
|
+
self.section_header_table_offset = None
|
|
146
|
+
self.flags = 0
|
|
147
|
+
# Number of program headers in the program header table.
|
|
148
|
+
self.program_header_entries_count = 0
|
|
149
|
+
# Number of section headers in the section header table.
|
|
150
|
+
self.section_header_entries_count = 0
|
|
151
|
+
# Index of the section header for a section which contains section name string table.
|
|
152
|
+
# Usually this section is called ".shstrtab"
|
|
153
|
+
self.section_name_string_table_index = (
|
|
154
|
+
nervapy.formats.elf.section.SectionIndex.undefined
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def as_bytearray(self):
|
|
159
|
+
import nervapy.encoder
|
|
160
|
+
|
|
161
|
+
encoder = nervapy.encoder.Encoder(self.abi.endianness, self.abi.elf_bitness)
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
self.identification.as_bytearray
|
|
165
|
+
+ encoder.uint16(self.file_type)
|
|
166
|
+
+ encoder.uint16(self.abi.elf_machine_type)
|
|
167
|
+
+ encoder.uint32(self.file_version)
|
|
168
|
+
+ encoder.unsigned_offset(self.entry_address or 0)
|
|
169
|
+
+ encoder.unsigned_offset(self.program_header_table_offset or 0)
|
|
170
|
+
+ encoder.unsigned_offset(self.section_header_table_offset or 0)
|
|
171
|
+
+ encoder.uint32(self.flags)
|
|
172
|
+
+ encoder.uint16(self.file_header_size)
|
|
173
|
+
+ encoder.uint16(self.program_header_entry_size)
|
|
174
|
+
+ encoder.uint16(self.program_header_entries_count)
|
|
175
|
+
+ encoder.uint16(self.section_header_entry_size)
|
|
176
|
+
+ encoder.uint16(self.section_header_entries_count)
|
|
177
|
+
+ encoder.uint16(self.section_name_string_table_index)
|
|
178
|
+
)
|
|
@@ -0,0 +1,106 @@
|
|
|
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
|
+
|
|
5
|
+
class Image:
|
|
6
|
+
def __init__(self, abi, source=None):
|
|
7
|
+
from nervapy.formats.elf.section import (SectionIndex, StringSection,
|
|
8
|
+
SymbolSection, null_section)
|
|
9
|
+
from nervapy.formats.elf.symbol import (Symbol, SymbolBinding,
|
|
10
|
+
SymbolType)
|
|
11
|
+
|
|
12
|
+
self.abi = abi
|
|
13
|
+
self.shstrtab = StringSection(".shstrtab")
|
|
14
|
+
self.strtab = StringSection(".strtab")
|
|
15
|
+
self.symtab = SymbolSection(string_table=self.strtab)
|
|
16
|
+
self.sections = [null_section, self.shstrtab, self.strtab, self.symtab]
|
|
17
|
+
self._section_names = set(
|
|
18
|
+
[self.shstrtab.name, self.strtab.name, self.symtab.name]
|
|
19
|
+
)
|
|
20
|
+
if source:
|
|
21
|
+
source_symbol = Symbol()
|
|
22
|
+
source_symbol.value = 0
|
|
23
|
+
source_symbol.binding = SymbolBinding.local
|
|
24
|
+
source_symbol.type = SymbolType.file
|
|
25
|
+
source_symbol.name = source
|
|
26
|
+
source_symbol.size = 0
|
|
27
|
+
source_symbol.section = SectionIndex.absolute
|
|
28
|
+
self.symtab.add(source_symbol)
|
|
29
|
+
|
|
30
|
+
def add_section(self, section):
|
|
31
|
+
from nervapy.formats.elf.section import Section
|
|
32
|
+
|
|
33
|
+
if not isinstance(section, Section):
|
|
34
|
+
raise TypeError("%s is not a Section object" % str(section))
|
|
35
|
+
if section.name is not None and section.name in self._section_names:
|
|
36
|
+
raise ValueError(
|
|
37
|
+
"Section %s is already present in the image" % section.name
|
|
38
|
+
)
|
|
39
|
+
self.sections.append(section)
|
|
40
|
+
self._section_names.add(section.name)
|
|
41
|
+
|
|
42
|
+
def find_section(self, section_name):
|
|
43
|
+
for section in self.sections:
|
|
44
|
+
if section.name == section_name:
|
|
45
|
+
return section
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def as_bytearray(self):
|
|
49
|
+
import six
|
|
50
|
+
|
|
51
|
+
from nervapy.formats.elf.file import FileHeader
|
|
52
|
+
from nervapy.formats.elf.section import (Section, StringSection,
|
|
53
|
+
SymbolSection)
|
|
54
|
+
from nervapy.util import roundup
|
|
55
|
+
|
|
56
|
+
file_header = FileHeader(self.abi)
|
|
57
|
+
file_header.section_header_table_offset = file_header.size
|
|
58
|
+
file_header.section_header_entries_count = len(self.sections)
|
|
59
|
+
file_header.section_name_string_table_index = 1
|
|
60
|
+
data = file_header.as_bytearray
|
|
61
|
+
|
|
62
|
+
# Collect strings from sections
|
|
63
|
+
for section in self.sections:
|
|
64
|
+
self.shstrtab.add(section.name)
|
|
65
|
+
if isinstance(section, StringSection):
|
|
66
|
+
pass
|
|
67
|
+
elif isinstance(section, SymbolSection):
|
|
68
|
+
for symbol in six.iterkeys(section.symbol_index_map):
|
|
69
|
+
self.strtab.add(symbol.name)
|
|
70
|
+
|
|
71
|
+
# Layout sections
|
|
72
|
+
data_offset = file_header.size + Section.get_header_size(self.abi) * len(
|
|
73
|
+
self.sections
|
|
74
|
+
)
|
|
75
|
+
section_offsets = []
|
|
76
|
+
for section in self.sections:
|
|
77
|
+
if section.alignment != 0:
|
|
78
|
+
data_offset = roundup(data_offset, section.alignment)
|
|
79
|
+
section_offsets.append(data_offset)
|
|
80
|
+
data_offset += section.get_content_size(self.abi)
|
|
81
|
+
|
|
82
|
+
from nervapy.encoder import Encoder
|
|
83
|
+
|
|
84
|
+
encoder = Encoder(self.abi.endianness, self.abi.elf_bitness)
|
|
85
|
+
|
|
86
|
+
section_index_map = {
|
|
87
|
+
section: index for index, section in enumerate(self.sections)
|
|
88
|
+
}
|
|
89
|
+
# Write section headers
|
|
90
|
+
for section, offset in zip(self.sections, section_offsets):
|
|
91
|
+
data += section.encode_header(
|
|
92
|
+
encoder, self.shstrtab._string_index_map, section_index_map, offset
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Write section content
|
|
96
|
+
for section in self.sections:
|
|
97
|
+
padding = bytearray(roundup(len(data), section.alignment) - len(data))
|
|
98
|
+
data += padding
|
|
99
|
+
data += section.encode_content(
|
|
100
|
+
encoder,
|
|
101
|
+
self.strtab._string_index_map,
|
|
102
|
+
section_index_map,
|
|
103
|
+
self.symtab.symbol_index_map,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
return data
|
|
@@ -0,0 +1,422 @@
|
|
|
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 SectionFlags(IntEnum):
|
|
8
|
+
# Section contains writable data during process execution
|
|
9
|
+
writable = 0x1
|
|
10
|
+
# Section occupies memory during process execution
|
|
11
|
+
allocate = 0x2
|
|
12
|
+
# Section contains executable data machine instructions
|
|
13
|
+
executable = 0x4
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SectionType(IntEnum):
|
|
17
|
+
# Nil section
|
|
18
|
+
null = 0
|
|
19
|
+
# Program-specific content
|
|
20
|
+
program_bits = 1
|
|
21
|
+
# Symbol table
|
|
22
|
+
symbol_table = 2
|
|
23
|
+
# String table
|
|
24
|
+
string_table = 3
|
|
25
|
+
# Relocations with explicit addend
|
|
26
|
+
relocations_with_addend = 4
|
|
27
|
+
# Hash table for symbols used in dynamic linking
|
|
28
|
+
symbol_hash_table = 5
|
|
29
|
+
# Information for dynamic linking
|
|
30
|
+
dynamic_linking_info = 6
|
|
31
|
+
# Free-form note
|
|
32
|
+
note = 7
|
|
33
|
+
# Program-specific zero-initialized content
|
|
34
|
+
no_bits = 8
|
|
35
|
+
# Relocations without explicit addends
|
|
36
|
+
relocations = 9
|
|
37
|
+
# Minimal symbol table for dynamic linking
|
|
38
|
+
dynamic_symbol_table = 11
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class SectionIndex(IntEnum):
|
|
42
|
+
absolute = 0xFFF1
|
|
43
|
+
common = 0xFFF2
|
|
44
|
+
undefined = 0x0000
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Section(object):
|
|
48
|
+
def __init__(self, name, type, allocate=False, writable=False, executable=False):
|
|
49
|
+
# Section name
|
|
50
|
+
self.name = name
|
|
51
|
+
# Type of the section content
|
|
52
|
+
self._type = SectionType.null
|
|
53
|
+
self.type = type # Check the type object in property setter
|
|
54
|
+
# Properties of section content
|
|
55
|
+
self.flags = 0
|
|
56
|
+
if allocate:
|
|
57
|
+
self.flags |= SectionFlags.allocate
|
|
58
|
+
if writable:
|
|
59
|
+
self.flags |= SectionFlags.writable
|
|
60
|
+
if executable:
|
|
61
|
+
self.flags |= SectionFlags.executable
|
|
62
|
+
# Section address alignment. Only powers of 2 are allowed. Value 0 or 1 mean no alignment restrictions.
|
|
63
|
+
self._alignment = 1
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def type(self):
|
|
67
|
+
return self._type
|
|
68
|
+
|
|
69
|
+
@type.setter
|
|
70
|
+
def type(self, type):
|
|
71
|
+
if not isinstance(type, SectionType):
|
|
72
|
+
raise TypeError("Section type %s is not a SectionType enum" % str(type))
|
|
73
|
+
self._type = type
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def alignment(self):
|
|
77
|
+
return self._alignment
|
|
78
|
+
|
|
79
|
+
@alignment.setter
|
|
80
|
+
def alignment(self, alignment):
|
|
81
|
+
from nervapy.util import is_uint32
|
|
82
|
+
|
|
83
|
+
if not is_uint32(alignment):
|
|
84
|
+
raise TypeError(
|
|
85
|
+
"Section alignment %s is not representable as a 32-bit unsigned integer"
|
|
86
|
+
% str(alignment)
|
|
87
|
+
)
|
|
88
|
+
if alignment & (alignment - 1) != 0:
|
|
89
|
+
raise ValueError("Section alignment %d is not a power of 2" % alignment)
|
|
90
|
+
if alignment == 0:
|
|
91
|
+
alignment = 1
|
|
92
|
+
self._alignment = alignment
|
|
93
|
+
|
|
94
|
+
@staticmethod
|
|
95
|
+
def get_header_size(abi):
|
|
96
|
+
from nervapy.abi import ABI
|
|
97
|
+
|
|
98
|
+
assert isinstance(abi, ABI)
|
|
99
|
+
assert abi.elf_bitness in [32, 64]
|
|
100
|
+
|
|
101
|
+
return {32: 40, 64: 64}[abi.elf_bitness]
|
|
102
|
+
|
|
103
|
+
def get_content_size(self, abi):
|
|
104
|
+
return 0
|
|
105
|
+
|
|
106
|
+
def encode_header(
|
|
107
|
+
self,
|
|
108
|
+
encoder,
|
|
109
|
+
name_index_map,
|
|
110
|
+
section_index_map,
|
|
111
|
+
offset,
|
|
112
|
+
address=None,
|
|
113
|
+
link_section=None,
|
|
114
|
+
info=None,
|
|
115
|
+
content_size=0,
|
|
116
|
+
entry_size=0,
|
|
117
|
+
):
|
|
118
|
+
import nervapy.encoder
|
|
119
|
+
from nervapy.util import is_uint32, is_uint64
|
|
120
|
+
|
|
121
|
+
assert isinstance(encoder, nervapy.encoder.Encoder)
|
|
122
|
+
assert isinstance(name_index_map, dict)
|
|
123
|
+
assert section_index_map is None or isinstance(section_index_map, dict)
|
|
124
|
+
assert offset is None or is_uint64(offset)
|
|
125
|
+
assert address is None or is_uint64(address)
|
|
126
|
+
assert link_section is None or isinstance(link_section, Section)
|
|
127
|
+
assert info is None or is_uint64(info)
|
|
128
|
+
assert is_uint64(content_size)
|
|
129
|
+
assert is_uint32(entry_size)
|
|
130
|
+
|
|
131
|
+
assert encoder.bitness in [32, 64]
|
|
132
|
+
if encoder.bitness == 32:
|
|
133
|
+
assert offset is None or is_uint32(offset)
|
|
134
|
+
assert address is None or is_uint32(address)
|
|
135
|
+
assert self.name is None or self.name in name_index_map
|
|
136
|
+
assert section_index_map is not None or link_section is None
|
|
137
|
+
|
|
138
|
+
name_index = name_index_map.get(self.name, 0)
|
|
139
|
+
if address is None:
|
|
140
|
+
address = 0
|
|
141
|
+
if offset is None:
|
|
142
|
+
offset = 0
|
|
143
|
+
link = 0
|
|
144
|
+
if link_section is not None:
|
|
145
|
+
link = section_index_map[link_section]
|
|
146
|
+
if info is None:
|
|
147
|
+
info = 0
|
|
148
|
+
return (
|
|
149
|
+
encoder.uint32(name_index)
|
|
150
|
+
+ encoder.uint32(self.type)
|
|
151
|
+
+ encoder.unsigned_offset(self.flags)
|
|
152
|
+
+ encoder.unsigned_offset(address)
|
|
153
|
+
+ encoder.unsigned_offset(offset)
|
|
154
|
+
+ encoder.unsigned_offset(content_size)
|
|
155
|
+
+ encoder.uint32(link)
|
|
156
|
+
+ encoder.uint32(info)
|
|
157
|
+
+ encoder.unsigned_offset(self.alignment)
|
|
158
|
+
+ encoder.unsigned_offset(entry_size)
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
def encode_content(
|
|
162
|
+
self, encoder, name_index_map, section_index_map, symbol_index_map
|
|
163
|
+
):
|
|
164
|
+
import nervapy.encoder
|
|
165
|
+
|
|
166
|
+
assert isinstance(encoder, nervapy.encoder.Encoder)
|
|
167
|
+
assert isinstance(name_index_map, dict)
|
|
168
|
+
assert section_index_map is None or isinstance(section_index_map, dict)
|
|
169
|
+
assert symbol_index_map is None or isinstance(symbol_index_map, dict)
|
|
170
|
+
|
|
171
|
+
assert encoder.bitness in [32, 64]
|
|
172
|
+
|
|
173
|
+
return bytearray()
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
null_section = Section(None, SectionType.null)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class ProgramBitsSection(Section):
|
|
180
|
+
def __init__(self, name, allocate=True, writable=False, executable=False):
|
|
181
|
+
super(ProgramBitsSection, self).__init__(
|
|
182
|
+
name, SectionType.program_bits, allocate, writable, executable
|
|
183
|
+
)
|
|
184
|
+
self.content = bytearray()
|
|
185
|
+
|
|
186
|
+
def get_content_size(self, abi):
|
|
187
|
+
return len(self.content)
|
|
188
|
+
|
|
189
|
+
def encode_header(
|
|
190
|
+
self, encoder, name_index_map, section_index_map, offset, address=None
|
|
191
|
+
):
|
|
192
|
+
return super(ProgramBitsSection, self).encode_header(
|
|
193
|
+
encoder,
|
|
194
|
+
name_index_map,
|
|
195
|
+
section_index_map,
|
|
196
|
+
offset,
|
|
197
|
+
address=address,
|
|
198
|
+
content_size=len(self.content),
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
def encode_content(
|
|
202
|
+
self, encoder, name_index_map, section_index_map, symbol_index_map
|
|
203
|
+
):
|
|
204
|
+
super(ProgramBitsSection, self).encode_content(
|
|
205
|
+
encoder, name_index_map, section_index_map, symbol_index_map
|
|
206
|
+
)
|
|
207
|
+
return self.content
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class TextSection(ProgramBitsSection):
|
|
211
|
+
def __init__(self, name=".text"):
|
|
212
|
+
super(TextSection, self).__init__(name, executable=True)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class DataSection(ProgramBitsSection):
|
|
216
|
+
def __init__(self, name=".data"):
|
|
217
|
+
super(DataSection, self).__init__(name, writable=True)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class ReadOnlyDataSection(ProgramBitsSection):
|
|
221
|
+
def __init__(self, name=".rodata"):
|
|
222
|
+
super(ReadOnlyDataSection, self).__init__(name)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class StringSection(Section):
|
|
226
|
+
def __init__(self, name=".strtab"):
|
|
227
|
+
super(StringSection, self).__init__(name, SectionType.string_table)
|
|
228
|
+
self._string_index_map = dict()
|
|
229
|
+
self.content_size = 0
|
|
230
|
+
|
|
231
|
+
def add(self, string):
|
|
232
|
+
if not string:
|
|
233
|
+
return 0
|
|
234
|
+
elif string in self._string_index_map:
|
|
235
|
+
return self._string_index_map[string]
|
|
236
|
+
else:
|
|
237
|
+
import codecs
|
|
238
|
+
|
|
239
|
+
if self.content_size == 0:
|
|
240
|
+
self.content_size = 1
|
|
241
|
+
string_index = self.content_size
|
|
242
|
+
self._string_index_map[string] = string_index
|
|
243
|
+
string_bytes = codecs.encode(string, "utf-8")
|
|
244
|
+
self.content_size += len(string_bytes) + 1
|
|
245
|
+
return string_index
|
|
246
|
+
|
|
247
|
+
def get_content_size(self, abi):
|
|
248
|
+
return self.content_size
|
|
249
|
+
|
|
250
|
+
def encode_header(self, encoder, name_index_map, section_index_map, offset):
|
|
251
|
+
return super(StringSection, self).encode_header(
|
|
252
|
+
encoder,
|
|
253
|
+
name_index_map,
|
|
254
|
+
section_index_map,
|
|
255
|
+
offset,
|
|
256
|
+
content_size=self.content_size,
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
def encode_content(
|
|
260
|
+
self, encoder, name_index_map, section_index_map, symbol_index_map
|
|
261
|
+
):
|
|
262
|
+
super(StringSection, self).encode_content(
|
|
263
|
+
encoder, name_index_map, section_index_map, symbol_index_map
|
|
264
|
+
)
|
|
265
|
+
if self.content_size != 0:
|
|
266
|
+
import codecs
|
|
267
|
+
|
|
268
|
+
bytes = b"\x00"
|
|
269
|
+
for string in sorted(
|
|
270
|
+
self._string_index_map, key=self._string_index_map.get
|
|
271
|
+
):
|
|
272
|
+
bytes += codecs.encode(string, "utf8") + b"\x00"
|
|
273
|
+
return bytes
|
|
274
|
+
else:
|
|
275
|
+
return bytearray()
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class SymbolSection(Section):
|
|
279
|
+
def __init__(self, name=".symtab", string_table=None):
|
|
280
|
+
super(SymbolSection, self).__init__(name, SectionType.symbol_table)
|
|
281
|
+
self._symbols_set = set()
|
|
282
|
+
self._local_symbols = list()
|
|
283
|
+
self._nonlocal_symbols = list()
|
|
284
|
+
self._string_table = string_table
|
|
285
|
+
|
|
286
|
+
@property
|
|
287
|
+
def symbol_index_map(self):
|
|
288
|
+
symbol_index_map = {
|
|
289
|
+
symbol: index for index, symbol in enumerate(self._local_symbols)
|
|
290
|
+
}
|
|
291
|
+
local_symbols_count = len(self._local_symbols)
|
|
292
|
+
symbol_index_map.update(
|
|
293
|
+
{
|
|
294
|
+
symbol: local_symbols_count + index
|
|
295
|
+
for index, symbol in enumerate(self._nonlocal_symbols)
|
|
296
|
+
}
|
|
297
|
+
)
|
|
298
|
+
return symbol_index_map
|
|
299
|
+
|
|
300
|
+
def add(self, symbol):
|
|
301
|
+
from nervapy.formats.elf.symbol import Symbol, SymbolBinding
|
|
302
|
+
|
|
303
|
+
assert isinstance(symbol, Symbol)
|
|
304
|
+
|
|
305
|
+
if symbol in self._symbols_set:
|
|
306
|
+
raise ValueError(
|
|
307
|
+
"Symbol %s is already present in the section %s"
|
|
308
|
+
% (str(symbol), self.name)
|
|
309
|
+
)
|
|
310
|
+
self._symbols_set.add(symbol)
|
|
311
|
+
if symbol.binding == SymbolBinding.local:
|
|
312
|
+
self._local_symbols.append(symbol)
|
|
313
|
+
else:
|
|
314
|
+
self._nonlocal_symbols.append(symbol)
|
|
315
|
+
|
|
316
|
+
def get_content_size(self, abi):
|
|
317
|
+
from nervapy.abi import ABI
|
|
318
|
+
from nervapy.formats.elf.symbol import Symbol
|
|
319
|
+
|
|
320
|
+
assert isinstance(abi, ABI)
|
|
321
|
+
assert abi.elf_bitness in [32, 64]
|
|
322
|
+
|
|
323
|
+
entry_size = Symbol.get_entry_size(abi)
|
|
324
|
+
return entry_size * (len(self._local_symbols) + len(self._nonlocal_symbols))
|
|
325
|
+
|
|
326
|
+
def encode_header(self, encoder, name_index_map, section_index_map, offset):
|
|
327
|
+
import nervapy.encoder
|
|
328
|
+
|
|
329
|
+
assert isinstance(encoder, nervapy.encoder.Encoder)
|
|
330
|
+
assert encoder.bitness in [32, 64]
|
|
331
|
+
|
|
332
|
+
entry_size = {32: 16, 64: 24}[encoder.bitness]
|
|
333
|
+
symbols_count = len(self._local_symbols) + len(self._nonlocal_symbols)
|
|
334
|
+
return super(SymbolSection, self).encode_header(
|
|
335
|
+
encoder,
|
|
336
|
+
name_index_map,
|
|
337
|
+
section_index_map,
|
|
338
|
+
offset,
|
|
339
|
+
link_section=self._string_table,
|
|
340
|
+
info=len(self._local_symbols),
|
|
341
|
+
content_size=symbols_count * entry_size,
|
|
342
|
+
entry_size=entry_size,
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
def encode_content(
|
|
346
|
+
self, encoder, name_index_map, section_index_map, symbol_index_map
|
|
347
|
+
):
|
|
348
|
+
super(SymbolSection, self).encode_content(
|
|
349
|
+
encoder, name_index_map, section_index_map, symbol_index_map
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
# Local symbols must be encoded before non-local symbols. Thus, need to separate the two classes
|
|
353
|
+
content = bytearray()
|
|
354
|
+
|
|
355
|
+
# Step 1: encode local symbols
|
|
356
|
+
for symbol in self._local_symbols:
|
|
357
|
+
content += symbol.encode(encoder, name_index_map, section_index_map)
|
|
358
|
+
# Step 2: encode non-local symbols
|
|
359
|
+
for symbol in self._nonlocal_symbols:
|
|
360
|
+
content += symbol.encode(encoder, name_index_map, section_index_map)
|
|
361
|
+
|
|
362
|
+
return content
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
class RelocationsWithAddendSection(Section):
|
|
366
|
+
def __init__(self, reference_section, symbol_table):
|
|
367
|
+
super(RelocationsWithAddendSection, self).__init__(
|
|
368
|
+
".rela" + reference_section.name, SectionType.relocations_with_addend
|
|
369
|
+
)
|
|
370
|
+
self.reference_section = reference_section
|
|
371
|
+
self.symbol_table = symbol_table
|
|
372
|
+
|
|
373
|
+
self.relocations = list()
|
|
374
|
+
|
|
375
|
+
def add(self, relocation):
|
|
376
|
+
from nervapy.formats.elf.symbol import RelocationWithAddend
|
|
377
|
+
|
|
378
|
+
assert isinstance(relocation, RelocationWithAddend)
|
|
379
|
+
|
|
380
|
+
self.relocations.append(relocation)
|
|
381
|
+
|
|
382
|
+
def get_content_size(self, abi):
|
|
383
|
+
from nervapy.abi import ABI
|
|
384
|
+
|
|
385
|
+
assert isinstance(abi, ABI)
|
|
386
|
+
assert abi.elf_bitness in [32, 64]
|
|
387
|
+
|
|
388
|
+
entry_size = {32: 12, 64: 24}[abi.elf_bitness]
|
|
389
|
+
return entry_size * len(self.relocations)
|
|
390
|
+
|
|
391
|
+
def encode_header(self, encoder, name_index_map, section_index_map, offset):
|
|
392
|
+
import nervapy.encoder
|
|
393
|
+
|
|
394
|
+
assert isinstance(encoder, nervapy.encoder.Encoder)
|
|
395
|
+
assert encoder.bitness in [32, 64]
|
|
396
|
+
|
|
397
|
+
entry_size = {32: 16, 64: 24}[encoder.bitness]
|
|
398
|
+
relocations_count = len(self.relocations)
|
|
399
|
+
reference_section_index = section_index_map[self.reference_section]
|
|
400
|
+
return super(RelocationsWithAddendSection, self).encode_header(
|
|
401
|
+
encoder,
|
|
402
|
+
name_index_map,
|
|
403
|
+
section_index_map,
|
|
404
|
+
offset,
|
|
405
|
+
link_section=self.symbol_table,
|
|
406
|
+
info=reference_section_index,
|
|
407
|
+
content_size=relocations_count * entry_size,
|
|
408
|
+
entry_size=entry_size,
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
def encode_content(
|
|
412
|
+
self, encoder, name_index_map, section_index_map, symbol_index_map
|
|
413
|
+
):
|
|
414
|
+
super(RelocationsWithAddendSection, self).encode_content(
|
|
415
|
+
encoder, name_index_map, section_index_map, symbol_index_map
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
content = bytearray()
|
|
419
|
+
for relocation in self.relocations:
|
|
420
|
+
content += relocation.encode(encoder, symbol_index_map)
|
|
421
|
+
|
|
422
|
+
return content
|