diff options
Diffstat (limited to 'bxgen.c')
-rwxr-xr-x | bxgen.c | 304 |
1 files changed, 164 insertions, 140 deletions
@@ -37,11 +37,10 @@ exit $? // - ELF + x86_64 executable // - x86_64 object file // - Linking libraries -// - String table for names +// - String table for names and arrays // - Proper error handling // - Proper prefixes for identifiers // - Effective entity allocation -// - Hybrid-linked lists for large entities // - Implicit procedure prototypes // - Implicit exit after ret from entry point // - Static single-assignment @@ -157,18 +156,12 @@ enum { // Entity types // - ENTITY_TAIL = 0, - ENTITY_NODE, + ENTITY_NODE = 0, ENTITY_PROC, ENTITY_UNIT, // Limits // - // NOTE - // - // All limits can be exceeded using the linked list of entities - // (see `Entity::tail`), except for `MAX_ENTITY_COUNT`. - // MAX_LITERAL_SIZE = 400, MAX_NAME_SIZE = 80, @@ -220,7 +213,6 @@ typedef struct { // A semantic node is an operation with optional data // and possible references to other nodes. -// typedef struct { i16 op; @@ -235,7 +227,6 @@ typedef struct { // A procedure is a collection of semantic nodes // and has a string name. -// typedef struct { i16 convention; @@ -269,23 +260,14 @@ typedef struct { // // Every entity can be referenced by it's unique index // in the entity pool. -// -// If the entity's data doesn't fit in one entity, tail is -// an index that leads to the entity with the rest of the -// data, forming a linked list. -// typedef struct { b8 is_enabled; i16 type; - i64 tail; union { Node node; Proc proc; Unit unit; - c8 tail_chars[1]; - i64 tail_ids[1]; - Var tail_vars[1]; }; } Entity; @@ -293,7 +275,6 @@ typedef struct { // // NOTE // We use one single large memory block for *everything*. -// typedef struct { i64 entity_count; @@ -341,7 +322,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_id, void *io_user_data) i64 io_open_read(i64 name_size, c8 *name, void *user_data); i64 io_open_write(i64 name_size, c8 *name, void *user_data); void io_close(i64 f, void *user_data); -i64 io_seek(i64 f, i64 offset, u16 origin, void *user_data); +b8 io_seek(i64 f, i64 offset, u16 origin, void *user_data); i64 io_read(i64 f, i64 size, void *data, void *user_data); i64 io_write(i64 f, i64 size, void *data, void *user_data); void io_chmod_exe(i64 f, void *user_data); @@ -448,7 +429,6 @@ i64 node_init(Pool *pool, Node data) { return pool_add(pool, (Entity) { .type = ENTITY_NODE, - .tail = UNDEFINED, .node = data, }); } @@ -519,7 +499,6 @@ i64 node_ctrl_ret(Pool *pool, i64 value_count, Var *values) { i64 proc_init(Pool *pool) { return pool_add(pool, (Entity) { .type = ENTITY_PROC, - .tail = UNDEFINED, .proc = (Proc) { .ret_index = UNDEFINED, .index_in_unit = UNDEFINED, @@ -544,9 +523,6 @@ void proc_set_name(Pool *pool, i64 proc, i64 name_size, c8 *name) { BX_ASSERT(pool->entities[proc].is_enabled); BX_ASSERT(pool->entities[proc].type == ENTITY_PROC); - // TODO - // Implement large entities. - BX_ASSERT(name_size <= MAX_NAME_SIZE); BX_ASSERT(name_size >= 0); @@ -569,9 +545,6 @@ void proc_node_add(Pool *pool, i64 proc, i64 node) { BX_ASSERT(n->index_in_proc == UNDEFINED); - // TODO - // Implement large entities. - i64 index = p->node_count; if (n->op == CTRL_RET) @@ -599,9 +572,6 @@ void proc_node_remove(Pool *pool, i64 proc, i64 node) { Proc *p = &pool->entities[proc].proc; Node *n = &pool->entities[node].node; - // TODO - // Implement large entities. - BX_ASSERT(n->index_in_proc != UNDEFINED); BX_ASSERT(p->nodes[n->index_in_proc] == node); @@ -617,7 +587,6 @@ void proc_node_remove(Pool *pool, i64 proc, i64 node) { i64 unit_init(Pool *pool, i16 type) { return pool_add(pool, (Entity) { .type = ENTITY_UNIT, - .tail = UNDEFINED, .unit = (Unit) { .type = type, .entry_point_index = UNDEFINED, @@ -641,9 +610,6 @@ void unit_proc_add(Pool *pool, i64 unit, i64 proc) { BX_ASSERT(p->index_in_unit == UNDEFINED); - // TODO - // Implement large entities. - i64 index = u->proc_count; BX_ASSERT(index < MAX_PROC_COUNT); @@ -662,9 +628,6 @@ void unit_proc_remove(Pool *pool, i64 unit, i64 proc) { Unit *u = &pool->entities[unit].unit; Proc *p = &pool->entities[proc].proc; - // TODO - // Implement large entities. - BX_ASSERT(p->index_in_unit != UNDEFINED); BX_ASSERT(u->procs[p->index_in_unit] == proc); @@ -714,9 +677,6 @@ void unit_set_name(Pool *pool, i64 unit, i64 name_size, c8 *name) { BX_ASSERT(pool->entities[unit].is_enabled); BX_ASSERT(pool->entities[unit].type == ENTITY_UNIT); - // TODO - // Implement large entities. - BX_ASSERT(name_size <= MAX_NAME_SIZE); BX_ASSERT(name_size >= 0); @@ -756,6 +716,48 @@ void unit_set_entry_point(Pool *pool, i64 unit, i64 entry_point_proc) { #include <stdio.h> // TEMP #include <stdlib.h> // TEMP +enum { + MAX_SECTION_SIZE = 1024 * 1024 * 10, + MAX_INPUT_SIZE = 1024 * 1024 * 100, + MAX_RELOCATIONS = 1024 * 10, + MAX_INPUT_SECTIONS = 1024 * 10, +}; + +typedef struct { + i64 memory_address; + i64 file_offset; + i64 size; + u8 bytes[MAX_SECTION_SIZE]; +} Section; + +typedef struct { + i64 src_section; + i64 src_file_offset; + i64 src_size; + i64 dst_section; + i64 dst_memory_address; +} Relocation; + +typedef struct { + i64 object_index; + i64 section_index; + i64 file_offset; + i64 size; +} Input_Section_Info; + +typedef struct { + Section exec; + Section read_only; + Section read_write; + Section zero_init; + i64 relocs_size; + Relocation relocs[MAX_RELOCATIONS]; + i64 input_raw_size; + u8 input_raw[MAX_INPUT_SIZE]; + i64 input_sections_size; + Input_Section_Info input_sections[MAX_INPUT_SECTIONS]; +} Binary_Output; + void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data) { // Docs // @@ -765,7 +767,6 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data // LLVM impl https://github.com/llvm/llvm-project/blob/main/lld/ELF/Driver.cpp#L2822 // https://github.com/llvm/llvm-project/blob/main/lld/ELF/Writer.cpp#L304 // https://github.com/llvm/llvm-project/blob/main/lld/ELF/OutputSections.cpp#L469 - // BX_ASSERT(pool != NULL && pool->entities != NULL); BX_ASSERT(pool->entities[unit].is_enabled); @@ -845,10 +846,10 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data WRITE_4( 1 ); // type (PT_LOAD) WRITE_4( 5 ); // flags (PF_X | PF_R) WRITE_8( code_offset ); // offset - WRITE_8( code_address ); // vaddr - WRITE_8( code_address ); // paddr - WRITE_8( code_size ); // filesz - WRITE_8( code_size ); // memsz + WRITE_8( code_address ); // virtual address + WRITE_8( code_address ); // phisical address + WRITE_8( code_size ); // size in file + WRITE_8( code_size ); // size in memory WRITE_8( 8 ); // align // Code @@ -890,8 +891,9 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data i64 n = 0, current_offset = 0; - // Read AR + // ================================================================ // + // Read AR library u8 magic[8]; @@ -1043,8 +1045,9 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data printf(" <SYMBOLS NOT FOUND>\n"); } - // Decode ELF object file + // ================================================================ // + // Decode ELF object file i64 byte_count = atoi(size); if ((byte_count & 1) == 1) @@ -1294,102 +1297,119 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data printf("\n"); - if (type == 2) { - // Find symbol addresses + switch (type) { + // ================================================================ // + // Symbols - BX_ASSERT(entsize == 24); + case 2: { + // Find symbol addresses + // - i64 prev_offset = current_offset; - i64 prev_byte_count = byte_count; - io_seek(f, - begin_offset + offset, - IO_SEEK_BEGIN, io_user_data); - current_offset = begin_offset + offset; + BX_ASSERT(entsize == 24); - printf("\n"); + i64 prev_offset = current_offset; + i64 prev_byte_count = byte_count; + io_seek(f, + begin_offset + offset, + IO_SEEK_BEGIN, io_user_data); + current_offset = begin_offset + offset; + + printf("\n"); - for (byte_count = size; byte_count > 0;) { - BX_ASSERT(symbol_names_found); - - u32 sym_name; - u8 sym_info; - u8 sym_other; - u16 sym_shndx; - u64 sym_value; - u64 sym_size; - - READ(sym_name); BX_ASSERT(n != 0); - READ(sym_info); BX_ASSERT(n != 0); - READ(sym_other); BX_ASSERT(n != 0); - READ(sym_shndx); BX_ASSERT(n != 0); - READ(sym_value); BX_ASSERT(n != 0); - READ(sym_size); BX_ASSERT(n != 0); - - printf(" "); - - if (sym_name != 0) { - if (sym_name < symbol_names_size) { - // Search for the symbol name in the string table - // - - i64 prev_offset = current_offset; - io_seek(f, - begin_offset + symbol_names_offset + sym_name, - IO_SEEK_BEGIN, io_user_data); - - i32 padding = 48; - - if ((sym_info & 0xf) == 1 || - (sym_info & 0xf) == 2) - printf("%s", "\x1b[32m"); - - printf("\""); - - for (;; --padding) { - c8 c; - n = io_read(f, 1, &c, io_user_data); if (n == 0) break; - if (c == '\0') - break; - printf("%c", c); - } - - printf("\""); - if ((sym_info & 0xf) == 1 || - (sym_info & 0xf) == 2) - printf("%s", "\x1b[37m"); - if (padding > 0) - printf("%*s", padding, ""); - - io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); - current_offset = prev_offset; + for (byte_count = size; byte_count > 0;) { + BX_ASSERT(symbol_names_found); + + u32 sym_name; + u8 sym_info; + u8 sym_other; + u16 sym_shndx; + u64 sym_value; + u64 sym_size; + + READ(sym_name); BX_ASSERT(n != 0); + READ(sym_info); BX_ASSERT(n != 0); + READ(sym_other); BX_ASSERT(n != 0); + READ(sym_shndx); BX_ASSERT(n != 0); + READ(sym_value); BX_ASSERT(n != 0); + READ(sym_size); BX_ASSERT(n != 0); + + printf(" "); + + if (sym_name != 0) { + if (sym_name < symbol_names_size) { + // Search for the symbol name in the string table + // + + i64 prev_offset = current_offset; + io_seek(f, + begin_offset + symbol_names_offset + sym_name, + IO_SEEK_BEGIN, io_user_data); + + i32 padding = 48; + + if ((sym_info & 0xf) == 1 || + (sym_info & 0xf) == 2) + printf("%s", "\x1b[32m"); + + printf("\""); + + for (;; --padding) { + c8 c; + n = io_read(f, 1, &c, io_user_data); if (n == 0) break; + if (c == '\0') + break; + printf("%c", c); + } + + printf("\""); + if ((sym_info & 0xf) == 1 || + (sym_info & 0xf) == 2) + printf("%s", "\x1b[37m"); + if (padding > 0) + printf("%*s", padding, ""); + + io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); + current_offset = prev_offset; + } else + printf("%-50d", sym_name); } else - printf("%-50d", sym_name); - } else - printf("%*s", 50, ""); - - printf("%08llx ", sym_value); - - printf("%-8s ", - (sym_info & 0xf) <= 4 ? (c8 const *[]) { - "No type", - "Data", - "Func", - "Section", - "File", - }[sym_info & 0xf] : "" - ); - - if (sym_size != 0) - printf("- %lld bytes", sym_size); + printf("%*s", 50, ""); + + printf("%08llx ", sym_value); // symbol address + + printf("%-8s ", + (sym_info & 0xf) <= 4 ? (c8 const *[]) { + "No type", + "Data", + "Func", + "Section", + "File", + }[sym_info & 0xf] : "" + ); + + if (sym_size != 0) + printf("- %lld bytes", sym_size); + printf("\n"); + } + printf("\n"); - } - printf("\n"); + io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); + current_offset = prev_offset; + byte_count = prev_byte_count; + } break; - io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); - current_offset = prev_offset; - byte_count = prev_byte_count; + // ================================================================ + // + // Relocarions with addends + + case 4: { + } break; + + // ================================================================ + + default:; } } @@ -1399,6 +1419,8 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data current_offset += byte_count; #undef READ + + // ================================================================ } } @@ -1408,6 +1430,8 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data "<FILE NOT FOUND>", symbols[symbol_index]); + // ================================================================ + io_close(f, io_user_data); } } @@ -1429,9 +1453,9 @@ void io_close(i64 f, void *user_data) { io_dispatch(IO_CLOSE, &f, NULL, NULL, user_data); } -i64 io_seek(i64 f, i64 offset, u16 origin, void *user_data) { +b8 io_seek(i64 f, i64 offset, u16 origin, void *user_data) { io_dispatch(IO_SEEK, &f, &offset, &origin, user_data); - return offset; + return 1; } i64 io_read(i64 f, i64 size, void *data, void *user_data) { @@ -1564,7 +1588,7 @@ static Pool g_pool = { // // TODO // Reallocate the memory block when necessary. - // + .capacity = MAX_ENTITY_COUNT, .entities = (Entity[MAX_ENTITY_COUNT]) { 0 }, }; |