mirror of https://github.com/Nonannet/copapy.git
stecin_db and binwrite updated
This commit is contained in:
parent
d4bc56f1db
commit
0ec9007033
|
|
@ -1,8 +1,6 @@
|
||||||
import re
|
import re
|
||||||
import pkgutil
|
import pkgutil
|
||||||
from tkinter import Variable
|
from typing import Generator, Iterable, Any
|
||||||
from typing import Generator, Iterable, Any, Literal, TypeVar
|
|
||||||
import pelfy
|
|
||||||
from . import binwrite as binw
|
from . import binwrite as binw
|
||||||
from .stencil_db import stencil_database
|
from .stencil_db import stencil_database
|
||||||
|
|
||||||
|
|
@ -361,14 +359,39 @@ def compile_to_instruction_list(end_nodes: Iterable[Node] | Node) -> binw.data_w
|
||||||
# write auxiliary_functions
|
# write auxiliary_functions
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
# write program
|
# Prepare program data and relocations
|
||||||
for net, node in extended_output_ops:
|
object_addr_lookp = {net: out_offs for net, out_offs, _ in object_list}
|
||||||
|
data_list: list[bytes] = []
|
||||||
|
patch_list: list[tuple[int, int, int]] = []
|
||||||
|
offset = 0 # offset in generated code chunk
|
||||||
|
|
||||||
|
print('object_addr_lookp: ', object_addr_lookp)
|
||||||
|
|
||||||
|
for result_net, node in extended_output_ops:
|
||||||
assert node.name in sdb.function_definitions, f"- Warning: {node.name} prototype not found"
|
assert node.name in sdb.function_definitions, f"- Warning: {node.name} prototype not found"
|
||||||
data = sdb.get_func_data(node.name)
|
data = sdb.get_func_data(node.name)
|
||||||
|
data_list.append(data)
|
||||||
print('*', node.name, ' '.join(f'{d:02X}' for d in data))
|
print('*', node.name, ' '.join(f'{d:02X}' for d in data))
|
||||||
for reloc_offset, lengths, bits, reloc_type in sdb.get_relocs(node.name):
|
|
||||||
#if not relocation.symbol.name.startswith('result_'):
|
for patch in sdb.get_patch_positions(node.name):
|
||||||
print(relocation)
|
assert result_net, f"Relocation found but no result net defined for operation {node.name}"
|
||||||
|
print('patch: ', patch)
|
||||||
|
object_addr = object_addr_lookp[result_net]
|
||||||
|
patch_list.append((patch.type.value, offset + patch.addr, object_addr))
|
||||||
|
|
||||||
|
offset += len(data)
|
||||||
|
|
||||||
|
# write program data
|
||||||
|
dw.write_com(binw.Command.ALLOCATE_CODE)
|
||||||
|
dw.write_int(offset)
|
||||||
|
dw.write_bytes(b''.join(data_list))
|
||||||
|
|
||||||
|
# write relocations
|
||||||
|
for patch_type, patch_addr, object_addr in patch_list:
|
||||||
|
dw.write_com(binw.Command.PATCH_OBJECT)
|
||||||
|
dw.write_int(patch_addr)
|
||||||
|
dw.write_int(patch_type)
|
||||||
|
dw.write_int(object_addr)
|
||||||
|
|
||||||
print('-----')
|
print('-----')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,28 +3,19 @@ from pelfy import elf_symbol
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
|
|
||||||
Command = Enum('Command', [('ALLOCATE_DATA', 1), ('COPY_DATA', 2),
|
Command = Enum('Command', [('ALLOCATE_DATA', 1), ('COPY_DATA', 2),
|
||||||
('ALLOCATE_CODE', 3), ('COPY_CODE', 4),
|
('ALLOCATE_CODE', 3), ('COPY_CODE', 4),
|
||||||
('RELOCATE_FUNC', 5), ('RELOCATE_OBJECT', 6),
|
('PATCH_FUNC', 5), ('PATCH_OBJECT', 6),
|
||||||
('SET_ENTR_POINT', 64), ('END_PROG', 255)])
|
('SET_ENTR_POINT', 64), ('END_PROG', 255)])
|
||||||
|
|
||||||
RelocationType = Enum('RelocationType', [('RELOC_RELATIVE_32', 0)])
|
|
||||||
|
|
||||||
def translate_relocation(new_sym_addr: int, new_patch_addr: int, reloc_type: str, r_addend: int) -> tuple[int, int]:
|
|
||||||
if reloc_type in ('R_AMD64_PLT32', 'R_AMD64_PC32'):
|
|
||||||
# S + A - P
|
|
||||||
value = new_sym_addr + r_addend - new_patch_addr
|
|
||||||
return RelocationType.RELOC_RELATIVE_32.value, value
|
|
||||||
else:
|
|
||||||
raise Exception(f"Unknown: {reloc_type}")
|
|
||||||
|
|
||||||
|
|
||||||
def get_variable_data(symbols: list[elf_symbol]) -> tuple[list[tuple[elf_symbol, int, int]], int]:
|
def get_variable_data(symbols: list[elf_symbol]) -> tuple[list[tuple[elf_symbol, int, int]], int]:
|
||||||
object_list: list[tuple[elf_symbol, int, int]] = []
|
object_list: list[tuple[elf_symbol, int, int]] = []
|
||||||
out_offs = 0
|
out_offs = 0
|
||||||
for sym in symbols:
|
for sym in symbols:
|
||||||
assert sym.info == 'STT_OBJECT'
|
assert sym.info == 'STT_OBJECT'
|
||||||
lengths = sym.fields['st_size']
|
lengths = sym.fields['st_size'],
|
||||||
object_list.append((sym, out_offs, lengths))
|
object_list.append((sym, out_offs, lengths))
|
||||||
out_offs += (lengths + 3) // 4 * 4
|
out_offs += (lengths + 3) // 4 * 4
|
||||||
return object_list, out_offs
|
return object_list, out_offs
|
||||||
|
|
@ -114,6 +105,6 @@ def get_c_consts() -> str:
|
||||||
ret: list[str] = []
|
ret: list[str] = []
|
||||||
for c in Command:
|
for c in Command:
|
||||||
ret.append (f"#define {c.name} {c.value}")
|
ret.append (f"#define {c.name} {c.value}")
|
||||||
for c in RelocationType:
|
for c in PatchType:
|
||||||
ret.append(f"#define {c.name} {c.value}")
|
ret.append(f"#define {c.name} {c.value}")
|
||||||
return '\n'.join(ret)
|
return '\n'.join(ret)
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
from ast import Tuple
|
from dataclasses import dataclass
|
||||||
from os import name
|
|
||||||
from tkinter import NO
|
|
||||||
import pelfy
|
import pelfy
|
||||||
from typing import Generator, Literal
|
from typing import Generator, Literal
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
start_marker = 0xF17ECAFE
|
start_marker = 0xF17ECAFE
|
||||||
|
|
@ -10,6 +9,30 @@ end_marker = 0xF27ECAFE
|
||||||
|
|
||||||
LENGTH_CALL_INSTRUCTION = 4 # x86_64
|
LENGTH_CALL_INSTRUCTION = 4 # x86_64
|
||||||
|
|
||||||
|
RelocationType = Enum('RelocationType', [('RELOC_RELATIVE_32', 0)])
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class patch_entry:
|
||||||
|
"""
|
||||||
|
A class for representing a relocation entry
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
addr (int): address of first byte to patch relative to the start of the symbol
|
||||||
|
type (RelocationType): relocation type"""
|
||||||
|
|
||||||
|
type: RelocationType
|
||||||
|
addr: int
|
||||||
|
|
||||||
|
|
||||||
|
def translate_relocation(relocation_addr: int, reloc_type: str, bits: int, r_addend: int) -> patch_entry:
|
||||||
|
if reloc_type in ('R_AMD64_PLT32', 'R_AMD64_PC32'):
|
||||||
|
# S + A - P
|
||||||
|
patch_offset = relocation_addr - r_addend
|
||||||
|
return patch_entry(RelocationType.RELOC_RELATIVE_32, patch_offset)
|
||||||
|
else:
|
||||||
|
raise Exception(f"Unknown: {reloc_type}")
|
||||||
|
|
||||||
|
|
||||||
def get_ret_function_def(symbol: pelfy.elf_symbol):
|
def get_ret_function_def(symbol: pelfy.elf_symbol):
|
||||||
#print('*', symbol.name, symbol.section)
|
#print('*', symbol.name, symbol.section)
|
||||||
result_func = symbol.relocations[-1].symbol
|
result_func = symbol.relocations[-1].symbol
|
||||||
|
|
@ -55,13 +78,8 @@ class stencil_database():
|
||||||
self.elf.symbols[name].data
|
self.elf.symbols[name].data
|
||||||
|
|
||||||
|
|
||||||
def get_relocs(self, symbol_name: str) -> Generator[tuple[int, int, str], None, None]:
|
def get_patch_positions(self, symbol_name: str) -> Generator[patch_entry, None, None]:
|
||||||
"""Return relocation offset relative to striped symbol start.
|
"""Return patch positions
|
||||||
Yields tuples of (reloc_offset, symbol_lenght, bits, reloc_type)
|
|
||||||
1. reloc_offset: Offset of the relocation relative to the start of the stripped symbol data.
|
|
||||||
2. Length of the striped symbol.
|
|
||||||
3. Bits to patch
|
|
||||||
4. reloc_type: Type of the relocation as a string.
|
|
||||||
"""
|
"""
|
||||||
symbol = self.elf.symbols[symbol_name]
|
symbol = self.elf.symbols[symbol_name]
|
||||||
start_index = symbol.data.find(start_marker.to_bytes(4, symbol.file.byteorder))
|
start_index = symbol.data.find(start_marker.to_bytes(4, symbol.file.byteorder))
|
||||||
|
|
@ -69,10 +87,16 @@ class stencil_database():
|
||||||
|
|
||||||
for reloc in symbol.relocations:
|
for reloc in symbol.relocations:
|
||||||
|
|
||||||
reloc_offset = reloc.fields['r_offset'] - symbol.fields['st_value'] - start_index
|
# address to fist byte to patch relative to the start of the symbol
|
||||||
|
patch = translate_relocation(
|
||||||
|
reloc.fields['r_offset'] - symbol.fields['st_value'] - start_index,
|
||||||
|
reloc.type,
|
||||||
|
reloc.bits,
|
||||||
|
reloc.fields['r_addend'])
|
||||||
|
|
||||||
if reloc_offset < end_index - start_index - LENGTH_CALL_INSTRUCTION:
|
# Exclude the call to the result_x function
|
||||||
yield (reloc_offset, reloc.bits, reloc.type)
|
if patch.addr < end_index - start_index - LENGTH_CALL_INSTRUCTION:
|
||||||
|
yield patch
|
||||||
|
|
||||||
|
|
||||||
def get_func_data(self, name: str) -> bytes:
|
def get_func_data(self, name: str) -> bytes:
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,12 @@
|
||||||
#define COPY_DATA 2
|
#define COPY_DATA 2
|
||||||
#define ALLOCATE_CODE 3
|
#define ALLOCATE_CODE 3
|
||||||
#define COPY_CODE 4
|
#define COPY_CODE 4
|
||||||
#define RELOCATE_FUNC 5
|
#define PATCH_FUNC 5
|
||||||
#define RELOCATE_OBJECT 6
|
#define PATCH_OBJECT 6
|
||||||
#define SET_ENTR_POINT 64
|
#define SET_ENTR_POINT 64
|
||||||
#define END_PROG 255
|
#define END_PROG 255
|
||||||
|
|
||||||
#define RELOC_RELATIVE_32 0
|
#define PATCH_RELATIVE_32 0
|
||||||
|
|
||||||
uint8_t *data_memory;
|
uint8_t *data_memory;
|
||||||
uint8_t *executable_memory;
|
uint8_t *executable_memory;
|
||||||
|
|
@ -53,8 +53,8 @@ void patch_mem_32(uint8_t *patch_addr, int32_t value){
|
||||||
*val_ptr = value;
|
*val_ptr = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int relocate(uint8_t *patch_addr, uint32_t reloc_type, int32_t value){
|
int patch(uint8_t *patch_addr, uint32_t reloc_type, int32_t value){
|
||||||
if (reloc_type == RELOC_RELATIVE_32){
|
if (reloc_type == PATCH_RELATIVE_32){
|
||||||
patch_mem_32(patch_addr, value);
|
patch_mem_32(patch_addr, value);
|
||||||
}else{
|
}else{
|
||||||
printf("Not implemented");
|
printf("Not implemented");
|
||||||
|
|
@ -104,27 +104,27 @@ int parse_commands(uint8_t *bytes){
|
||||||
memcpy(executable_memory + offs, bytes, size); bytes += size;
|
memcpy(executable_memory + offs, bytes, size); bytes += size;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RELOCATE_FUNC:
|
case PATCH_FUNC:
|
||||||
offs = *(uint32_t*)bytes; bytes += 4;
|
offs = *(uint32_t*)bytes; bytes += 4;
|
||||||
reloc_type = *(uint32_t*)bytes; bytes += 4;
|
reloc_type = *(uint32_t*)bytes; bytes += 4;
|
||||||
value = *(int32_t*)bytes; bytes += 4;
|
value = *(int32_t*)bytes; bytes += 4;
|
||||||
printf("RELOCATE_FUNC patch_offs=%i reloc_type=%i value=%i\n",
|
printf("PATCH_FUNC patch_offs=%i reloc_type=%i value=%i\n",
|
||||||
offs, reloc_type, value);
|
offs, reloc_type, value);
|
||||||
relocate(executable_memory + offs, reloc_type, value);
|
patch(executable_memory + offs, reloc_type, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RELOCATE_OBJECT:
|
case PATCH_OBJECT:
|
||||||
offs = *(uint32_t*)bytes; bytes += 4;
|
offs = *(uint32_t*)bytes; bytes += 4;
|
||||||
reloc_type = *(uint32_t*)bytes; bytes += 4;
|
reloc_type = *(uint32_t*)bytes; bytes += 4;
|
||||||
value = *(int32_t*)bytes; bytes += 4;
|
value = *(int32_t*)bytes; bytes += 4;
|
||||||
printf("RELOCATE_OBJECT patch_offs=%i reloc_type=%i value=%i\n",
|
printf("PATCH_OBJECT patch_offs=%i reloc_type=%i value=%i\n",
|
||||||
offs, reloc_type, value);
|
offs, reloc_type, value);
|
||||||
data_offs = (int32_t)(data_memory - executable_memory);
|
data_offs = (int32_t)(data_memory - executable_memory);
|
||||||
if (abs(data_offs) > 0x7FFFFFFF) {
|
if (abs(data_offs) > 0x7FFFFFFF) {
|
||||||
perror("code and data memory to far apart");
|
perror("code and data memory to far apart");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
relocate(executable_memory + offs, reloc_type, value + (int32_t)data_offs);
|
patch(executable_memory + offs, reloc_type, value + (int32_t)data_offs);
|
||||||
//printf("> %i\n", data_offs);
|
//printf("> %i\n", data_offs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,5 @@
|
||||||
#from diss_helper import dmprint
|
from copapy import Write, const
|
||||||
import pelfy
|
|
||||||
#from IPython.display import Markdown
|
|
||||||
|
|
||||||
from typing import Literal
|
|
||||||
from copapy import Op, Write, const
|
|
||||||
import copapy as rc
|
import copapy as rc
|
||||||
from copapy.binwrite import data_writer, Command, RelocationType, get_variable_data, get_function_data, translate_relocation
|
|
||||||
|
|
||||||
def test_compile():
|
def test_compile():
|
||||||
c1 = const(1.11)
|
c1 = const(1.11)
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,5 @@ if __name__ == "__main__":
|
||||||
print('----')
|
print('----')
|
||||||
#print(sdb.function_definitions)
|
#print(sdb.function_definitions)
|
||||||
for sym_name in sdb.function_definitions.keys():
|
for sym_name in sdb.function_definitions.keys():
|
||||||
print('-', sym_name)
|
print('\n-', sym_name)
|
||||||
print(list(sdb.get_relocs(sym_name)))
|
print(list(sdb.get_patch_positions(sym_name)))
|
||||||
Loading…
Reference in New Issue