summaryrefslogtreecommitdiff
path: root/asm/src
diff options
context:
space:
mode:
Diffstat (limited to 'asm/src')
-rw-r--r--asm/src/library.c302
-rw-r--r--asm/src/main.c24
2 files changed, 326 insertions, 0 deletions
diff --git a/asm/src/library.c b/asm/src/library.c
new file mode 100644
index 0000000..c1342f9
--- /dev/null
+++ b/asm/src/library.c
@@ -0,0 +1,302 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <lcq/pit.h>
+#include <lcq/elf.h>
+
+#include <lcq/asm/library.h>
+
+struct elf_builder {
+ i64 cap;
+ elf_ctx ctx;
+};
+
+static void builder_ensure_size(struct elf_builder *e, i64 sz) {
+ i64 cur = e->ctx.len;
+ i64 cap = e->cap;
+ if (sz <= cur) return;
+ while (cap < sz) cap <<= 1;
+ e->ctx.buf = realloc(e->ctx.buf, (size_t) cap);
+ memset(e->ctx.buf + e->cap, 0, (size_t) (cap - e->cap));
+ e->ctx.len = sz;
+ e->cap = cap;
+}
+
+static i64 get_kwargs_i64(pit_runtime *rt, i64 def, pit_value kwargs, char *kw) {
+ pit_value v = pit_value_list_plist_get(rt, pit_symtab_intern_cstr(rt, kw), kwargs);
+ if (v != PIT_NIL && pit_value_is_integer(rt, v)) {
+ return pit_value_as_integer(rt, v);
+ } else {
+ return def;
+ }
+}
+static pit_value impl_elf_new(pit_runtime *rt, pit_value kwargs, void *data) {
+ (void) data;
+ i64 vclass = get_kwargs_i64(rt, ELF_CLASS_64, kwargs, ":class");
+ i64 vendianness = get_kwargs_i64(rt, ELF_ENDIANNESS_LITTLE, kwargs, ":endianness");
+ struct elf_builder *ret = malloc(sizeof(struct elf_builder));
+ i64 len = 256;
+ u8 *buf = calloc((size_t) len, 1);
+ ret->cap = len;
+ ret->ctx = elf_ctx_new(buf, len, vclass, vendianness);
+ return pit_value_nativedata_new(rt, pit_symtab_intern_cstr(rt, "elf"), (void *) ret);
+}
+static pit_value impl_elf_write_header(pit_runtime *rt, pit_value args, void *data) {
+ (void) data;
+ pit_value velf = pit_value_cons_car(rt, args);
+ pit_value kwargs = pit_value_cons_cdr(rt, args);
+ struct elf_builder *e = pit_value_nativedata_get(rt, pit_symtab_intern_cstr(rt, "elf"), velf);
+ elf_header h = {0};
+ if (!e) return PIT_NIL;
+ builder_ensure_size(e, elf_header_size(&e->ctx));
+ h.type = get_kwargs_i64(rt, ELF_TYPE_EXEC, kwargs, ":type");
+ h.machine = get_kwargs_i64(rt, ELF_MACHINE_AMD64, kwargs, ":machine");
+ h.version = (u32) get_kwargs_i64(rt, 1, kwargs, ":version");
+ h.entry = (u64) get_kwargs_i64(rt, 0x401000, kwargs, ":entry");
+ h.program_header_offset = (u64) get_kwargs_i64(rt, 0, kwargs, ":program-header-offset");
+ h.program_header_entry_size = (u16) get_kwargs_i64(rt, elf_program_header_size(&e->ctx), kwargs, ":program-header-entry-size");
+ h.program_header_entries = (u16) get_kwargs_i64(rt, 1, kwargs, ":program-header-entries");
+ h.section_header_offset = (u64) get_kwargs_i64(rt, 0, kwargs, ":section-header-offset");
+ h.section_header_entry_size = (u16) get_kwargs_i64(rt, elf_section_header_size(&e->ctx), kwargs, ":section-header-entry-size");
+ h.section_header_entries = (u16) get_kwargs_i64(rt, 0, kwargs, ":section-header-entries");
+ h.section_name_table_index = (u16) get_kwargs_i64(rt, 1, kwargs, ":section-name-table-index");
+ elf_write_header(&h, &e->ctx);
+ return PIT_NIL;
+}
+static pit_value impl_elf_write_section_header(pit_runtime *rt, pit_value args, void *data) {
+ (void) data;
+ pit_value velf = pit_value_cons_car(rt, args);
+ pit_value voff = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ i64 off = pit_value_as_integer(rt, voff);
+ pit_value kwargs = pit_value_cons_cdr(rt, pit_value_cons_cdr(rt, args));
+ struct elf_builder *e = pit_value_nativedata_get(rt, pit_symtab_intern_cstr(rt, "elf"), velf);
+ elf_section_header h = {0};
+ if (!e) return PIT_NIL;
+ if (off < 0) { pit_error(rt, "negative offset: %d", off); return PIT_NIL; }
+ builder_ensure_size(e, off + elf_header_size(&e->ctx));
+ h.name_index = (u32) get_kwargs_i64(rt, 0, kwargs, ":name-index");
+ h.type = (u32) get_kwargs_i64(rt, ELF_SECTION_TYPE_NULL, kwargs, ":type");
+ h.flags = (u64) get_kwargs_i64(rt, 0, kwargs, ":flags");
+ h.addr = (u64) get_kwargs_i64(rt, 0, kwargs, ":addr");
+ h.offset = (u64) get_kwargs_i64(rt, 0, kwargs, ":offset");
+ h.size = (u64) get_kwargs_i64(rt, 0, kwargs, ":size");
+ h.link = (u32) get_kwargs_i64(rt, 0, kwargs, ":link");
+ h.info = (u32) get_kwargs_i64(rt, 0, kwargs, ":info");
+ h.addr_alignment = (u64) get_kwargs_i64(rt, 0, kwargs, ":addr-alignment");
+ h.entry_size = (u64) get_kwargs_i64(rt, 0, kwargs, ":entry-size");
+ elf_write_section_header(&h, &e->ctx, (u64) off);
+ return PIT_NIL;
+}
+static pit_value impl_elf_write_symbol(pit_runtime *rt, pit_value args, void *data) {
+ (void) data;
+ pit_value velf = pit_value_cons_car(rt, args);
+ pit_value voff = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ i64 off = pit_value_as_integer(rt, voff);
+ pit_value kwargs = pit_value_cons_cdr(rt, pit_value_cons_cdr(rt, args));
+ elf_symbol h = {0};
+ struct elf_builder *e = pit_value_nativedata_get(rt, pit_symtab_intern_cstr(rt, "elf"), velf);
+ if (!e) return PIT_NIL;
+ if (off < 0) { pit_error(rt, "negative offset: %d", off); return PIT_NIL; }
+ builder_ensure_size(e, off + elf_symbol_size(&e->ctx));
+ h.size = (u64) get_kwargs_i64(rt, 0, kwargs, ":size");
+ h.value = (u64) get_kwargs_i64(rt, 0, kwargs, ":value");
+ h.name_index = (u32) get_kwargs_i64(rt, 0, kwargs, ":name_index");
+ h.bind = get_kwargs_i64(rt, ELF_SYMBOL_BINDING_LOCAL, kwargs, ":bind");
+ h.type = get_kwargs_i64(rt, ELF_SYMBOL_TYPE_NOTYPE, kwargs, ":type");
+ h.visibility = get_kwargs_i64(rt, ELF_SYMBOL_VISIBILITY_DEFAULT, kwargs, ":visibility");
+ h.section_header_index = (u16) get_kwargs_i64(rt, 0, kwargs, ":section-header-index");
+ elf_write_symbol(&h, &e->ctx, (u64) off);
+ return PIT_NIL;
+}
+static pit_value impl_elf_write_program_header(pit_runtime *rt, pit_value args, void *data) {
+ (void) data;
+ pit_value velf = pit_value_cons_car(rt, args);
+ pit_value voff = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ i64 off = pit_value_as_integer(rt, voff);
+ pit_value kwargs = pit_value_cons_cdr(rt, pit_value_cons_cdr(rt, args));
+ elf_program_header h = {0};
+ struct elf_builder *e = pit_value_nativedata_get(rt, pit_symtab_intern_cstr(rt, "elf"), velf);
+ if (!e) return PIT_NIL;
+ if (off < 0) { pit_error(rt, "negative offset: %d", off); return PIT_NIL; }
+ builder_ensure_size(e, off + elf_program_header_size(&e->ctx));
+ h.type = (u32) get_kwargs_i64(rt, ELF_PROGRAM_HEADER_TYPE_NULL, kwargs, ":type");
+ h.offset = (u64) get_kwargs_i64(rt, 0, kwargs, ":offset");
+ h.virtual_addr = (u64) get_kwargs_i64(rt, 0, kwargs, ":virtual-addr");
+ h.physical_addr = (u64) get_kwargs_i64(rt, 0, kwargs, ":physical-addr");
+ h.file_size = (u64) get_kwargs_i64(rt, 0, kwargs, ":file-size");
+ h.mem_size = (u64) get_kwargs_i64(rt, 0, kwargs, ":mem-size");
+ h.flags = (u32) get_kwargs_i64(rt, 0, kwargs, ":flags");
+ h.align = (u64) get_kwargs_i64(rt, 0, kwargs, ":align");
+ elf_write_program_header(&h, &e->ctx, (u64) off);
+ return PIT_NIL;
+}
+static pit_value impl_elf_write_bytes(pit_runtime *rt, pit_value args, void *data) {
+ (void) data;
+ pit_value velf = pit_value_cons_car(rt, args);
+ pit_value voff = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ pit_value vbytes = pit_value_cons_car(rt, pit_value_cons_cdr(rt, pit_value_cons_cdr(rt, args)));
+ pit_value_heavy *hbytes = NULL;
+ i64 off = 0;
+ struct elf_builder *e = pit_value_nativedata_get(rt, pit_symtab_intern_cstr(rt, "elf"), velf);
+ if (!e) return PIT_NIL;
+ if (!pit_value_is_integer(rt, voff)) {
+ pit_error(rt, "offset is not integer");
+ return PIT_NIL;
+ }
+ off = pit_value_as_integer(rt, voff);
+ if (off < 0) {
+ pit_error(rt, "negative offset");
+ return PIT_NIL;
+ }
+ if (pit_value_is_bytes(rt, vbytes)) {
+ if (pit_value_sort(vbytes) != PIT_VALUE_SORT_REF) {
+ pit_error(rt, "bytes are not a reference");
+ return PIT_NIL;
+ }
+ hbytes = pit_value_ref_deref(rt, pit_value_as_ref(rt, vbytes));
+ if (!hbytes) { pit_error(rt, "bad ref"); return PIT_NIL; }
+ if (hbytes->hsort != PIT_VALUE_HEAVY_SORT_BYTES) {
+ pit_error(rt, "invalid use of value as bytes");
+ return PIT_NIL;
+ }
+ builder_ensure_size(e, off + hbytes->in.bytes.len);
+ elf_write_bytes(&e->ctx, (u64 *) &off, hbytes->in.bytes.data, hbytes->in.bytes.len);
+ } else if (pit_value_is_cons(rt, vbytes)) {
+ while (vbytes != PIT_NIL) {
+ pit_value x = pit_value_cons_car(rt, vbytes);
+ i64 v = 0;
+ u8 byte = 0;
+ if (!pit_value_is_integer(rt, x)) {
+ pit_error(rt, "byte is not integer");
+ return PIT_NIL;
+ }
+ v = pit_value_as_integer(rt, x);
+ if (v < 0 || v > 255) {
+ pit_error(rt, "byte out of range");
+ return PIT_NIL;
+ }
+ byte = (u8) v;
+ builder_ensure_size(e, off + 1);
+ if (elf_write_bytes(&e->ctx, (u64 *) &off, (u8 *) &byte, 1) < 0) {
+ pit_error(rt, "failed to write byte at offset: %ld\n", off);
+ return PIT_NIL;
+ }
+ vbytes = pit_value_cons_cdr(rt, vbytes);
+ }
+ }
+ return PIT_T;
+}
+static pit_value impl_elf_spit(pit_runtime *rt, pit_value args, void *data) {
+ (void) data;
+ char pathbuf[1024] = {0};
+ i64 len = 0, actual = 0;
+ FILE *f = NULL;
+ struct elf_builder *e = NULL;
+ pit_value path = pit_value_cons_car(rt, args);
+ pit_value velf = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ len = pit_value_bytes_copy(rt, path, (u8 *) pathbuf, sizeof(pathbuf) - 1);
+ if (len < 0) { pit_error(rt, "path was not a string"); return PIT_NIL; }
+ pathbuf[len] = 0;
+ e = pit_value_nativedata_get(rt, pit_symtab_intern_cstr(rt, "elf"), velf);
+ if (!e) return PIT_NIL;
+ f = fopen(pathbuf, "w+");
+ if (!f) {
+ pit_error(rt, "failed to open file: %s", pathbuf);
+ return PIT_NIL;
+ }
+ actual = (i64) fwrite(e->ctx.buf, 1, (size_t) e->ctx.len, f);
+ fclose(f);
+ if (e->ctx.len != actual) {
+ pit_error(rt, "failed to write ELF file");
+ return PIT_NIL;
+ }
+ return velf;
+}
+
+void asm_install_library_elf(pit_runtime *rt) {
+ /* sizes */
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/HEADER_IDENT_SIZE"), pit_value_integer_new(rt, ELF_HEADER_IDENT_SIZE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/32_HEADER_SIZE"), pit_value_integer_new(rt, ELF32_HEADER_SIZE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/64_HEADER_SIZE"), pit_value_integer_new(rt, ELF64_HEADER_SIZE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/32_SECTION_HEADER_SIZE"), pit_value_integer_new(rt, ELF32_SECTION_HEADER_SIZE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/64_SECTION_HEADER_SIZE"), pit_value_integer_new(rt, ELF64_SECTION_HEADER_SIZE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/32_PROGRAM_HEADER_SIZE"), pit_value_integer_new(rt, ELF32_PROGRAM_HEADER_SIZE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/64_PROGRAM_HEADER_SIZE"), pit_value_integer_new(rt, ELF64_PROGRAM_HEADER_SIZE));
+ /* enums */
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/CLASS_INVALID"), pit_value_integer_new(rt, ELF_CLASS_INVALID));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/CLASS_32"), pit_value_integer_new(rt, ELF_CLASS_32));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/CLASS_64"), pit_value_integer_new(rt, ELF_CLASS_64));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/ENDIANNESS_INVALID"), pit_value_integer_new(rt, ELF_ENDIANNESS_INVALID));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/ENDIANNESS_LITTLE"), pit_value_integer_new(rt, ELF_ENDIANNESS_LITTLE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/ENDIANNESS_BIG"), pit_value_integer_new(rt, ELF_ENDIANNESS_BIG));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/TYPE_NONE"), pit_value_integer_new(rt, ELF_TYPE_NONE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/TYPE_REL"), pit_value_integer_new(rt, ELF_TYPE_REL));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/TYPE_EXEC"), pit_value_integer_new(rt, ELF_TYPE_EXEC));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/TYPE_DYN"), pit_value_integer_new(rt, ELF_TYPE_DYN));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/TYPE_CORE"), pit_value_integer_new(rt, ELF_TYPE_CORE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/MACHINE_NONE"), pit_value_integer_new(rt, ELF_MACHINE_NONE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/MACHINE_X86"), pit_value_integer_new(rt, ELF_MACHINE_X86));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/MACHINE_AMD64"), pit_value_integer_new(rt, ELF_MACHINE_AMD64));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_NULL"), pit_value_integer_new(rt, ELF_SECTION_TYPE_NULL));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_PROGBITS"), pit_value_integer_new(rt, ELF_SECTION_TYPE_PROGBITS));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_SYMTAB"), pit_value_integer_new(rt, ELF_SECTION_TYPE_SYMTAB));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_STRTAB"), pit_value_integer_new(rt, ELF_SECTION_TYPE_STRTAB));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_RELA"), pit_value_integer_new(rt, ELF_SECTION_TYPE_RELA));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_HASH"), pit_value_integer_new(rt, ELF_SECTION_TYPE_HASH));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_DYNAMIC"), pit_value_integer_new(rt, ELF_SECTION_TYPE_DYNAMIC));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_NOTE"), pit_value_integer_new(rt, ELF_SECTION_TYPE_NOTE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_NOBITS"), pit_value_integer_new(rt, ELF_SECTION_TYPE_NOBITS));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_REL"), pit_value_integer_new(rt, ELF_SECTION_TYPE_REL));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_SHLIB"), pit_value_integer_new(rt, ELF_SECTION_TYPE_SHLIB));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_DYNSYM"), pit_value_integer_new(rt, ELF_SECTION_TYPE_DYNSYM));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_INIT_ARRAY"), pit_value_integer_new(rt, ELF_SECTION_TYPE_INIT_ARRAY));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_FINI_ARRAY"), pit_value_integer_new(rt, ELF_SECTION_TYPE_FINI_ARRAY));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_PREINIT_ARRAY"), pit_value_integer_new(rt, ELF_SECTION_TYPE_PREINIT_ARRAY));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_GROUP"), pit_value_integer_new(rt, ELF_SECTION_TYPE_GROUP));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_TYPE_SYMTAB_SHNDX"), pit_value_integer_new(rt, ELF_SECTION_TYPE_SYMTAB_SHNDX));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_FLAG_WRITE"), pit_value_integer_new(rt, ELF_SECTION_FLAG_WRITE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_FLAG_ALLOC"), pit_value_integer_new(rt, ELF_SECTION_FLAG_ALLOC));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_FLAG_EXECINSTR"), pit_value_integer_new(rt, ELF_SECTION_FLAG_EXECINSTR));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_FLAG_MERGE"), pit_value_integer_new(rt, ELF_SECTION_FLAG_MERGE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_FLAG_STRINGS"), pit_value_integer_new(rt, ELF_SECTION_FLAG_STRINGS));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_FLAG_INFO_LINK"), pit_value_integer_new(rt, ELF_SECTION_FLAG_INFO_LINK));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_FLAG_LINK_ORDER"), pit_value_integer_new(rt, ELF_SECTION_FLAG_LINK_ORDER));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_FLAG_OS_NONCOMFORMING"), pit_value_integer_new(rt, ELF_SECTION_FLAG_OS_NONCOMFORMING));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_FLAG_GROUP"), pit_value_integer_new(rt, ELF_SECTION_FLAG_GROUP));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_FLAG_TLS"), pit_value_integer_new(rt, ELF_SECTION_FLAG_TLS));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SECTION_FLAG_COMPRESSED"), pit_value_integer_new(rt, ELF_SECTION_FLAG_COMPRESSED));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_BINDING_LOCAL"), pit_value_integer_new(rt, ELF_SYMBOL_BINDING_LOCAL));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_BINDING_GLOBAL"), pit_value_integer_new(rt, ELF_SYMBOL_BINDING_GLOBAL));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_BINDING_WEAK"), pit_value_integer_new(rt, ELF_SYMBOL_BINDING_WEAK));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_TYPE_NOTYPE"), pit_value_integer_new(rt, ELF_SYMBOL_TYPE_NOTYPE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_TYPE_OBJECT"), pit_value_integer_new(rt, ELF_SYMBOL_TYPE_OBJECT));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_TYPE_FUNC"), pit_value_integer_new(rt, ELF_SYMBOL_TYPE_FUNC));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_TYPE_SECTION"), pit_value_integer_new(rt, ELF_SYMBOL_TYPE_SECTION));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_TYPE_FILE"), pit_value_integer_new(rt, ELF_SYMBOL_TYPE_FILE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_TYPE_COMMON"), pit_value_integer_new(rt, ELF_SYMBOL_TYPE_COMMON));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_TYPE_TLS"), pit_value_integer_new(rt, ELF_SYMBOL_TYPE_TLS));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_VISIBILITY_DEFAULT"), pit_value_integer_new(rt, ELF_SYMBOL_VISIBILITY_DEFAULT));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_VISIBILITY_INTERNAL"), pit_value_integer_new(rt, ELF_SYMBOL_VISIBILITY_INTERNAL));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_VISIBILITY_HIDDEN"), pit_value_integer_new(rt, ELF_SYMBOL_VISIBILITY_HIDDEN));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/SYMBOL_VISIBILITY_PROTECTED"), pit_value_integer_new(rt, ELF_SYMBOL_VISIBILITY_PROTECTED));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_NULL"), pit_value_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_NULL));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_LOAD"), pit_value_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_LOAD));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_DYNAMIC"), pit_value_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_DYNAMIC));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_INTERP"), pit_value_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_INTERP));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_NOTE"), pit_value_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_NOTE));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_SHLIB"), pit_value_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_SHLIB));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_PHDR"), pit_value_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_PHDR));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_TLS"), pit_value_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_TLS));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/PROGRAM_HEADER_FLAG_X"), pit_value_integer_new(rt, ELF_PROGRAM_HEADER_FLAG_X));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/PROGRAM_HEADER_FLAG_W"), pit_value_integer_new(rt, ELF_PROGRAM_HEADER_FLAG_W));
+ pit_symtab_set(rt, pit_symtab_intern_cstr(rt, "elf/PROGRAM_HEADER_FLAG_R"), pit_value_integer_new(rt, ELF_PROGRAM_HEADER_FLAG_R));
+
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "elf/new!"), pit_value_nativefunc_new(rt, impl_elf_new));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "elf/write-header!"), pit_value_nativefunc_new(rt, impl_elf_write_header));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "elf/write-section-header!"), pit_value_nativefunc_new(rt, impl_elf_write_section_header));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "elf/write-symbol!"), pit_value_nativefunc_new(rt, impl_elf_write_symbol));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "elf/write-program-header!"), pit_value_nativefunc_new(rt, impl_elf_write_program_header));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "elf/write-bytes!"), pit_value_nativefunc_new(rt, impl_elf_write_bytes));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "elf/spit!"), pit_value_nativefunc_new(rt, impl_elf_spit));
+}
diff --git a/asm/src/main.c b/asm/src/main.c
new file mode 100644
index 0000000..2d25274
--- /dev/null
+++ b/asm/src/main.c
@@ -0,0 +1,24 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <lcq/pit.h>
+
+#include <lcq/asm/library.h>
+
+int main(int argc, char **argv) {
+ i64 sz = 256 * 1024 * 1024;
+ u8 *buf = malloc((size_t) sz);
+ pit_runtime *rt = pit_runtime_new(buf, sz);
+ rt->fuel = 10000000;
+ pit_install_library_essential(rt);
+ pit_install_library_io(rt);
+ pit_install_library_plist(rt);
+ pit_install_library_alist(rt);
+ pit_install_library_bytestring(rt);
+ asm_install_library_elf(rt);
+ if (argc < 2) {
+ pit_repl(rt);
+ } else {
+ pit_load_file(rt, argv[1]);
+ }
+}