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.
Files changed (74) hide show
  1. nervapy/__init__.py +50 -0
  2. nervapy/abi.py +91 -0
  3. nervapy/arm/__init__.py +124 -0
  4. nervapy/arm/__main__.py +0 -0
  5. nervapy/arm/abi.py +138 -0
  6. nervapy/arm/formats.py +49 -0
  7. nervapy/arm/function.py +2465 -0
  8. nervapy/arm/generic.py +10796 -0
  9. nervapy/arm/instructions.py +519 -0
  10. nervapy/arm/isa.py +409 -0
  11. nervapy/arm/literal_pool.py +331 -0
  12. nervapy/arm/microarchitecture.py +211 -0
  13. nervapy/arm/pseudo.py +652 -0
  14. nervapy/arm/registers.py +1458 -0
  15. nervapy/arm/vfpneon.py +4092 -0
  16. nervapy/arm.py +13 -0
  17. nervapy/c/__init__.py +1 -0
  18. nervapy/c/types.py +436 -0
  19. nervapy/codegen.py +99 -0
  20. nervapy/common/__init__.py +4 -0
  21. nervapy/common/function.py +5 -0
  22. nervapy/common/regalloc.py +121 -0
  23. nervapy/constant_data.py +282 -0
  24. nervapy/encoder.py +246 -0
  25. nervapy/formats/__init__.py +2 -0
  26. nervapy/formats/elf/__init__.py +4 -0
  27. nervapy/formats/elf/file.py +178 -0
  28. nervapy/formats/elf/image.py +106 -0
  29. nervapy/formats/elf/section.py +422 -0
  30. nervapy/formats/elf/symbol.py +281 -0
  31. nervapy/formats/macho/__init__.py +2 -0
  32. nervapy/formats/macho/file.py +123 -0
  33. nervapy/formats/macho/image.py +143 -0
  34. nervapy/formats/macho/section.py +322 -0
  35. nervapy/formats/macho/symbol.py +158 -0
  36. nervapy/formats/mscoff/__init__.py +8 -0
  37. nervapy/formats/mscoff/image.py +132 -0
  38. nervapy/formats/mscoff/section.py +181 -0
  39. nervapy/formats/mscoff/symbol.py +148 -0
  40. nervapy/function.py +136 -0
  41. nervapy/literal.py +731 -0
  42. nervapy/loader.py +188 -0
  43. nervapy/name.py +159 -0
  44. nervapy/parse.py +52 -0
  45. nervapy/stream.py +58 -0
  46. nervapy/util.py +126 -0
  47. nervapy/writer.py +518 -0
  48. nervapy/x86_64/__init__.py +324 -0
  49. nervapy/x86_64/__main__.py +407 -0
  50. nervapy/x86_64/abi.py +517 -0
  51. nervapy/x86_64/amd.py +6464 -0
  52. nervapy/x86_64/avx.py +102029 -0
  53. nervapy/x86_64/crypto.py +1533 -0
  54. nervapy/x86_64/encoding.py +424 -0
  55. nervapy/x86_64/fma.py +19138 -0
  56. nervapy/x86_64/function.py +2707 -0
  57. nervapy/x86_64/generic.py +23384 -0
  58. nervapy/x86_64/instructions.py +500 -0
  59. nervapy/x86_64/isa.py +476 -0
  60. nervapy/x86_64/lower.py +126 -0
  61. nervapy/x86_64/mask.py +2593 -0
  62. nervapy/x86_64/meta.py +143 -0
  63. nervapy/x86_64/mmxsse.py +17265 -0
  64. nervapy/x86_64/nacl.py +327 -0
  65. nervapy/x86_64/operand.py +1204 -0
  66. nervapy/x86_64/options.py +21 -0
  67. nervapy/x86_64/pseudo.py +686 -0
  68. nervapy/x86_64/registers.py +1225 -0
  69. nervapy/x86_64/types.py +17 -0
  70. nervapy/x86_64/uarch.py +580 -0
  71. pynerva-0.0.7.dist-info/METADATA +310 -0
  72. pynerva-0.0.7.dist-info/RECORD +74 -0
  73. pynerva-0.0.7.dist-info/WHEEL +4 -0
  74. 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