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 pkgutil
|
||||
from tkinter import Variable
|
||||
from typing import Generator, Iterable, Any, Literal, TypeVar
|
||||
import pelfy
|
||||
from typing import Generator, Iterable, Any
|
||||
from . import binwrite as binw
|
||||
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
|
||||
# TODO
|
||||
|
||||
# write program
|
||||
for net, node in extended_output_ops:
|
||||
# Prepare program data and relocations
|
||||
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"
|
||||
data = sdb.get_func_data(node.name)
|
||||
data_list.append(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_'):
|
||||
print(relocation)
|
||||
|
||||
for patch in sdb.get_patch_positions(node.name):
|
||||
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('-----')
|
||||
|
||||
|
|
|
|||
|
|
@ -3,28 +3,19 @@ from pelfy import elf_symbol
|
|||
from typing import Literal
|
||||
import struct
|
||||
|
||||
|
||||
Command = Enum('Command', [('ALLOCATE_DATA', 1), ('COPY_DATA', 2),
|
||||
('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)])
|
||||
|
||||
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]:
|
||||
object_list: list[tuple[elf_symbol, int, int]] = []
|
||||
out_offs = 0
|
||||
for sym in symbols:
|
||||
assert sym.info == 'STT_OBJECT'
|
||||
lengths = sym.fields['st_size']
|
||||
lengths = sym.fields['st_size'],
|
||||
object_list.append((sym, out_offs, lengths))
|
||||
out_offs += (lengths + 3) // 4 * 4
|
||||
return object_list, out_offs
|
||||
|
|
@ -114,6 +105,6 @@ def get_c_consts() -> str:
|
|||
ret: list[str] = []
|
||||
for c in Command:
|
||||
ret.append (f"#define {c.name} {c.value}")
|
||||
for c in RelocationType:
|
||||
for c in PatchType:
|
||||
ret.append(f"#define {c.name} {c.value}")
|
||||
return '\n'.join(ret)
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
from ast import Tuple
|
||||
from os import name
|
||||
from tkinter import NO
|
||||
from dataclasses import dataclass
|
||||
import pelfy
|
||||
from typing import Generator, Literal
|
||||
from enum import Enum
|
||||
|
||||
|
||||
start_marker = 0xF17ECAFE
|
||||
|
|
@ -10,6 +9,30 @@ end_marker = 0xF27ECAFE
|
|||
|
||||
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):
|
||||
#print('*', symbol.name, symbol.section)
|
||||
result_func = symbol.relocations[-1].symbol
|
||||
|
|
@ -55,13 +78,8 @@ class stencil_database():
|
|||
self.elf.symbols[name].data
|
||||
|
||||
|
||||
def get_relocs(self, symbol_name: str) -> Generator[tuple[int, int, str], None, None]:
|
||||
"""Return relocation offset relative to striped symbol start.
|
||||
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.
|
||||
def get_patch_positions(self, symbol_name: str) -> Generator[patch_entry, None, None]:
|
||||
"""Return patch positions
|
||||
"""
|
||||
symbol = self.elf.symbols[symbol_name]
|
||||
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:
|
||||
|
||||
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:
|
||||
yield (reloc_offset, reloc.bits, reloc.type)
|
||||
# Exclude the call to the result_x function
|
||||
if patch.addr < end_index - start_index - LENGTH_CALL_INSTRUCTION:
|
||||
yield patch
|
||||
|
||||
|
||||
def get_func_data(self, name: str) -> bytes:
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@
|
|||
#define COPY_DATA 2
|
||||
#define ALLOCATE_CODE 3
|
||||
#define COPY_CODE 4
|
||||
#define RELOCATE_FUNC 5
|
||||
#define RELOCATE_OBJECT 6
|
||||
#define PATCH_FUNC 5
|
||||
#define PATCH_OBJECT 6
|
||||
#define SET_ENTR_POINT 64
|
||||
#define END_PROG 255
|
||||
|
||||
#define RELOC_RELATIVE_32 0
|
||||
#define PATCH_RELATIVE_32 0
|
||||
|
||||
uint8_t *data_memory;
|
||||
uint8_t *executable_memory;
|
||||
|
|
@ -53,8 +53,8 @@ void patch_mem_32(uint8_t *patch_addr, int32_t value){
|
|||
*val_ptr = value;
|
||||
}
|
||||
|
||||
int relocate(uint8_t *patch_addr, uint32_t reloc_type, int32_t value){
|
||||
if (reloc_type == RELOC_RELATIVE_32){
|
||||
int patch(uint8_t *patch_addr, uint32_t reloc_type, int32_t value){
|
||||
if (reloc_type == PATCH_RELATIVE_32){
|
||||
patch_mem_32(patch_addr, value);
|
||||
}else{
|
||||
printf("Not implemented");
|
||||
|
|
@ -104,27 +104,27 @@ int parse_commands(uint8_t *bytes){
|
|||
memcpy(executable_memory + offs, bytes, size); bytes += size;
|
||||
break;
|
||||
|
||||
case RELOCATE_FUNC:
|
||||
case PATCH_FUNC:
|
||||
offs = *(uint32_t*)bytes; bytes += 4;
|
||||
reloc_type = *(uint32_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);
|
||||
relocate(executable_memory + offs, reloc_type, value);
|
||||
patch(executable_memory + offs, reloc_type, value);
|
||||
break;
|
||||
|
||||
case RELOCATE_OBJECT:
|
||||
case PATCH_OBJECT:
|
||||
offs = *(uint32_t*)bytes; bytes += 4;
|
||||
reloc_type = *(uint32_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);
|
||||
data_offs = (int32_t)(data_memory - executable_memory);
|
||||
if (abs(data_offs) > 0x7FFFFFFF) {
|
||||
perror("code and data memory to far apart");
|
||||
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);
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
#from diss_helper import dmprint
|
||||
import pelfy
|
||||
#from IPython.display import Markdown
|
||||
|
||||
from typing import Literal
|
||||
from copapy import Op, Write, const
|
||||
from copapy import Write, const
|
||||
import copapy as rc
|
||||
from copapy.binwrite import data_writer, Command, RelocationType, get_variable_data, get_function_data, translate_relocation
|
||||
|
||||
def test_compile():
|
||||
c1 = const(1.11)
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ if __name__ == "__main__":
|
|||
print('----')
|
||||
#print(sdb.function_definitions)
|
||||
for sym_name in sdb.function_definitions.keys():
|
||||
print('-', sym_name)
|
||||
print(list(sdb.get_relocs(sym_name)))
|
||||
print('\n-', sym_name)
|
||||
print(list(sdb.get_patch_positions(sym_name)))
|
||||
Loading…
Reference in New Issue