From 32823e1f86402b95b6544110dd61495e2e9d788e Mon Sep 17 00:00:00 2001 From: Axy Date: Mon, 1 Jun 2026 19:12:22 +0200 Subject: [PATCH] mini obj files --- .deps | 9 ++++- .gitignore | 1 - Makefile | 4 +-- conf.mk | 4 +-- src/ccera.h | 4 ++- src/execalloc.c | 45 +++++++++++++++++++++++++ src/execalloc.h | 18 ++++++++++ src/miniobj.c | 75 ++++++++++++++++++++++++++++++++++++++++++ src/miniobj.h | 55 +++++++++++++++++++++++++++++++ src/miniobj_lifetime.c | 30 +++++++++++++++++ src/vec.h | 34 +++++++++++++++++++ test.c | 31 +++++++++++++++-- 12 files changed, 301 insertions(+), 9 deletions(-) create mode 100644 src/execalloc.c create mode 100644 src/execalloc.h create mode 100644 src/miniobj.c create mode 100644 src/miniobj.h create mode 100644 src/miniobj_lifetime.c create mode 100644 src/vec.h diff --git a/.deps b/.deps index c143355..cee5ecb 100644 --- a/.deps +++ b/.deps @@ -38,9 +38,16 @@ ${BUILDDIR}/defer.o: src/defer.c src/defer.h src/framealloc.h src/align.h \ ${BUILDDIR}/eval.o: src/eval.c src/ccera.h src/jmp.h src/defer.h src/framealloc.h \ src/align.h src/stacktrack.h src/memutils.h src/panic.h src/value.h \ src/value_get.h src/value_types.h src/value_new.h src/arith.h \ - src/arc.h src/atomic.h src/builtin_register.h + src/arc.h src/atomic.h src/builtin_register.h src/execalloc.h \ + src/miniobj.h +${BUILDDIR}/execalloc.o: src/execalloc.c src/panic.h src/jmp.h ${BUILDDIR}/framealloc.o: src/framealloc.c src/framealloc.h src/align.h \ src/stacktrack.h +${BUILDDIR}/miniobj.o: src/miniobj.c src/miniobj.h src/panic.h src/jmp.h src/defer.h \ + src/framealloc.h src/align.h src/stacktrack.h src/memutils.h src/vec.h \ + src/execalloc.h +${BUILDDIR}/miniobj_lifetime.o: src/miniobj_lifetime.c src/miniobj.h src/memutils.h \ + src/panic.h src/jmp.h ${BUILDDIR}/panic.o: src/panic.c src/panic.h src/jmp.h src/defer.h src/framealloc.h \ src/align.h src/stacktrack.h src/memutils.h ${BUILDDIR}/stacktrack.o: src/stacktrack.c src/stacktrack.h diff --git a/.gitignore b/.gitignore index b929644..2278ee6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ a.out vgcore.* .direnv .norm_fail -Makefile.tmp *.tmp flamegraph.svg perf.data diff --git a/Makefile b/Makefile index 08a8e86..5df2d45 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ NAME=ccera.a -SRCS=src/arc.c src/builtin_add.c src/builtin.c src/builtin_list_get.c src/builtin_list_set.c src/builtin_list_set_drop.c src/builtin_lte.c src/builtin_mul.c src/builtin_noop.c src/builtin_register.c src/builtin_sub.c src/defer.c src/eval.c src/framealloc.c src/panic.c src/stacktrack.c src/value_debug.c src/value_lifetime.c src/value_list.c src/value_move.c src/value_new.c src/value_new_utils.c +SRCS=src/arc.c src/builtin_add.c src/builtin.c src/builtin_list_get.c src/builtin_list_set.c src/builtin_list_set_drop.c src/builtin_lte.c src/builtin_mul.c src/builtin_noop.c src/builtin_register.c src/builtin_sub.c src/defer.c src/eval.c src/execalloc.c src/framealloc.c src/miniobj.c src/miniobj_lifetime.c src/panic.c src/stacktrack.c src/value_debug.c src/value_lifetime.c src/value_list.c src/value_move.c src/value_new.c src/value_new_utils.c -HEADERS=src/align.h src/arc.h src/arith.h src/atomic.h src/builtin_register.h src/ccera.h src/defer.h src/framealloc.h src/jmp.h src/memutils.h src/panic.h src/stacktrack.h src/value_get.h src/value.h src/value_new.h src/value_types.h +HEADERS=src/align.h src/arc.h src/arith.h src/atomic.h src/builtin_register.h src/ccera.h src/defer.h src/execalloc.h src/framealloc.h src/jmp.h src/memutils.h src/miniobj.h src/panic.h src/stacktrack.h src/value_get.h src/value.h src/value_new.h src/value_types.h src/vec.h CC = cc diff --git a/conf.mk b/conf.mk index 35cb9ab..c54d73c 100644 --- a/conf.mk +++ b/conf.mk @@ -1,5 +1,5 @@ -LTO=1 -OPT=1 +LTO=0 +OPT=0 CC=clang #UBSAN=1 #TSAN=1 diff --git a/src/ccera.h b/src/ccera.h index 14487eb..4207780 100644 --- a/src/ccera.h +++ b/src/ccera.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/04/29 16:08:57 by agilliar #+# #+# */ -/* Updated: 2026/05/20 14:06:31 by agilliar ### ########.fr */ +/* Updated: 2026/06/01 18:27:59 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,6 +23,8 @@ # include "stacktrack.h" # include "atomic.h" # include "builtin_register.h" +# include "execalloc.h" +# include "miniobj.h" // The expression value is a tuple of an evaluatable and the argument to give it // diff --git a/src/execalloc.c b/src/execalloc.c new file mode 100644 index 0000000..e172070 --- /dev/null +++ b/src/execalloc.c @@ -0,0 +1,45 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* execalloc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/29 19:54:36 by agilliar #+# #+# */ +/* Updated: 2026/06/01 18:43:36 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include "panic.h" + +#define EXECALLOC_SIZE_N 1000000 +#define EXECALLOC_SIZE "1000000" + +asm ( + ".section rwx, \"awx\"\n" + ".global _execalloc_store\n" + "_execalloc_store:\n" + ".zero " EXECALLOC_SIZE "\n" + ".size _execaclloc_store, " EXECALLOC_SIZE "\n" + ); + +char *execalloc(size_t n) +{ + static size_t used = 0; + extern char _execalloc_store[EXECALLOC_SIZE_N]; + size_t prev_used; + size_t next_used; + + while (true) + { + prev_used = __atomic_load_n(&used, __ATOMIC_RELAXED); + if (__builtin_add_overflow(prev_used, n, &next_used) + || next_used > EXECALLOC_SIZE_N) + panic("execalloc failed"); + if (__atomic_compare_exchange_n(&used, &prev_used, next_used, + true, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) + return (&_execalloc_store[prev_used]); + } +} diff --git a/src/execalloc.h b/src/execalloc.h new file mode 100644 index 0000000..70f9535 --- /dev/null +++ b/src/execalloc.h @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* execalloc.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/31 22:52:39 by agilliar #+# #+# */ +/* Updated: 2026/05/31 23:51:15 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef EXECALLOC_H +# define EXECALLOC_H + +char *execalloc(size_t n); + +#endif diff --git a/src/miniobj.c b/src/miniobj.c new file mode 100644 index 0000000..820819a --- /dev/null +++ b/src/miniobj.c @@ -0,0 +1,75 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* miniobj.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/31 22:55:45 by agilliar #+# #+# */ +/* Updated: 2026/06/01 18:55:02 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include "miniobj.h" +#include "panic.h" +#include "defer.h" +#include "memutils.h" +#include "vec.h" +#include "execalloc.h" + +void miniobj_write_s(t_miniobj *obj, const char *s) +{ + miniobj_write(obj, s, cera_strlen(s)); +} + +void miniobj_write(t_miniobj *obj, const char *s, size_t n) +{ + vec_grow((void **) &obj->byte_buf, &obj->byte_capacity, obj->byte_len + n); + cera_memcpy(&obj->byte_buf[obj->byte_len], s, n); + obj->byte_len += n; +} + +t_objaddr miniobj_label(t_miniobj *obj, t_label label) +{ + obj->resolved_labels[label] = obj->byte_len; + return (obj->byte_len); +} + +void miniobj_write_reloc(t_miniobj *obj, t_label label, t_reloc_kind kind) +{ + const uintptr_t s = 0; + + vec_grow((void **) &obj->reloc_buf, + &obj->reloc_capacity, (obj->reloc_len + 1) * sizeof(t_relocation)); + obj->reloc_buf[obj->reloc_len] = (t_relocation){obj->byte_len, label, kind}; + miniobj_write(obj, (const char *)&s, sizeof(int32_t)); + obj->reloc_len += 1; +} + +const char *miniobj_finish(t_miniobj obj) +{ + char *res; + size_t i; + t_relocation reloc; + int32_t offset; + + defer(miniobj_drop, &obj); + res = execalloc(obj.byte_len); + cera_memcpy(res, obj.byte_buf, obj.byte_len); + i = 0; + while (i < obj.reloc_len) + { + reloc = obj.reloc_buf[i++]; + if (reloc.kind == REL_I32) + { + offset = obj.resolved_labels[reloc.label] - reloc.loc + - sizeof(int32_t); + cera_memcpy( + &res[reloc.loc], + (const char *) &offset, + sizeof(int32_t)); + } + } + return (res); +} diff --git a/src/miniobj.h b/src/miniobj.h new file mode 100644 index 0000000..235500c --- /dev/null +++ b/src/miniobj.h @@ -0,0 +1,55 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* miniobj.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/31 22:55:56 by agilliar #+# #+# */ +/* Updated: 2026/06/01 17:56:03 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef MINIOBJ_H +# define MINIOBJ_H + +# include + +typedef size_t t_objaddr; +typedef size_t t_label; + +typedef enum e_reloc_kind +{ + REL_I32, +} t_reloc_kind; + +typedef struct s_relocation +{ + t_objaddr loc; + t_label label; + t_reloc_kind kind; +} t_relocation; + +typedef struct s_miniobj +{ + char *byte_buf; + size_t byte_len; + size_t byte_capacity; + t_relocation *reloc_buf; + size_t reloc_len; + size_t reloc_capacity; + t_objaddr *resolved_labels; +} t_miniobj; + +t_miniobj miniobj_new(size_t label_count); +void miniobj_drop(t_miniobj *obj); + +void miniobj_write_s(t_miniobj *obj, const char *s); +void miniobj_write(t_miniobj *obj, const char *s, size_t n); +t_objaddr miniobj_label(t_miniobj *obj, t_label label); +void miniobj_write_reloc(t_miniobj *obj, t_label label, + t_reloc_kind kind); +// the returned buffer is addressable by the return values of defining labels +const char *miniobj_finish(t_miniobj obj); + +#endif diff --git a/src/miniobj_lifetime.c b/src/miniobj_lifetime.c new file mode 100644 index 0000000..4eac03d --- /dev/null +++ b/src/miniobj_lifetime.c @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* miniobj_lifetime.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/06/01 00:06:44 by agilliar #+# #+# */ +/* Updated: 2026/06/01 00:09:00 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "miniobj.h" +#include "memutils.h" + +t_miniobj miniobj_new(size_t label_count) +{ + t_miniobj res; + + cera_memset(&res, 0, sizeof(t_miniobj)); + res.resolved_labels = cera_malloc(label_count * sizeof(t_objaddr)); + return (res); +} + +void miniobj_drop(t_miniobj *obj) +{ + free(obj->byte_buf); + free(obj->reloc_buf); + free(obj->resolved_labels); +} diff --git a/src/vec.h b/src/vec.h new file mode 100644 index 0000000..bddae52 --- /dev/null +++ b/src/vec.h @@ -0,0 +1,34 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* vec.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/31 23:16:07 by agilliar #+# #+# */ +/* Updated: 2026/06/01 18:31:18 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef VEC_H +# define VEC_H + +# include +# include "memutils.h" + +static inline void vec_grow(void **p, size_t *cap, size_t to) +{ + void *nxt; + + if (to <= *cap) + return ; + if (to < *cap * 2) + to = *cap * 2; + nxt = cera_malloc(to); + cera_memcpy(nxt, *p, *cap); + free(*p); + *p = nxt; + *cap = to; +} + +#endif diff --git a/test.c b/test.c index 3a1217f..837e24b 100644 --- a/test.c +++ b/test.c @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/04/30 17:19:58 by agilliar #+# #+# */ -/* Updated: 2026/05/27 17:25:44 by agilliar ### ########.fr */ +/* Updated: 2026/06/01 18:55:35 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -210,12 +210,13 @@ void main2(void *_orig) defer(free, s2); strcpy(s2, orig); //t_value res = expr_eval(test_expr(), value_new_uint(0)); - t_value res = expr_eval(fact(), value_new_uint(1000000)); + t_value res = expr_eval(fact(), value_new_uint(5000000)); value_debug(0, &res); defer(value_drop, &res); printf("%s\n", s2); } +/* int main(void) { char *msg; @@ -233,3 +234,29 @@ int main(void) char *s2 = malloc(strlen(orig) + 1); defer(free, s2); } +*/ + +int main(void) +{ + t_miniobj obj; + t_objaddr func; + size_t (*fact)(size_t); + + obj = miniobj_new(2); + func = miniobj_label(&obj, 0); // func: + miniobj_write_s(&obj, "\x48\x85\xff"); // test rdi, rdi + miniobj_write_s(&obj, "\x0f\x84"); + miniobj_write_reloc(&obj, 1, REL_I32); // je rel32 end + miniobj_write_s(&obj, "\x57"); // push rdi + miniobj_write_s(&obj, "\x48\xff\xcf"); // dec rdi + miniobj_write_s(&obj, "\xe8"); + miniobj_write_reloc(&obj, 0, REL_I32); // call func + miniobj_write_s(&obj, "\x5f"); // pop rdi + miniobj_write_s(&obj, "\x48\x0f\xaf\xc7"); // imul rdi, rax + miniobj_write_s(&obj, "\xc3"); // ret + miniobj_label(&obj, 1); // end: + miniobj_write(&obj, "\xb8\x01\x00\x00\x00", 5); // mov 1, eax + miniobj_write_s(&obj, "\xc3"); // ret + fact = (void *) &miniobj_finish(obj)[func]; + printf("%lu\n", fact(10)); +} -- 2.53.0