mirror of https://github.com/Nonannet/copapy.git
no segfault anymore
This commit is contained in:
parent
8bb75ba58b
commit
f53dd5ee51
|
|
@ -1,13 +1,16 @@
|
|||
backend/index/*
|
||||
/backend/index/*
|
||||
__pycache__
|
||||
*.code-workspace
|
||||
*.egg.info
|
||||
/src/*.egg-info/*
|
||||
/dist/*
|
||||
.vscode
|
||||
.venv
|
||||
.mypy_cache
|
||||
.pytest_cache
|
||||
tests/autogenerated_*.py
|
||||
/tests/autogenerated_*.py
|
||||
*test*.o
|
||||
/src/copapy/obj/ops*.o
|
||||
test.copapy
|
||||
token.txt
|
||||
/src/copapy/obj/*.o
|
||||
runmem2
|
||||
|
|
|
|||
|
|
@ -7,4 +7,3 @@ gcc -c src/copapy/stencils.c -o src/copapy/obj/stencils_x86_64.o
|
|||
gcc -c src/copapy/stencils.c -O1 -o src/copapy/obj/stencils_x86_64_O1.o
|
||||
gcc -c src/copapy/stencils.c -O2 -o src/copapy/obj/stencils_x86_64_O2.o
|
||||
gcc -c src/copapy/stencils.c -O3 -o src/copapy/obj/stencils_x86_64_O3.o
|
||||
ls -l src/copapy/obj/*.o
|
||||
|
|
@ -7,7 +7,7 @@ authors = [
|
|||
description = "Copy-Patch Compiler"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
license = "MIT"
|
||||
license = "GPL-3.0-only"
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3",
|
||||
"Operating System :: OS Independent",
|
||||
|
|
|
|||
|
|
@ -338,20 +338,30 @@ def compile_to_instruction_list(end_nodes: Iterable[Node] | Node) -> binw.data_w
|
|||
|
||||
print('object_addr_lookp: ', object_addr_lookp)
|
||||
|
||||
data = sdb.get_func_data('function_start')
|
||||
data_list.append(data)
|
||||
offset += len(data)
|
||||
|
||||
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))
|
||||
print(f"* {node.name} ({offset}) " + ' '.join(f'{d:02X}' for d in data))
|
||||
|
||||
for patch in sdb.get_patch_positions(node.name):
|
||||
assert result_net, f"Relocation found but no net defined for operation {node.name}"
|
||||
object_addr = object_addr_lookp[result_net]
|
||||
print('patch: ', patch, offset + patch.addr)
|
||||
patch_list.append((patch.type.value, offset + patch.addr, object_addr))
|
||||
patch_value = object_addr + patch.addend - (offset + patch.addr)
|
||||
print('patch: ', patch, object_addr, patch_value)
|
||||
patch_list.append((patch.type.value, offset + patch.addr, patch_value))
|
||||
|
||||
offset += len(data)
|
||||
|
||||
data = sdb.get_func_data('function_end')
|
||||
data_list.append(data)
|
||||
offset += len(data)
|
||||
print('function_end', offset, data)
|
||||
|
||||
# allocate program data
|
||||
dw.write_com(binw.Command.ALLOCATE_CODE)
|
||||
dw.write_int(offset)
|
||||
|
|
@ -367,7 +377,7 @@ def compile_to_instruction_list(end_nodes: Iterable[Node] | Node) -> binw.data_w
|
|||
dw.write_com(binw.Command.PATCH_OBJECT)
|
||||
dw.write_int(patch_addr)
|
||||
dw.write_int(patch_type)
|
||||
dw.write_int(object_addr)
|
||||
dw.write_int(object_addr, signed=True)
|
||||
|
||||
# set entry point
|
||||
dw.write_com(binw.Command.SET_ENTR_POINT)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,22 @@ from typing import Generator
|
|||
op_signs = {'add': '+', 'sub': '-', 'mul': '*', 'div': '/'}
|
||||
|
||||
|
||||
def get_function_start():
|
||||
return """
|
||||
void function_start(){
|
||||
result_int(0);
|
||||
asm volatile (".long 0xF27ECAFE");
|
||||
}
|
||||
"""
|
||||
|
||||
def get_function_end():
|
||||
return """
|
||||
void function_end(){
|
||||
result_int(0);
|
||||
asm volatile (".long 0xF17ECAFE");
|
||||
}
|
||||
"""
|
||||
|
||||
def get_op_code(op: str, type1: str, type2: str, type_out: str):
|
||||
return f"""
|
||||
void {op}_{type1}_{type2}({type1} arg1, {type2} arg2) {{
|
||||
|
|
@ -95,5 +111,7 @@ if __name__ == "__main__":
|
|||
for t1 in types:
|
||||
code += get_write_code(t1)
|
||||
|
||||
code += get_function_start() + get_function_end()
|
||||
|
||||
with open('src/copapy/stencils.c', 'w') as f:
|
||||
f.write(code)
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -3,11 +3,13 @@ import pelfy
|
|||
from typing import Generator, Literal
|
||||
from enum import Enum
|
||||
|
||||
ByteOrder = Literal['little', 'big']
|
||||
|
||||
start_marker = 0xF17ECAFE
|
||||
end_marker = 0xF27ECAFE
|
||||
START_MARKER = 0xF17ECAFE
|
||||
END_MARKER = 0xF27ECAFE
|
||||
MARKER_LENGTH = 4
|
||||
|
||||
LENGTH_CALL_INSTRUCTION = 4 # x86_64
|
||||
LENGTH_CALL_INSTRUCTION = 5 # x86_64
|
||||
|
||||
RelocationType = Enum('RelocationType', [('RELOC_RELATIVE_32', 0)])
|
||||
|
||||
|
|
@ -22,37 +24,45 @@ class patch_entry:
|
|||
|
||||
type: RelocationType
|
||||
addr: int
|
||||
addend: 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)
|
||||
patch_offset = relocation_addr
|
||||
return patch_entry(RelocationType.RELOC_RELATIVE_32, patch_offset, r_addend)
|
||||
else:
|
||||
raise Exception(f"Unknown: {reloc_type}")
|
||||
|
||||
|
||||
def get_ret_function_def(symbol: pelfy.elf_symbol):
|
||||
#print('*', symbol.name, symbol.section)
|
||||
def get_ret_function_def(symbol: pelfy.elf_symbol) -> str:
|
||||
#print('*', symbol.name, len(symbol.relocations))
|
||||
if symbol.relocations:
|
||||
result_func = symbol.relocations[-1].symbol
|
||||
|
||||
assert result_func.name.startswith('result_')
|
||||
return result_func.name[7:]
|
||||
else:
|
||||
return 'void'
|
||||
|
||||
|
||||
def strip_symbol(data: bytes, byteorder: Literal['little', 'big']) -> bytes:
|
||||
def strip_symbol(data: bytes, byteorder: ByteOrder) -> bytes:
|
||||
"""Return data between start and end marker and removing last instruction (call)"""
|
||||
start_index, end_index = get_stencil_position(data, byteorder)
|
||||
return data[start_index:end_index]
|
||||
|
||||
|
||||
def get_stencil_position(data: bytes, byteorder: ByteOrder) -> tuple[int, int]:
|
||||
# Find first start marker
|
||||
start_index = data.find(start_marker.to_bytes(4, byteorder))
|
||||
marker_index = data.find(START_MARKER.to_bytes(MARKER_LENGTH, byteorder))
|
||||
start_index = 0 if marker_index < 0 else marker_index + MARKER_LENGTH
|
||||
|
||||
# Find last end marker
|
||||
end_index = data.rfind(end_marker.to_bytes(4, byteorder), start_index)
|
||||
|
||||
assert start_index > -1 and end_index > -1, f"Marker not found"
|
||||
return data[start_index + 4:end_index - LENGTH_CALL_INSTRUCTION]
|
||||
end_index = data.rfind(END_MARKER.to_bytes(MARKER_LENGTH, byteorder))
|
||||
end_index = len(data) if end_index < 0 else end_index - LENGTH_CALL_INSTRUCTION
|
||||
|
||||
return start_index, end_index
|
||||
|
||||
|
||||
class stencil_database():
|
||||
|
|
@ -82,8 +92,7 @@ class stencil_database():
|
|||
"""Return patch positions
|
||||
"""
|
||||
symbol = self.elf.symbols[symbol_name]
|
||||
start_index = symbol.data.find(start_marker.to_bytes(4, symbol.file.byteorder))
|
||||
end_index = symbol.data.rfind(end_marker.to_bytes(4, symbol.file.byteorder), start_index)
|
||||
start_index, end_index = get_stencil_position(symbol.data, symbol.file.byteorder)
|
||||
|
||||
for reloc in symbol.relocations:
|
||||
|
||||
|
|
@ -95,7 +104,7 @@ class stencil_database():
|
|||
reloc.fields['r_addend'])
|
||||
|
||||
# Exclude the call to the result_x function
|
||||
if patch.addr < end_index - start_index - LENGTH_CALL_INSTRUCTION:
|
||||
if patch.addr < end_index - start_index:
|
||||
yield patch
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -223,3 +223,13 @@
|
|||
asm volatile (".long 0xF27ECAFE");
|
||||
}
|
||||
|
||||
void function_start(){
|
||||
result_int(0);
|
||||
asm volatile (".long 0xF27ECAFE");
|
||||
}
|
||||
|
||||
void function_end(){
|
||||
result_int(0);
|
||||
asm volatile (".long 0xF17ECAFE");
|
||||
}
|
||||
|
||||
|
|
@ -71,6 +71,7 @@ int parse_commands(uint8_t *bytes){
|
|||
int data_offs;
|
||||
uint32_t size;
|
||||
int err_flag = 0;
|
||||
uint32_t rel_entr_point;
|
||||
|
||||
while(!err_flag){
|
||||
command = *(uint32_t*)bytes;
|
||||
|
|
@ -78,8 +79,8 @@ int parse_commands(uint8_t *bytes){
|
|||
switch(command) {
|
||||
case ALLOCATE_DATA:
|
||||
size = *(uint32_t*)bytes; bytes += 4;
|
||||
printf("ALLOCATE_DATA size=%i\n", size);
|
||||
data_memory = get_data_memory(size);
|
||||
printf("ALLOCATE_DATA size=%i mem_addr=%p\n", size, (void*)data_memory);
|
||||
break;
|
||||
|
||||
case COPY_DATA:
|
||||
|
|
@ -91,9 +92,9 @@ int parse_commands(uint8_t *bytes){
|
|||
|
||||
case ALLOCATE_CODE:
|
||||
size = *(uint32_t*)bytes; bytes += 4;
|
||||
printf("ALLOCATE_CODE size=%i\n", size);
|
||||
executable_memory = get_executable_memory(size);
|
||||
executable_memory_len = size;
|
||||
printf("ALLOCATE_CODE size=%i mem_addr=%p\n", size, (void*)executable_memory);
|
||||
//printf("# d %i c %i off %i\n", data_memory, executable_memory, data_offs);
|
||||
break;
|
||||
|
||||
|
|
@ -117,19 +118,19 @@ int parse_commands(uint8_t *bytes){
|
|||
offs = *(uint32_t*)bytes; bytes += 4;
|
||||
reloc_type = *(uint32_t*)bytes; bytes += 4;
|
||||
value = *(int32_t*)bytes; bytes += 4;
|
||||
printf("PATCH_OBJECT patch_offs=%i reloc_type=%i value=%i\n",
|
||||
offs, reloc_type, value);
|
||||
data_offs = (int32_t)(data_memory - executable_memory);
|
||||
//printf("PATCH_OBJECT patch_offs=%i reloc_type=%i value=%i data_offs=%i\n",
|
||||
// offs, reloc_type, value, data_offs);
|
||||
if (abs(data_offs) > 0x7FFFFFFF) {
|
||||
perror("code and data memory to far apart");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
patch(executable_memory + offs, reloc_type, value + (int32_t)data_offs);
|
||||
patch(executable_memory + offs, reloc_type, value + data_offs);
|
||||
//printf("> %i\n", data_offs);
|
||||
break;
|
||||
|
||||
case SET_ENTR_POINT:
|
||||
uint32_t rel_entr_point = *(uint32_t*)bytes; bytes += 4;
|
||||
rel_entr_point = *(uint32_t*)bytes; bytes += 4;
|
||||
printf("SET_ENTR_POINT rel_entr_point=%i\n", rel_entr_point);
|
||||
entr_point = (int (*)())(executable_memory + rel_entr_point);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
echo "Compile..."
|
||||
python tests/test_compile.py
|
||||
echo "Run..."
|
||||
echo "-----------------------------------"
|
||||
gcc -Wall -Wextra -Wconversion -Wsign-conversion -Wshadow -Wstrict-overflow -Werror -g src/runner/runmem2.c -o runmem2
|
||||
./runmem2 test.copapy
|
||||
|
|
@ -1,9 +1,26 @@
|
|||
from copapy import stencil_database
|
||||
from copapy import stencil_db
|
||||
|
||||
if __name__ == "__main__":
|
||||
def test_list_symbols():
|
||||
sdb = stencil_database('src/copapy/obj/stencils_x86_64_O3.o')
|
||||
print('----')
|
||||
#print(sdb.function_definitions)
|
||||
for sym_name in sdb.function_definitions.keys():
|
||||
print('\n-', sym_name)
|
||||
print(list(sdb.get_patch_positions(sym_name)))
|
||||
|
||||
|
||||
def test_start_end_function():
|
||||
sdb = stencil_database('src/copapy/obj/stencils_x86_64_O3.o')
|
||||
for sym_name in sdb.function_definitions.keys():
|
||||
data = sdb.elf.symbols[sym_name].data
|
||||
print('-', sym_name, stencil_db.get_stencil_position(data, sdb.elf.byteorder), len(data))
|
||||
|
||||
start, end = stencil_db.get_stencil_position(data, sdb.elf.byteorder)
|
||||
|
||||
assert start>= 0 and end >= start and end <= len(data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_list_symbols()
|
||||
test_start_end_function()
|
||||
Loading…
Reference in New Issue