#include #include #include #include #include #include #include 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_plist_get(rt, pit_intern_cstr(rt, kw), kwargs); if (v != PIT_NIL && pit_is_integer(rt, v)) { return pit_as_integer(rt, v); } else { return def; } } static pit_value impl_elf_new(pit_runtime *rt, pit_value kwargs) { 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_nativedata_new(rt, pit_intern_cstr(rt, "elf"), (void *) ret); } static pit_value impl_elf_write_header(pit_runtime *rt, pit_value args) { pit_value velf = pit_car(rt, args); pit_value kwargs = pit_cdr(rt, args); struct elf_builder *e = pit_nativedata_get(rt, pit_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) { pit_value velf = pit_car(rt, args); pit_value voff = pit_car(rt, pit_cdr(rt, args)); i64 off = pit_as_integer(rt, voff); pit_value kwargs = pit_cdr(rt, pit_cdr(rt, args)); struct elf_builder *e = pit_nativedata_get(rt, pit_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) { pit_value velf = pit_car(rt, args); pit_value voff = pit_car(rt, pit_cdr(rt, args)); i64 off = pit_as_integer(rt, voff); pit_value kwargs = pit_cdr(rt, pit_cdr(rt, args)); elf_symbol h = {0}; struct elf_builder *e = pit_nativedata_get(rt, pit_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) { pit_value velf = pit_car(rt, args); pit_value voff = pit_car(rt, pit_cdr(rt, args)); i64 off = pit_as_integer(rt, voff); pit_value kwargs = pit_cdr(rt, pit_cdr(rt, args)); elf_program_header h = {0}; struct elf_builder *e = pit_nativedata_get(rt, pit_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) { pit_value velf = pit_car(rt, args); pit_value voff = pit_car(rt, pit_cdr(rt, args)); pit_value vbytes = pit_car(rt, pit_cdr(rt, pit_cdr(rt, args))); pit_value_heavy *hbytes = NULL; i64 off = 0; struct elf_builder *e = pit_nativedata_get(rt, pit_intern_cstr(rt, "elf"), velf); if (!e) return PIT_NIL; if (!pit_is_integer(rt, voff)) { pit_error(rt, "offset is not integer"); return PIT_NIL; } off = pit_as_integer(rt, voff); if (off < 0) { pit_error(rt, "negative offset"); return PIT_NIL; } if (pit_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_deref(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_is_cons(rt, vbytes)) { while (vbytes != PIT_NIL) { pit_value x = pit_car(rt, vbytes); i64 v = 0; u8 byte = 0; if (!pit_is_integer(rt, x)) { pit_error(rt, "byte is not integer"); return PIT_NIL; } v = pit_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_cdr(rt, vbytes); } } return PIT_T; } static pit_value impl_elf_spit(pit_runtime *rt, pit_value args) { char pathbuf[1024] = {0}; i64 len = 0, actual = 0; FILE *f = NULL; struct elf_builder *e = NULL; pit_value path = pit_car(rt, args); pit_value velf = pit_car(rt, pit_cdr(rt, args)); len = pit_as_bytes(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_nativedata_get(rt, pit_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 rj_install_library(pit_runtime *rt) { /* sizes */ pit_set(rt, pit_intern_cstr(rt, "elf/HEADER_IDENT_SIZE"), pit_integer_new(rt, ELF_HEADER_IDENT_SIZE)); pit_set(rt, pit_intern_cstr(rt, "elf/32_HEADER_SIZE"), pit_integer_new(rt, ELF32_HEADER_SIZE)); pit_set(rt, pit_intern_cstr(rt, "elf/64_HEADER_SIZE"), pit_integer_new(rt, ELF64_HEADER_SIZE)); pit_set(rt, pit_intern_cstr(rt, "elf/32_SECTION_HEADER_SIZE"), pit_integer_new(rt, ELF32_SECTION_HEADER_SIZE)); pit_set(rt, pit_intern_cstr(rt, "elf/64_SECTION_HEADER_SIZE"), pit_integer_new(rt, ELF64_SECTION_HEADER_SIZE)); pit_set(rt, pit_intern_cstr(rt, "elf/32_PROGRAM_HEADER_SIZE"), pit_integer_new(rt, ELF32_PROGRAM_HEADER_SIZE)); pit_set(rt, pit_intern_cstr(rt, "elf/64_PROGRAM_HEADER_SIZE"), pit_integer_new(rt, ELF64_PROGRAM_HEADER_SIZE)); /* enums */ pit_set(rt, pit_intern_cstr(rt, "elf/CLASS_INVALID"), pit_integer_new(rt, ELF_CLASS_INVALID)); pit_set(rt, pit_intern_cstr(rt, "elf/CLASS_32"), pit_integer_new(rt, ELF_CLASS_32)); pit_set(rt, pit_intern_cstr(rt, "elf/CLASS_64"), pit_integer_new(rt, ELF_CLASS_64)); pit_set(rt, pit_intern_cstr(rt, "elf/ENDIANNESS_INVALID"), pit_integer_new(rt, ELF_ENDIANNESS_INVALID)); pit_set(rt, pit_intern_cstr(rt, "elf/ENDIANNESS_LITTLE"), pit_integer_new(rt, ELF_ENDIANNESS_LITTLE)); pit_set(rt, pit_intern_cstr(rt, "elf/ENDIANNESS_BIG"), pit_integer_new(rt, ELF_ENDIANNESS_BIG)); pit_set(rt, pit_intern_cstr(rt, "elf/TYPE_NONE"), pit_integer_new(rt, ELF_TYPE_NONE)); pit_set(rt, pit_intern_cstr(rt, "elf/TYPE_REL"), pit_integer_new(rt, ELF_TYPE_REL)); pit_set(rt, pit_intern_cstr(rt, "elf/TYPE_EXEC"), pit_integer_new(rt, ELF_TYPE_EXEC)); pit_set(rt, pit_intern_cstr(rt, "elf/TYPE_DYN"), pit_integer_new(rt, ELF_TYPE_DYN)); pit_set(rt, pit_intern_cstr(rt, "elf/TYPE_CORE"), pit_integer_new(rt, ELF_TYPE_CORE)); pit_set(rt, pit_intern_cstr(rt, "elf/MACHINE_NONE"), pit_integer_new(rt, ELF_MACHINE_NONE)); pit_set(rt, pit_intern_cstr(rt, "elf/MACHINE_X86"), pit_integer_new(rt, ELF_MACHINE_X86)); pit_set(rt, pit_intern_cstr(rt, "elf/MACHINE_AMD64"), pit_integer_new(rt, ELF_MACHINE_AMD64)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_NULL"), pit_integer_new(rt, ELF_SECTION_TYPE_NULL)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_PROGBITS"), pit_integer_new(rt, ELF_SECTION_TYPE_PROGBITS)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_SYMTAB"), pit_integer_new(rt, ELF_SECTION_TYPE_SYMTAB)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_STRTAB"), pit_integer_new(rt, ELF_SECTION_TYPE_STRTAB)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_RELA"), pit_integer_new(rt, ELF_SECTION_TYPE_RELA)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_HASH"), pit_integer_new(rt, ELF_SECTION_TYPE_HASH)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_DYNAMIC"), pit_integer_new(rt, ELF_SECTION_TYPE_DYNAMIC)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_NOTE"), pit_integer_new(rt, ELF_SECTION_TYPE_NOTE)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_NOBITS"), pit_integer_new(rt, ELF_SECTION_TYPE_NOBITS)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_REL"), pit_integer_new(rt, ELF_SECTION_TYPE_REL)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_SHLIB"), pit_integer_new(rt, ELF_SECTION_TYPE_SHLIB)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_DYNSYM"), pit_integer_new(rt, ELF_SECTION_TYPE_DYNSYM)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_INIT_ARRAY"), pit_integer_new(rt, ELF_SECTION_TYPE_INIT_ARRAY)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_FINI_ARRAY"), pit_integer_new(rt, ELF_SECTION_TYPE_FINI_ARRAY)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_PREINIT_ARRAY"), pit_integer_new(rt, ELF_SECTION_TYPE_PREINIT_ARRAY)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_GROUP"), pit_integer_new(rt, ELF_SECTION_TYPE_GROUP)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_TYPE_SYMTAB_SHNDX"), pit_integer_new(rt, ELF_SECTION_TYPE_SYMTAB_SHNDX)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_FLAG_WRITE"), pit_integer_new(rt, ELF_SECTION_FLAG_WRITE)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_FLAG_ALLOC"), pit_integer_new(rt, ELF_SECTION_FLAG_ALLOC)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_FLAG_EXECINSTR"), pit_integer_new(rt, ELF_SECTION_FLAG_EXECINSTR)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_FLAG_MERGE"), pit_integer_new(rt, ELF_SECTION_FLAG_MERGE)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_FLAG_STRINGS"), pit_integer_new(rt, ELF_SECTION_FLAG_STRINGS)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_FLAG_INFO_LINK"), pit_integer_new(rt, ELF_SECTION_FLAG_INFO_LINK)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_FLAG_LINK_ORDER"), pit_integer_new(rt, ELF_SECTION_FLAG_LINK_ORDER)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_FLAG_OS_NONCOMFORMING"), pit_integer_new(rt, ELF_SECTION_FLAG_OS_NONCOMFORMING)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_FLAG_GROUP"), pit_integer_new(rt, ELF_SECTION_FLAG_GROUP)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_FLAG_TLS"), pit_integer_new(rt, ELF_SECTION_FLAG_TLS)); pit_set(rt, pit_intern_cstr(rt, "elf/SECTION_FLAG_COMPRESSED"), pit_integer_new(rt, ELF_SECTION_FLAG_COMPRESSED)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_BINDING_LOCAL"), pit_integer_new(rt, ELF_SYMBOL_BINDING_LOCAL)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_BINDING_GLOBAL"), pit_integer_new(rt, ELF_SYMBOL_BINDING_GLOBAL)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_BINDING_WEAK"), pit_integer_new(rt, ELF_SYMBOL_BINDING_WEAK)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_TYPE_NOTYPE"), pit_integer_new(rt, ELF_SYMBOL_TYPE_NOTYPE)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_TYPE_OBJECT"), pit_integer_new(rt, ELF_SYMBOL_TYPE_OBJECT)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_TYPE_FUNC"), pit_integer_new(rt, ELF_SYMBOL_TYPE_FUNC)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_TYPE_SECTION"), pit_integer_new(rt, ELF_SYMBOL_TYPE_SECTION)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_TYPE_FILE"), pit_integer_new(rt, ELF_SYMBOL_TYPE_FILE)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_TYPE_COMMON"), pit_integer_new(rt, ELF_SYMBOL_TYPE_COMMON)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_TYPE_TLS"), pit_integer_new(rt, ELF_SYMBOL_TYPE_TLS)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_VISIBILITY_DEFAULT"), pit_integer_new(rt, ELF_SYMBOL_VISIBILITY_DEFAULT)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_VISIBILITY_INTERNAL"), pit_integer_new(rt, ELF_SYMBOL_VISIBILITY_INTERNAL)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_VISIBILITY_HIDDEN"), pit_integer_new(rt, ELF_SYMBOL_VISIBILITY_HIDDEN)); pit_set(rt, pit_intern_cstr(rt, "elf/SYMBOL_VISIBILITY_PROTECTED"), pit_integer_new(rt, ELF_SYMBOL_VISIBILITY_PROTECTED)); pit_set(rt, pit_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_NULL"), pit_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_NULL)); pit_set(rt, pit_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_LOAD"), pit_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_LOAD)); pit_set(rt, pit_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_DYNAMIC"), pit_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_DYNAMIC)); pit_set(rt, pit_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_INTERP"), pit_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_INTERP)); pit_set(rt, pit_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_NOTE"), pit_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_NOTE)); pit_set(rt, pit_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_SHLIB"), pit_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_SHLIB)); pit_set(rt, pit_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_PHDR"), pit_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_PHDR)); pit_set(rt, pit_intern_cstr(rt, "elf/PROGRAM_HEADER_TYPE_TLS"), pit_integer_new(rt, ELF_PROGRAM_HEADER_TYPE_TLS)); pit_set(rt, pit_intern_cstr(rt, "elf/PROGRAM_HEADER_FLAG_X"), pit_integer_new(rt, ELF_PROGRAM_HEADER_FLAG_X)); pit_set(rt, pit_intern_cstr(rt, "elf/PROGRAM_HEADER_FLAG_W"), pit_integer_new(rt, ELF_PROGRAM_HEADER_FLAG_W)); pit_set(rt, pit_intern_cstr(rt, "elf/PROGRAM_HEADER_FLAG_R"), pit_integer_new(rt, ELF_PROGRAM_HEADER_FLAG_R)); pit_fset(rt, pit_intern_cstr(rt, "elf/new!"), pit_nativefunc_new(rt, impl_elf_new)); pit_fset(rt, pit_intern_cstr(rt, "elf/write-header!"), pit_nativefunc_new(rt, impl_elf_write_header)); pit_fset(rt, pit_intern_cstr(rt, "elf/write-section-header!"), pit_nativefunc_new(rt, impl_elf_write_section_header)); pit_fset(rt, pit_intern_cstr(rt, "elf/write-symbol!"), pit_nativefunc_new(rt, impl_elf_write_symbol)); pit_fset(rt, pit_intern_cstr(rt, "elf/write-program-header!"), pit_nativefunc_new(rt, impl_elf_write_program_header)); pit_fset(rt, pit_intern_cstr(rt, "elf/write-bytes!"), pit_nativefunc_new(rt, impl_elf_write_bytes)); pit_fset(rt, pit_intern_cstr(rt, "elf/spit!"), pit_nativefunc_new(rt, impl_elf_spit)); }