diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2024-07-25 22:43:44 +0200 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2024-07-25 22:43:44 +0200 |
commit | 941491cf484bd6f11dd743aae76e8dea8057cc60 (patch) | |
tree | ae35c6a202c3c786306eaff045fd47221c6ecd76 | |
parent | 7a0155cab821a6bc2102123c02f72e705df1f4cd (diff) | |
download | bxgen-941491cf484bd6f11dd743aae76e8dea8057cc60.zip |
Codegen: call (incomplete)
-rwxr-xr-x | bxgen.c | 280 |
1 files changed, 165 insertions, 115 deletions
@@ -31,6 +31,7 @@ #/ - Linking libraries #/ - GNU ld script #/ - Unused dependencies elimination +#/ - Use 0 for UNDEFINED #/ - String table for names and arrays #/ - Proper prefixes for identifiers #/ - Effective entity allocation @@ -164,6 +165,7 @@ enum { MAX_NUM_OBJECT_FILES = 10 * 1024, MAX_NUM_SECTIONS = 2 * 1024 * 1024, MAX_NUM_SYMBOLS = 2 * 1024 * 1024, + MAX_NUM_RELS = 100 * 1024, MAX_OBJECT_FILE_SIZE = 10 * 1024 * 1024, // 10 MB MAX_DEPENDENCIES_SIZE = 50 * 1024 * 1024, // 50 MB MAX_NOT_FOUND_SIZE = 10 * 1024, // 10 KB @@ -257,6 +259,11 @@ enum { ARCH_X86_64, ARCH_ARM32, ARCH_ARM64, + + // Relocations + // + + REL_CALL = 0, }; // TODO @@ -275,7 +282,7 @@ typedef struct { typedef struct { i16 num; - i16 type; + u16 type; i64 node; } Var; @@ -289,7 +296,7 @@ typedef struct { // We may call a local procedure by it's id, // or a global procedure by name. - i16 convention; // can be implicitly retrieved from the procedure + u16 convention; // can be implicitly retrieved from the procedure i64 target_proc; i64 target_name_size; c8 target_name[MAX_NAME_SIZE]; // TODO use string table @@ -301,7 +308,7 @@ typedef struct { // and possible references to other nodes. typedef struct { - i16 op; + u16 op; i64 index_in_proc; union { u8 lit_bytes[MAX_LITERAL_SIZE]; // byte array literal @@ -325,7 +332,7 @@ typedef struct { // and has a string name. typedef struct { - i16 convention; + u16 convention; i64 name_size; c8 name[MAX_NAME_SIZE]; // TODO use string table i64 num_nodes; @@ -339,7 +346,7 @@ typedef struct { // typedef struct { - i16 type; + u16 type; i64 entry_point_index; i64 name_size; c8 name[MAX_NAME_SIZE]; // TODO use string table @@ -359,7 +366,7 @@ typedef struct { typedef struct { b8 is_enabled; - i16 type; + u16 type; union { Node node; Proc proc; @@ -368,12 +375,20 @@ typedef struct { } Entity; typedef struct { + u16 type; + i64 name_size; + i64 name[MAX_NAME_SIZE]; + i64 address; + i64 size; +} Rel_Entry; + +typedef struct { i64 name_size; c8 *name; i64 section; i64 address; i64 size; -} Internal_Symbol_Entry; +} Symbol_Entry; // Pool, a collection of all entities. // @@ -392,9 +407,16 @@ typedef struct { // TODO Use string table for buffers also. typedef struct { - i64 max_code_size; - i64 entry_point; - u8 *code_buffer; + i64 max_num_rels; + i64 max_code_size; + i64 max_rodata_size; + i64 entry_point; + i64 num_rels; + i64 offset_code; + i64 offset_rodata; + Rel_Entry *rels; + u8 * buffer_code; + u8 * buffer_rodata; } Codegen_Context; typedef struct { @@ -408,13 +430,13 @@ typedef struct { i64 num_obj_files; - u8 * obj_file_buffer; - u8 * dependencies_buffer; - i64 * obj_file_offsets; - i64 * section_addresses; - Internal_Symbol_Entry *symbols; - c8 * not_found_buffer; - u8 * output_buffer; + u8 * obj_file_buffer; + u8 * dependencies_buffer; + i64 * obj_file_offsets; + i64 * section_addresses; + Symbol_Entry *symbols; + c8 * not_found_buffer; + u8 * output_buffer; } Linker_Context; // ================================================================ @@ -437,31 +459,31 @@ extern "C" { // void bx_log(i32 log_level, u32 line, c8 *file, c8 *format, ...); void bx_assert(b8 condition, c8 *message, u32 line, c8 *file); -void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data); +void io_dispatch(u16 op, i64 *id, i64 *size, void *data, void *user_data); // ================================================================ // // Main API // i64 pool_add(Pool *pool, Entity data); -void pool_remove(Pool *pool, i64 entity, i16 type); +void pool_remove(Pool *pool, i64 entity, u16 type); i64 node_init(Pool *pool, Node data); void node_destroy(Pool *pool, i64 node); i64 node_data_array_c8(Pool *pool, i64 size, c8 *data); i64 node_data_i64(Pool *pool, i64 value); -i64 node_ctrl_call(Pool *pool, i16 convention, i64 target_proc, i64 num_args, Var *args); -i64 node_ctrl_call_by_name(Pool *pool, i16 convention, i64 name_size, c8 *name, i64 num_args, Var *args); +i64 node_ctrl_call(Pool *pool, u16 convention, i64 target_proc, i64 num_args, Var *args); +i64 node_ctrl_call_by_name(Pool *pool, u16 convention, i64 name_size, c8 *name, i64 num_args, Var *args); i64 node_ctrl_ret(Pool *pool, i64 num_values, Var *values); i64 proc_init(Pool *pool); void proc_destroy(Pool *pool, i64 proc); -void proc_set_convention(Pool *pool, i64 proc, i16 convention); +void proc_set_convention(Pool *pool, i64 proc, u16 convention); void proc_set_name(Pool *pool, i64 proc, i64 name_size, c8 *name); void proc_node_add(Pool *pool, i64 proc, i64 node); void proc_node_remove(Pool *pool, i64 proc, i64 node); -i64 unit_init(Pool *pool, i16 type); +i64 unit_init(Pool *pool, u16 type); void unit_destroy(Pool *pool, i64 unit); void unit_proc_add(Pool *pool, i64 unit, i64 proc); void unit_proc_remove(Pool *pool, i64 unit, i64 proc); @@ -487,8 +509,8 @@ void io_chmod_exe(i64 f, void *user_data); #ifndef DISABLE_HELPERS i64 n_str(i64 proc, c8 *value); i64 n_i64(i64 proc, i64 value); -i64 n_call(i64 proc, i16 convention, i64 target_proc, i64 num_args, Var *args); -i64 n_call_by_name(i64 proc, i16 convention, c8 *name, i64 num_args, Var *args); +i64 n_call(i64 proc, u16 convention, i64 target_proc, i64 num_args, Var *args); +i64 n_call_by_name(i64 proc, u16 convention, c8 *name, i64 num_args, Var *args); i64 n_ret(i64 proc, i64 num_vals, Var *vals); i64 p_new(i64 unit, c8 *name); i64 p_new_entry(i64 unit, c8 *name); @@ -584,10 +606,10 @@ void bx_mem_set(void *dst, u8 val, i64 size) { ((u8 *)dst)[i] = val; } -void bx_mem_cpy(void *dst, void *src, i64 size) { +void bx_mem_cpy(void *dst, void *__restrict src, i64 size) { BX_CHECK(dst != NULL, "Invalid arguments",); BX_CHECK(src != NULL, "Invalid arguments",); - BX_CHECK(size > 0, "Invalid size",); + BX_CHECK(size >= 0, "Invalid size",); for (i64 i = 0; i < size; ++i) ((u8 *)dst)[i] = ((u8 *)src)[i]; @@ -705,7 +727,7 @@ i64 pool_add(Pool *pool, Entity data) { return id; } -void pool_remove(Pool *pool, i64 entity, i16 type) { +void pool_remove(Pool *pool, i64 entity, u16 type) { BX_CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); BX_CHECK(entity >= 0 && entity < pool->num_entities, "Buffer overflow",); BX_CHECK(pool->entities[entity].is_enabled, "Entity already removed",); @@ -741,7 +763,7 @@ i64 node_data_i64(Pool *pool, i64 value) { }); } -i64 node_ctrl_call(Pool *pool, i16 convention, i64 target_proc, i64 num_args, Var *args) { +i64 node_ctrl_call(Pool *pool, u16 convention, i64 target_proc, i64 num_args, Var *args) { BX_CHECK(num_args <= MAX_NUM_ARGS, "Array too big", UNDEFINED); Call call = { @@ -759,7 +781,7 @@ i64 node_ctrl_call(Pool *pool, i16 convention, i64 target_proc, i64 num_args, Va }); } -i64 node_ctrl_call_by_name(Pool *pool, i16 convention, i64 name_size, c8 *name, i64 num_args, Var *args) { +i64 node_ctrl_call_by_name(Pool *pool, u16 convention, i64 name_size, c8 *name, i64 num_args, Var *args) { BX_CHECK(num_args <= MAX_NUM_ARGS, "Array too big", UNDEFINED); Call call = { @@ -807,7 +829,7 @@ void proc_destroy(Pool *pool, i64 proc) { pool_remove(pool, proc, ENTITY_PROC); } -void proc_set_convention(Pool *pool, i64 proc, i16 convention) { +void proc_set_convention(Pool *pool, i64 proc, u16 convention) { BX_CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",); BX_CHECK(proc >= 0 && proc < pool->num_entities, "Buffer overflow",); BX_CHECK(pool->entities[proc].is_enabled, "Entity does not exist",); @@ -886,7 +908,7 @@ void proc_node_remove(Pool *pool, i64 proc, i64 node) { n->index_in_proc = UNDEFINED; } -i64 unit_init(Pool *pool, i16 type) { +i64 unit_init(Pool *pool, u16 type) { return pool_add(pool, (Entity) { .type = ENTITY_UNIT, .unit = (Unit) { @@ -1366,6 +1388,9 @@ void write_f64(u32 ordering, f64 x, void *v, void *v_end) { // https://man7.org/linux/man-pages/man2/syscalls.2.html // https://man7.org/linux/man-pages/man2/syscall.2.html // +// Linker scripts +// https://home.cs.colorado.edu/~main/cs1300/doc/gnu/ld_3.html +// // ---------------------------------------------------------------- // // TODO Experiment with mapping several p_vaddr into one p_paddr. @@ -1623,7 +1648,7 @@ typedef struct { i64 entry_size; i64 num_entries; Offset_Size data; -} Section_Header; +} Elf_Section_Header; typedef struct { Offset_Size name; @@ -1631,24 +1656,23 @@ typedef struct { u8 bind; i64 section; Offset_Size value; -} Symbol_Entry; +} Elf_Symbol_Entry; typedef struct { - Symbol_Entry symbol; - i64 offset; - u32 type; - i64 addent; -} Relx_Entry; + Elf_Symbol_Entry symbol; + i64 offset; + u32 type; + i64 addent; +} Elf_Relx_Entry; // ================================================================ // // Codegen // -i64 x86_64_emit_node( +void x86_64_emit_node( Pool * pool, Codegen_Context *codegen, - i64 offset, i64 node, u32 context ) { @@ -1658,8 +1682,8 @@ i64 x86_64_emit_node( Node *n = &pool->entities[node].node; - u8 *begin = codegen->code_buffer + offset; - u8 *end = codegen->code_buffer + codegen->max_code_size; + u8 *begin = codegen->buffer_code + codegen->offset_code; + u8 *end = codegen->buffer_code + codegen->max_code_size; switch (n->op) { case DATA_C8: @@ -1669,6 +1693,26 @@ i64 x86_64_emit_node( case CTRL_CALL: { BX_LOG(ERROR, "CTRL_CALL: not implemented", 0); + + if (0) { + BX_CHECK(n->call.convention == CONV_CDECL, "Not implemented", 0); + BX_CHECK(n->call.target_proc == UNDEFINED, "Not implemented", 0); + BX_CHECK(n->call.target_name_size > 0, "No proc name", 0); + + BX_CHECK(n->call.num_args == 1, "Not implemented", 0); + BX_CHECK(n->call.args[0].num == 1, "Not implemented", 0); + BX_CHECK(n->call.args[0].type == TYPE_PTR, "Not implemented", 0); + + i64 n_arg = n->call.args[0].node; + BX_CHECK(n_arg != UNDEFINED, "Internal", 0); + BX_CHECK(pool->entities[n_arg].is_enabled, "Internal", 0); + BX_CHECK(pool->entities[n_arg].type == ENTITY_NODE, "Internal", 0); + + Node *arg = &pool->entities[n_arg].node; + BX_CHECK(arg->op == DATA_C8, "Not implemented", 0); + + // TODO + } } break; case CTRL_RET: { @@ -1702,23 +1746,20 @@ i64 x86_64_emit_node( write_u8 (LE, 0x0f, begin + 10, end); // syscall write_u8 (LE, 0x05, begin + 11, end); - offset += 12; + codegen->offset_code += 12; } else { - BX_FAIL("Not implemented", 0); + BX_FAIL("Not implemented",); } } break; default: - BX_FAIL("Unknown operation", 0); + BX_FAIL("Unknown operation",); } - - return offset; } -i64 emit_proc( +void emit_proc( Pool * pool, Codegen_Context *codegen, - i64 offset, i64 proc, u16 arch, u32 context @@ -1736,12 +1777,10 @@ i64 emit_proc( // Now we assume that nodes are already sorted. for (i64 i = 0; i < p->num_nodes; ++i) - offset = x86_64_emit_node(pool, codegen, offset, p->nodes[i], context); - - return offset; + x86_64_emit_node(pool, codegen, p->nodes[i], context); } -i64 emit_unit(Pool *pool, Codegen_Context *codegen, i64 offset, i64 unit, u16 arch) { +void emit_unit(Pool *pool, Codegen_Context *codegen, i64 unit, u16 arch) { BX_CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments", 0); BX_CHECK(unit != UNDEFINED && pool->entities[unit].is_enabled, "No unit", 0); BX_CHECK(pool->entities[unit].type == ENTITY_UNIT, "Invalid entity", 0); @@ -1750,14 +1789,12 @@ i64 emit_unit(Pool *pool, Codegen_Context *codegen, i64 offset, i64 unit, u16 ar u32 context = 0; if (i == pool->entities[unit].unit.entry_point_index) { - codegen->entry_point = offset; + codegen->entry_point = codegen->offset_code; context |= EMIT_ENTRY_PROC; } - offset = emit_proc(pool, codegen, offset, pool->entities[unit].unit.procs[i], arch, context); + emit_proc(pool, codegen, pool->entities[unit].unit.procs[i], arch, context); } - - return offset; } // ================================================================ @@ -1898,14 +1935,14 @@ i64 elf_find_section_index_by_name( return 0; } -Section_Header elf_section( +Elf_Section_Header elf_section( Buffer_Context b, i64 index ) { Offset_Size names = elf_section_names_data(b); u8 * begin = b.begin + elf_section_header_offset(b, index); u8 * end = b.begin + b.elf.offset + b.elf.size; - BX_CHECK(end <= b.end, "Buffer overflow", (Section_Header) {0}); + BX_CHECK(end <= b.end, "Buffer overflow", (Elf_Section_Header) {0}); i64 name_index = (i64) read_u32(LE, begin, end); i64 size = read_i64(LE, begin + 32, end); @@ -1919,7 +1956,7 @@ Section_Header elf_section( type = SEC_NONE; } - return (Section_Header) { + return (Elf_Section_Header) { .name = elf_name_in_string_table(b, names, name_index), .type = type, .alloc = (flags & 2) == 2, @@ -1935,13 +1972,13 @@ Section_Header elf_section( }; } -Section_Header elf_find_section_by_name( +Elf_Section_Header elf_find_section_by_name( Buffer_Context b, c8 * name, i64 name_size ) { i64 index = elf_find_section_index_by_name(b, name, name_size); - return index == 0 ? (Section_Header) {0} : elf_section(b, index); + return index == 0 ? (Elf_Section_Header) {0} : elf_section(b, index); } c8 *elf_name_from_offset( @@ -1963,7 +2000,7 @@ i64 elf_find_related_section_index( i64 section_index ) { Offset_Size src_name = elf_section(b, section_index).name; - Section_Header dst = elf_section(b, section_index - 1); + Elf_Section_Header dst = elf_section(b, section_index - 1); if (src_name.size > dst.name.size && bx_mem_eq( @@ -1998,7 +2035,7 @@ Offset_Size elf_find_related_data( return elf_section(b, elf_find_related_section_index(b, section_index)).data; } -Symbol_Entry elf_symbol( +Elf_Symbol_Entry elf_symbol( Buffer_Context b, Offset_Size symbol_table, Offset_Size string_table, @@ -2007,8 +2044,8 @@ Symbol_Entry elf_symbol( u8 *begin = b.begin + symbol_table.offset + symbol_index * ELF_SYMBOL_ENTRY_SIZE; u8 *end = b.begin + symbol_table.offset + symbol_table.size; - BX_CHECK(end <= b.end, "Buffer overflow", (Symbol_Entry) {0}); - BX_CHECK(end <= b.begin + b.elf.offset + b.elf.size, "Buffer overflow", (Symbol_Entry) {0}); + BX_CHECK(end <= b.end, "Buffer overflow", (Elf_Symbol_Entry) {0}); + BX_CHECK(end <= b.begin + b.elf.offset + b.elf.size, "Buffer overflow", (Elf_Symbol_Entry) {0}); i64 sym_name = (i64) read_u32(LE, begin, end); u8 sym_info = read_u8 (LE, begin + 4, end); @@ -2028,7 +2065,7 @@ Symbol_Entry elf_symbol( (sym_info >> 4) == 2 ? BIND_WEAK : BIND_LOCAL; - return (Symbol_Entry) { + return (Elf_Symbol_Entry) { .name = elf_name_in_string_table(b, string_table, sym_name), .type = type, .bind = bind, @@ -2040,7 +2077,7 @@ Symbol_Entry elf_symbol( }; } -Relx_Entry elf_relx( +Elf_Relx_Entry elf_relx( Buffer_Context b, Offset_Size symbol_table, Offset_Size string_table, @@ -2051,16 +2088,16 @@ Relx_Entry elf_relx( u8 *begin = b.begin + relocations.offset + relx_index * (is_rela ? ELF_RELA_ENTRY_SIZE : ELF_REL_ENTRY_SIZE); u8 *end = begin + ELF_RELA_ENTRY_SIZE; - BX_CHECK(end <= b.end, "Buffer overflow", (Relx_Entry) {0}); - BX_CHECK(end <= b.begin + b.elf.offset + b.elf.size, "Buffer overflow", (Relx_Entry) {0}); - BX_CHECK(end <= b.begin + relocations.offset + relocations.size, "Buffer overflow", (Relx_Entry) {0}); + BX_CHECK(end <= b.end, "Buffer overflow", (Elf_Relx_Entry) {0}); + BX_CHECK(end <= b.begin + b.elf.offset + b.elf.size, "Buffer overflow", (Elf_Relx_Entry) {0}); + BX_CHECK(end <= b.begin + relocations.offset + relocations.size, "Buffer overflow", (Elf_Relx_Entry) {0}); i64 relx_offset = read_i64(LE, begin, end); u32 relx_type = read_u32(LE, begin + 8, end); i64 relx_sym = (i64) read_u32(LE, begin + 12, end); i64 relx_addent = is_rela ? read_i64(LE, begin + 16, end) : 0; - return (Relx_Entry) { + return (Elf_Relx_Entry) { .symbol = elf_symbol(b, symbol_table, string_table, relx_sym), .offset = relx_offset, .type = relx_type, @@ -2068,26 +2105,26 @@ Relx_Entry elf_relx( }; } -Symbol_Entry elf_find_symbol_by_name( +Elf_Symbol_Entry elf_find_symbol_by_name( Buffer_Context b, i64 symbol_table_index, Offset_Size string_table, c8 * name, i64 name_size ) { - Section_Header symbol_table = elf_section(b, symbol_table_index); + Elf_Section_Header symbol_table = elf_section(b, symbol_table_index); for (i64 i = 0; i < symbol_table.num_entries; ++i) { - Symbol_Entry sym = elf_symbol(b, symbol_table.data, string_table, i); + Elf_Symbol_Entry sym = elf_symbol(b, symbol_table.data, string_table, i); - BX_CHECK(b.begin + sym.name.offset + name_size <= b.end, "Buffer overflow", (Symbol_Entry) {0}); - BX_CHECK(sym.name.offset + name_size <= b.elf.size, "Buffer overflow", (Symbol_Entry) {0}); + BX_CHECK(b.begin + sym.name.offset + name_size <= b.end, "Buffer overflow", (Elf_Symbol_Entry) {0}); + BX_CHECK(sym.name.offset + name_size <= b.elf.size, "Buffer overflow", (Elf_Symbol_Entry) {0}); if (name_size == sym.name.size && bx_mem_eq(name, b.begin + sym.name.offset, name_size)) return sym; } - BX_FAIL("Not found", (Symbol_Entry) {0}); + BX_FAIL("Not found", (Elf_Symbol_Entry) {0}); } void elf_checks(Buffer_Context b) { @@ -2125,7 +2162,7 @@ void elf_dump(u32 log_level, Buffer_Context b) { Offset_Size symtab = elf_find_section_by_name(b, SECTION_SYMTAB, sizeof SECTION_SYMTAB - 1).data; for (i64 sec_index = 1; sec_index < headers.num; ++sec_index) { - Section_Header section = elf_section(b, sec_index); + Elf_Section_Header section = elf_section(b, sec_index); c8 *name = elf_name_from_offset(b, section.name); @@ -2155,7 +2192,7 @@ void elf_dump(u32 log_level, Buffer_Context b) { BX_LOG(log_level, " - -"); for (i64 sym_index = 1; sym_index < section.num_entries; ++sym_index) { - Symbol_Entry sym = elf_symbol(b, section.data, strtab, (u16) sym_index); + Elf_Symbol_Entry sym = elf_symbol(b, section.data, strtab, (u16) sym_index); c8 *name = elf_name_from_offset(b, sym.name); @@ -2194,7 +2231,7 @@ void elf_dump(u32 log_level, Buffer_Context b) { BX_LOG(log_level, " - -"); for (i64 relx_index = 0; relx_index < section.num_entries; ++relx_index) { - Relx_Entry relx = elf_relx(b, symtab, strtab, section.data, relx_index, section.type == SEC_RELA); + Elf_Relx_Entry relx = elf_relx(b, symtab, strtab, section.data, relx_index, section.type == SEC_RELA); BX_LOG( log_level, @@ -2242,7 +2279,7 @@ i64 unit_write_in_memory( BX_CHECK(linker->dependencies_buffer != NULL, "No dependencies buffer",); BX_CHECK(linker->obj_file_offsets != NULL, "No object file offsets buffer",); - i64 code_size = emit_unit(pool, codegen, 0, unit, arch); + emit_unit(pool, codegen, unit, arch); u16 num_program_headers = 4; i64 program_offset = bx_align(ELF_HEADER_SIZE + ELF_PROGRAM_HEADER_SIZE * num_program_headers, X86_64_ALIGNMENT); @@ -2251,12 +2288,12 @@ i64 unit_write_in_memory( i64 rotext_address = base_address + program_offset; i64 entry = rotext_address + codegen->entry_point; - Internal_Symbol_Entry sym_printf = {0}; + Symbol_Entry sym_printf = {0}; - i64 rotext_size = code_size; + i64 rotext_size = codegen->offset_code; i64 rwzval_size = 0; i64 rwdata_size = 0; - i64 rodata_size = 0; + i64 rodata_size = codegen->offset_rodata; i64 num_sections = 0; i64 num_symbols = 0; @@ -2279,7 +2316,7 @@ i64 unit_write_in_memory( linker->section_addresses[num_sections] = 0; - Section_Header section = elf_section(buf, sec_index); + Elf_Section_Header section = elf_section(buf, sec_index); if (!section.alloc) continue; @@ -2321,19 +2358,19 @@ i64 unit_write_in_memory( linker->section_addresses[sec_index_global] = 0; - Section_Header section = elf_section(buf, sec_index); + Elf_Section_Header section = elf_section(buf, sec_index); if (!section.alloc) continue; if (section.exec) - linker->section_addresses[sec_index_global] += rotext_address + code_size; + linker->section_addresses[sec_index_global] += rotext_address + codegen->offset_code; else if (section.write && section.type == SEC_NOBITS) linker->section_addresses[sec_index_global] += rwzval_address; else if (section.write) linker->section_addresses[sec_index_global] += rwdata_address; else if (section.data.size > 0) - linker->section_addresses[sec_index_global] += rodata_address; + linker->section_addresses[sec_index_global] += rodata_address + codegen->offset_rodata; } } @@ -2348,12 +2385,12 @@ i64 unit_write_in_memory( Offset_Size strtab = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data; for (i64 sec_index = 1; sec_index < headers.num; ++sec_index) { - Section_Header tab = elf_section(buf, sec_index); + Elf_Section_Header tab = elf_section(buf, sec_index); if (tab.type != SEC_SYMTAB) continue; for (i64 sym_index = 1; sym_index < tab.num_entries; ++sym_index) { - Symbol_Entry sym = elf_symbol(buf, tab.data, strtab, sym_index); + Elf_Symbol_Entry sym = elf_symbol(buf, tab.data, strtab, sym_index); c8 * sym_name = elf_name_from_offset(buf, sym.name); if (sym.section == 0) // undefined symbol @@ -2372,7 +2409,7 @@ i64 unit_write_in_memory( BX_CHECK(num_symbols < linker->max_num_symbols, "Too many symbols",); - linker->symbols[num_symbols++] = (Internal_Symbol_Entry) { + linker->symbols[num_symbols++] = (Symbol_Entry) { .name_size = sym.name.size, .name = sym_name, .section = sym_section, @@ -2453,7 +2490,7 @@ i64 unit_write_in_memory( Offset_Size symtab = elf_find_section_by_name(buf, SECTION_SYMTAB, sizeof SECTION_SYMTAB - 1).data; for (i64 sec_index = 1; sec_index < num_sections; ++sec_index, ++sec_index_global) { - Section_Header src_sec = elf_section(buf, sec_index); + Elf_Section_Header src_sec = elf_section(buf, sec_index); if (src_sec.type != SEC_REL && src_sec.type != SEC_RELA) continue; @@ -2462,11 +2499,11 @@ i64 unit_write_in_memory( BX_CHECK(dst_index >= 0 && dst_index < linker->max_num_sections, "Buffer overflow",); for (i64 entry_index = 0; entry_index < src_sec.num_entries; ++entry_index) { - Relx_Entry relx = elf_relx(buf, symtab, strtab, src_sec.data, entry_index, src_sec.type == SEC_RELA); + Elf_Relx_Entry relx = elf_relx(buf, symtab, strtab, src_sec.data, entry_index, src_sec.type == SEC_RELA); c8 *sym_name = elf_name_from_offset(buf, relx.symbol.name); - Internal_Symbol_Entry symbol = {0}; + Symbol_Entry symbol = {0}; if (relx.symbol.section == 0) { for (i64 i = 0; i < num_symbols; ++i) @@ -2492,7 +2529,7 @@ i64 unit_write_in_memory( not_found_size += relx.symbol.name.size + 1; } } else - symbol = (Internal_Symbol_Entry) { + symbol = (Symbol_Entry) { .section = sec_index_global, .address = relx.symbol.value.offset, .size = relx.symbol.value.size, @@ -2705,7 +2742,8 @@ i64 unit_write_in_memory( // Code // - bx_mem_cpy(o + rotext_offset, codegen->code_buffer, code_size); + bx_mem_cpy(o + rotext_offset, codegen->buffer_code, codegen->offset_code); + bx_mem_cpy(o + rodata_offset, codegen->buffer_rodata, codegen->offset_rodata); // ============================================================== // @@ -2716,13 +2754,13 @@ i64 unit_write_in_memory( Offset_Num headers = elf_section_headers(buf); for (i64 sec_index = 1; sec_index < headers.num; ++sec_index, ++num_sections) { - Section_Header section = elf_section(buf, sec_index); + Elf_Section_Header section = elf_section(buf, sec_index); if (linker->section_addresses[sec_index] == 0 || !section.alloc || section.data.size == 0) continue; u8 *p = o + (linker->section_addresses[sec_index] - base_address); - BX_CHECK(p >= linker->output_buffer + program_offset + code_size, "Buffer overflow",); + BX_CHECK(p >= linker->output_buffer + program_offset + codegen->offset_code, "Buffer overflow",); BX_CHECK(p + section.data.size <= linker->output_buffer + output_size, "Buffer overflow",); bx_mem_cpy(p, buf.begin + section.data.offset, section.data.size); } @@ -2831,10 +2869,13 @@ void unit_write( // // Cleanup + codegen->num_rels = 0; codegen->entry_point = 0; linker->num_obj_files = 0; - bx_mem_set(codegen->code_buffer, 0, codegen->max_code_size); + bx_mem_set(codegen->rels, 0, codegen->max_num_rels * sizeof *codegen->rels); + bx_mem_set(codegen->buffer_code, 0, codegen->max_code_size); + bx_mem_set(codegen->buffer_rodata, 0, codegen->max_rodata_size); bx_mem_set(linker->obj_file_buffer, 0, linker->max_obj_file_size); bx_mem_set(linker->dependencies_buffer, 0, linker->max_dependencies_size); bx_mem_set(linker->obj_file_offsets, 0, linker->max_num_obj_files * sizeof *linker->obj_file_offsets); @@ -2987,7 +3028,7 @@ void bx_assert(b8 condition, c8 *message, u32 line, c8 *file) { // IO dispatch procedure // -void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data) { +void io_dispatch(u16 op, i64 *id, i64 *size, void *data, void *user_data) { BX_CHECK(id != NULL, "Invalid arguments",); (void) user_data; @@ -3089,9 +3130,18 @@ Pool g_pool = { }; Codegen_Context g_codegen = { - .max_code_size = MAX_CODE_SIZE, - .entry_point = 0, - .code_buffer = (u8[MAX_CODE_SIZE]) {0}, + .max_num_rels = MAX_NUM_RELS, + .max_code_size = MAX_CODE_SIZE, + .max_rodata_size = MAX_CODE_SIZE, + + .entry_point = 0, + .num_rels = 0, + .offset_code = 0, + .offset_rodata = 0, + + .rels = (Rel_Entry[MAX_NUM_RELS]) {0}, + .buffer_code = (u8[MAX_CODE_SIZE]) {0}, + .buffer_rodata = (u8[MAX_CODE_SIZE]) {0}, }; Linker_Context g_linker = { @@ -3103,15 +3153,15 @@ Linker_Context g_linker = { .max_not_found_size = MAX_NOT_FOUND_SIZE, .max_output_size = MAX_OUTPUT_SIZE, - .num_obj_files = 0, + .num_obj_files = 0, - .obj_file_buffer = (u8[MAX_OBJECT_FILE_SIZE]) {0}, - .dependencies_buffer = (u8[MAX_DEPENDENCIES_SIZE]) {0}, - .obj_file_offsets = (i64[MAX_NUM_OBJECT_FILES]) {0}, - .section_addresses = (i64[MAX_NUM_SECTIONS]) {0}, - .symbols = (Internal_Symbol_Entry[MAX_NUM_SYMBOLS]) {0}, - .not_found_buffer = (c8[MAX_NOT_FOUND_SIZE]) {0}, - .output_buffer = (u8[MAX_OUTPUT_SIZE]) {0}, + .obj_file_buffer = (u8[MAX_OBJECT_FILE_SIZE]) {0}, + .dependencies_buffer = (u8[MAX_DEPENDENCIES_SIZE]) {0}, + .obj_file_offsets = (i64[MAX_NUM_OBJECT_FILES]) {0}, + .section_addresses = (i64[MAX_NUM_SECTIONS]) {0}, + .symbols = (Symbol_Entry[MAX_NUM_SYMBOLS]) {0}, + .not_found_buffer = (c8[MAX_NOT_FOUND_SIZE]) {0}, + .output_buffer = (u8[MAX_OUTPUT_SIZE]) {0}, }; // Handy procedures @@ -3130,13 +3180,13 @@ i64 n_i64(i64 proc, i64 value) { return n; } -i64 n_call(i64 proc, i16 convention, i64 target_proc, i64 num_args, Var *args) { +i64 n_call(i64 proc, u16 convention, i64 target_proc, i64 num_args, Var *args) { i64 n = node_ctrl_call(&g_pool, convention, target_proc, num_args, args); p_add(proc, n); return n; } -i64 n_call_by_name(i64 proc, i16 convention, c8 *name, i64 num_args, Var *args) { +i64 n_call_by_name(i64 proc, u16 convention, c8 *name, i64 num_args, Var *args) { i64 n = node_ctrl_call_by_name(&g_pool, convention, bx_str_len(name, name + MAX_NAME_SIZE), name, num_args, args); p_add(proc, n); return n; |