mirror of https://github.com/Nonannet/copapy.git
python module is working. no return values yet.
This commit is contained in:
parent
672a67837f
commit
6625da1a47
|
|
@ -14,3 +14,5 @@ test.copapy
|
|||
token.txt
|
||||
/src/copapy/obj/*.o
|
||||
runmem2
|
||||
src/*.so
|
||||
bin/*
|
||||
|
|
|
|||
2
build.sh
2
build.sh
|
|
@ -9,5 +9,5 @@ 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
|
||||
|
||||
mkdir bin -p
|
||||
gcc -Wall -Wextra -Wconversion -Wsign-conversion -Wshadow -Wstrict-overflow -Werror -g src/coparun/coparun.c src/coparun/runmem.c -o bin/coparun
|
||||
gcc -Wall -Wextra -Wconversion -Wsign-conversion -Wshadow -Wstrict-overflow -Werror -g src/coparun/runmem.c src/coparun/coparun.c -o bin/coparun
|
||||
#x86_64-w64-mingw32-gcc -Wall -Wextra -Wconversion -Wsign-conversion -Wshadow -Wstrict-overflow -Werror src/runner/runmem2.c -Wall -O3 -o bin/runmem2.exe
|
||||
|
|
@ -30,9 +30,6 @@ where = ["src"]
|
|||
[tool.setuptools.package-data]
|
||||
copapy = ["*.o"]
|
||||
|
||||
[tool.setuptools.ext_modules]
|
||||
coparun = { sources = ["src/coparun/coparun_module.c"] }
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"flake8",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
from setuptools import setup, Extension
|
||||
|
||||
ext = Extension(
|
||||
"coparun_module",
|
||||
sources=[
|
||||
"src/coparun/coparun_module.c",
|
||||
"src/coparun/runmem.c"
|
||||
]
|
||||
)
|
||||
|
||||
setup(
|
||||
ext_modules=[ext],
|
||||
)
|
||||
|
|
@ -163,9 +163,11 @@ def stable_toposort(edges: Iterable[tuple[Node, Node]]) -> list[Node]:
|
|||
pos = 0
|
||||
for u, v in edges:
|
||||
if u not in order:
|
||||
order[u] = pos; pos += 1
|
||||
order[u] = pos
|
||||
pos += 1
|
||||
if v not in order:
|
||||
order[v] = pos; pos += 1
|
||||
order[v] = pos
|
||||
pos += 1
|
||||
adj[u].append(v)
|
||||
indeg[v] += 1
|
||||
indeg.setdefault(u, 0)
|
||||
|
|
@ -306,7 +308,6 @@ def compile_to_instruction_list(end_nodes: Iterable[Node] | Node) -> binw.data_w
|
|||
|
||||
# Get all nets associated with heap memory
|
||||
variable_list = get_nets([[const_net_list]], extended_output_ops)
|
||||
assert(len(set(variable_list)) == len(variable_list)), 'Duplicates!'
|
||||
|
||||
dw = binw.data_writer(sdb.byteorder)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ Command = Enum('Command', [('ALLOCATE_DATA', 1), ('COPY_DATA', 2),
|
|||
('ALLOCATE_CODE', 3), ('COPY_CODE', 4),
|
||||
('PATCH_FUNC', 5), ('PATCH_OBJECT', 6),
|
||||
('SET_ENTR_POINT', 64), ('READ_DATA', 65),
|
||||
('END_PROG', 255)])
|
||||
('END_PROG', 256), ('FREE_MEMORY', 257)])
|
||||
|
||||
|
||||
class data_writer():
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include "runmem.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <binary_file>\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Open the file
|
||||
int fd = open(argv[1], O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Get file size
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0) {
|
||||
perror("fstat");
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (st.st_size == 0) {
|
||||
fprintf(stderr, "Error: File is empty\n");
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
//uint8_t *file_buff = get_data_memory((uint32_t)st.st_size);
|
||||
uint8_t *file_buff = (uint8_t*)malloc((size_t)st.st_size);
|
||||
|
||||
// Read file into allocated memory
|
||||
if (read(fd, file_buff, (long unsigned int)st.st_size) != st.st_size) {
|
||||
perror("read");
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
parse_commands(file_buff);
|
||||
|
||||
free_memory();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,31 +1,46 @@
|
|||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Python.h>
|
||||
#include "runmem.h"
|
||||
|
||||
// A simple C function exposed to Python
|
||||
static PyObject* my_function(PyObject* self, PyObject* args) {
|
||||
int a, b;
|
||||
if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
|
||||
return NULL; // Error if arguments aren't two integers
|
||||
}
|
||||
return PyLong_FromLong(a + b); // Return sum as Python integer
|
||||
/*
|
||||
* coparun(PyObject *self, PyObject *args)
|
||||
* Accepts a Python `bytes` (or objects supporting the buffer protocol).
|
||||
* We use the "y#" format in PyArg_ParseTuple which returns a pointer to
|
||||
* the internal bytes buffer and its length (Py_ssize_t). For safety and
|
||||
* performance we pass that pointer directly to parse_commands which expects
|
||||
* a uint8_t* buffer. If parse_commands needs the length, consider
|
||||
* extending its API to accept a length parameter.
|
||||
*/
|
||||
static PyObject* coparun(PyObject* self, PyObject* args) {
|
||||
const char *buf;
|
||||
Py_ssize_t buf_len;
|
||||
int result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "y#", &buf, &buf_len)) {
|
||||
return NULL; /* TypeError set by PyArg_ParseTuple */
|
||||
}
|
||||
|
||||
/* If parse_commands may run for a long time, release the GIL. */
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
result = parse_commands((uint8_t*)buf);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
return PyLong_FromLong(result);
|
||||
}
|
||||
|
||||
// Method definitions
|
||||
static PyMethodDef MyMethods[] = {
|
||||
{"add", my_function, METH_VARARGS, "Adds two numbers"},
|
||||
{NULL, NULL, 0, NULL} // Sentinel
|
||||
{"coparun", coparun, METH_VARARGS, "Pass raw command data to coparun"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
// Module definition
|
||||
static struct PyModuleDef my_module = {
|
||||
static struct PyModuleDef coparun_module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"my_module", // Module name
|
||||
"coparun_module", // Module name
|
||||
NULL, // Documentation
|
||||
-1, // Size of per-interpreter state (-1 for global)
|
||||
MyMethods
|
||||
};
|
||||
|
||||
// Module initialization function
|
||||
PyMODINIT_FUNC PyInit_my_module(void) {
|
||||
return PyModule_Create(&my_module);
|
||||
PyMODINIT_FUNC PyInit_coparun_module(void) {
|
||||
return PyModule_Create(&coparun_module);
|
||||
}
|
||||
|
|
@ -6,23 +6,14 @@
|
|||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "runmem.h"
|
||||
|
||||
#define ALLOCATE_DATA 1
|
||||
#define COPY_DATA 2
|
||||
#define ALLOCATE_CODE 3
|
||||
#define COPY_CODE 4
|
||||
#define PATCH_FUNC 5
|
||||
#define PATCH_OBJECT 6
|
||||
#define SET_ENTR_POINT 64
|
||||
#define READ_DATA 65
|
||||
#define END_PROG 255
|
||||
|
||||
#define PATCH_RELATIVE_32 0
|
||||
|
||||
uint8_t *data_memory;
|
||||
uint8_t *executable_memory;
|
||||
uint32_t executable_memory_len;
|
||||
int (*entr_point)();
|
||||
/* Definitions for globals declared extern in runmem.h */
|
||||
uint8_t *data_memory = NULL;
|
||||
uint32_t data_memory_len = 0;
|
||||
uint8_t *executable_memory = NULL;
|
||||
uint32_t executable_memory_len = 0;
|
||||
entry_point_t entr_point = NULL;
|
||||
|
||||
uint8_t *get_executable_memory(uint32_t num_bytes){
|
||||
// Allocate executable memory
|
||||
|
|
@ -64,6 +55,13 @@ int patch(uint8_t *patch_addr, uint32_t reloc_type, int32_t value){
|
|||
return 1;
|
||||
}
|
||||
|
||||
void free_memory(){
|
||||
if (executable_memory_len) munmap(executable_memory, executable_memory_len);
|
||||
if (data_memory_len) munmap(data_memory, data_memory_len);
|
||||
data_memory_len = 0;
|
||||
executable_memory_len = 0;
|
||||
}
|
||||
|
||||
int parse_commands(uint8_t *bytes){
|
||||
int32_t value;
|
||||
uint32_t command;
|
||||
|
|
@ -78,9 +76,15 @@ int parse_commands(uint8_t *bytes){
|
|||
command = *(uint32_t*)bytes;
|
||||
bytes += 4;
|
||||
switch(command) {
|
||||
case FREE_MEMORY:
|
||||
size = *(uint32_t*)bytes; bytes += 4;
|
||||
free_memory();
|
||||
break;
|
||||
|
||||
case ALLOCATE_DATA:
|
||||
size = *(uint32_t*)bytes; bytes += 4;
|
||||
data_memory = get_data_memory(size);
|
||||
data_memory_len = size;
|
||||
printf("ALLOCATE_DATA size=%i mem_addr=%p\n", size, (void*)data_memory);
|
||||
break;
|
||||
|
||||
|
|
@ -163,47 +167,3 @@ int parse_commands(uint8_t *bytes){
|
|||
}
|
||||
return err_flag;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <binary_file>\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Open the file
|
||||
int fd = open(argv[1], O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Get file size
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0) {
|
||||
perror("fstat");
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (st.st_size == 0) {
|
||||
fprintf(stderr, "Error: File is empty\n");
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
//uint8_t *file_buff = get_data_memory((uint32_t)st.st_size);
|
||||
uint8_t *file_buff = (uint8_t*)malloc((size_t)st.st_size);
|
||||
|
||||
// Read file into allocated memory
|
||||
if (read(fd, file_buff, (long unsigned int)st.st_size) != st.st_size) {
|
||||
perror("read");
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
parse_commands(file_buff);
|
||||
|
||||
munmap(executable_memory, executable_memory_len);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef RUNMEM_H
|
||||
#define RUNMEM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Command opcodes used by the parser */
|
||||
#define ALLOCATE_DATA 1
|
||||
#define COPY_DATA 2
|
||||
#define ALLOCATE_CODE 3
|
||||
#define COPY_CODE 4
|
||||
#define PATCH_FUNC 5
|
||||
#define PATCH_OBJECT 6
|
||||
#define SET_ENTR_POINT 64
|
||||
#define READ_DATA 65
|
||||
#define END_PROG 256
|
||||
#define FREE_MEMORY 257
|
||||
|
||||
/* Relocation types */
|
||||
#define PATCH_RELATIVE_32 0
|
||||
|
||||
/* Memory blobs accessible by other translation units */
|
||||
extern uint8_t *data_memory;
|
||||
extern uint32_t data_memory_len;
|
||||
extern uint8_t *executable_memory;
|
||||
extern uint32_t executable_memory_len;
|
||||
|
||||
/* Entry point type and variable */
|
||||
typedef int (*entry_point_t)(void);
|
||||
extern entry_point_t entr_point;
|
||||
|
||||
|
||||
/* Command parser: takes a pointer to the command stream and returns
|
||||
an error flag (0 on success according to current code) */
|
||||
int parse_commands(uint8_t *bytes);
|
||||
|
||||
/* Free program and data memory */
|
||||
void free_memory();
|
||||
|
||||
#endif /* RUNMEM_H */
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
from copapy import Write, const, Node
|
||||
from copapy import Write, const
|
||||
import copapy as rc
|
||||
from typing import Iterable, Generator
|
||||
|
||||
|
||||
def test_ast_generation():
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from copapy import Write, const
|
|||
import copapy
|
||||
import subprocess
|
||||
import struct
|
||||
from copapy import binwrite as binw
|
||||
from copapy import binwrite
|
||||
|
||||
|
||||
def run_command(command: list[str], encoding: str = 'utf8') -> str:
|
||||
|
|
@ -60,12 +60,12 @@ def test_compile():
|
|||
copapy.read_variable(il, r1)
|
||||
copapy.read_variable(il, r2)
|
||||
|
||||
il.write_com(binw.Command.READ_DATA)
|
||||
il.write_com(binwrite.Command.READ_DATA)
|
||||
il.write_int(0)
|
||||
il.write_int(36)
|
||||
|
||||
# run program command
|
||||
il.write_com(binw.Command.END_PROG)
|
||||
il.write_com(binwrite.Command.END_PROG)
|
||||
|
||||
print('* Data to runner:')
|
||||
il.print()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
from coparun_module import coparun
|
||||
from copapy import Write, const
|
||||
import copapy
|
||||
from copapy import binwrite
|
||||
|
||||
|
||||
def test_compile():
|
||||
|
||||
c1 = const(4)
|
||||
c2 = const(2)
|
||||
|
||||
i1 = c1 * 2
|
||||
r1 = i1 + 7 + (c2 + 7 * 9)
|
||||
r2 = i1 + 9
|
||||
out = [Write(r1), Write(r2)]
|
||||
|
||||
il = copapy.compile_to_instruction_list(out)
|
||||
|
||||
copapy.read_variable(il, r1)
|
||||
copapy.read_variable(il, r2)
|
||||
|
||||
il.write_com(binwrite.Command.READ_DATA)
|
||||
il.write_int(0)
|
||||
il.write_int(36)
|
||||
|
||||
# run program command
|
||||
il.write_com(binwrite.Command.END_PROG)
|
||||
|
||||
#print('* Data to runner:')
|
||||
#il.print()
|
||||
|
||||
print('+ run coparun')
|
||||
result = coparun(il.get_data())
|
||||
|
||||
assert result == 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_compile()
|
||||
Loading…
Reference in New Issue