diff options
-rwxr-xr-x | bxgen.c | 492 |
1 files changed, 293 insertions, 199 deletions
@@ -194,10 +194,6 @@ enum { IO_SEEK_END, }; -// A semantic node is an operation with optional data -// and possible references to other nodes. -// - typedef struct { i16 size; i16 type; @@ -217,11 +213,15 @@ typedef struct { i16 convention; // can be implicitly retrieved from the procedure i64 target_proc; i64 target_name_size; - c8 target_name[MAX_NAME_SIZE]; + c8 target_name[MAX_NAME_SIZE]; // TODO use string table i64 arg_count; Var args[MAX_ARG_COUNT]; } Call; +// A semantic node is an operation with optional data +// and possible references to other nodes. +// + typedef struct { i16 op; i64 index_in_proc; @@ -240,7 +240,7 @@ typedef struct { typedef struct { i16 convention; i64 name_size; - c8 name[MAX_NAME_SIZE]; + c8 name[MAX_NAME_SIZE]; // TODO use string table i64 node_count; i64 nodes[MAX_NODE_COUNT]; i64 ret_index; @@ -255,7 +255,7 @@ typedef struct { i16 type; i64 entry_point_index; i64 name_size; - c8 name[MAX_NAME_SIZE]; + c8 name[MAX_NAME_SIZE]; // TODO use string table i64 proc_count; i64 procs[MAX_PROC_COUNT]; i64 link_count; @@ -346,6 +346,7 @@ 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); +void bx_assert(b8 condition, c8 const *message, u32 line, c8 const *file); void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data); #ifndef DISABLE_HELPERS @@ -380,15 +381,52 @@ void l_static(i64 unit, c8 *static_library); #error Implementation code should be compiled with a C compiler! #endif -#include <string.h> // memcpy -#include <assert.h> // assert +// Utils +// + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#define BX_ASSERT(condition) \ + bx_assert((condition), #condition, __LINE__, __FILE__) + +static void bx_memcpy(void *dst, void const *src, i64 size) { + BX_ASSERT(dst != NULL); + BX_ASSERT(src != NULL); + BX_ASSERT(size > 0); + + for (i64 i = 0; i < size; ++i) + ((u8 *)dst)[i] = ((u8 const *)src)[i]; +} + +static b8 bx_str_eq(c8 const *a, c8 const *b) { + BX_ASSERT(a != NULL); + BX_ASSERT(b != NULL); + + while (*a == *b && *a != '\0' && *b != '\0') { + ++a; + ++b; + } + + return *a == '\0' && *b == '\0'; +} + +static c8 *bx_find_char(c8 *s, c8 c) { + BX_ASSERT(s != NULL); + + while (*s != '\0' && *s != c) + ++s; + + return *s == c ? s : NULL; +} // IR building procs // i64 pool_add(Pool *pool, Entity data) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entity_count < pool->capacity); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entity_count < pool->capacity); i64 id = pool->entity_count++; data.is_enabled = 1, @@ -398,9 +436,9 @@ i64 pool_add(Pool *pool, Entity data) { } void pool_remove(Pool *pool, i64 entity, i16 type) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[entity].is_enabled); - assert(pool->entities[entity].type == type); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[entity].is_enabled); + BX_ASSERT(pool->entities[entity].type == type); pool->entities[entity].is_enabled = 1; } @@ -427,7 +465,7 @@ i64 node_data_i64(Pool *pool, i64 value) { } i64 node_ctrl_call(Pool *pool, i16 convention, i64 target_proc, i64 arg_count, Var *args) { - assert(arg_count <= MAX_ARG_COUNT); + BX_ASSERT(arg_count <= MAX_ARG_COUNT); Call call = { .convention = convention, @@ -436,7 +474,7 @@ i64 node_ctrl_call(Pool *pool, i16 convention, i64 target_proc, i64 arg_count, V }; if (arg_count > 0) - memcpy(call.args, args, arg_count * sizeof *args); + bx_memcpy(call.args, args, arg_count * sizeof *args); return node_init(pool, (Node) { .op = CTRL_CALL, @@ -445,7 +483,7 @@ i64 node_ctrl_call(Pool *pool, i16 convention, i64 target_proc, i64 arg_count, V } i64 node_ctrl_call_by_name(Pool *pool, i16 convention, i64 name_size, c8 *name, i64 arg_count, Var *args) { - assert(arg_count <= MAX_ARG_COUNT); + BX_ASSERT(arg_count <= MAX_ARG_COUNT); Call call = { .convention = convention, @@ -454,9 +492,9 @@ i64 node_ctrl_call_by_name(Pool *pool, i16 convention, i64 name_size, c8 *name, }; if (name_size > 0) - memcpy(call.target_name, name, name_size); + bx_memcpy(call.target_name, name, name_size); if (arg_count > 0) - memcpy(call.args, args, arg_count * sizeof *args); + bx_memcpy(call.args, args, arg_count * sizeof *args); return node_init(pool, (Node) { .op = CTRL_CALL, @@ -465,12 +503,12 @@ i64 node_ctrl_call_by_name(Pool *pool, i16 convention, i64 name_size, c8 *name, } i64 node_ctrl_ret(Pool *pool, i64 value_count, Var *values) { - assert(value_count <= MAX_ARG_COUNT); + BX_ASSERT(value_count <= MAX_ARG_COUNT); Ret ret = { .val_count = value_count, }; if (value_count > 0) - memcpy(ret.vals, values, value_count * sizeof *values); + bx_memcpy(ret.vals, values, value_count * sizeof *values); return node_init(pool, (Node) { .op = CTRL_RET, @@ -494,42 +532,42 @@ void proc_destroy(Pool *pool, i64 proc) { } void proc_set_convention(Pool *pool, i64 proc, i16 convention) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[proc].is_enabled); - assert(pool->entities[proc].type == ENTITY_PROC); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[proc].is_enabled); + BX_ASSERT(pool->entities[proc].type == ENTITY_PROC); pool->entities[proc].proc.convention = convention; } void proc_set_name(Pool *pool, i64 proc, i64 name_size, c8 *name) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[proc].is_enabled); - assert(pool->entities[proc].type == ENTITY_PROC); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[proc].is_enabled); + BX_ASSERT(pool->entities[proc].type == ENTITY_PROC); // TODO // Implement large entities. - assert(name_size <= MAX_NAME_SIZE); - assert(name_size >= 0); + BX_ASSERT(name_size <= MAX_NAME_SIZE); + BX_ASSERT(name_size >= 0); Proc *p = &pool->entities[proc].proc; p->name_size = name_size; if (name_size > 0) - memcpy(p->name, name, name_size); + bx_memcpy(p->name, name, name_size); } void proc_node_add(Pool *pool, i64 proc, i64 node) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[proc].is_enabled); - assert(pool->entities[proc].type == ENTITY_PROC); - assert(pool->entities[node].is_enabled); - assert(pool->entities[node].type == ENTITY_NODE); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[proc].is_enabled); + BX_ASSERT(pool->entities[proc].type == ENTITY_PROC); + BX_ASSERT(pool->entities[node].is_enabled); + BX_ASSERT(pool->entities[node].type == ENTITY_NODE); Proc *p = &pool->entities[proc].proc; Node *n = &pool->entities[node].node; - assert(n->index_in_proc == UNDEFINED); + BX_ASSERT(n->index_in_proc == UNDEFINED); // TODO // Implement large entities. @@ -541,11 +579,11 @@ void proc_node_add(Pool *pool, i64 proc, i64 node) { // Only one return node is allowed. // - assert(p->ret_index == UNDEFINED); + BX_ASSERT(p->ret_index == UNDEFINED); p->ret_index = index; } - assert(index < MAX_NODE_COUNT); + BX_ASSERT(index < MAX_NODE_COUNT); n->index_in_proc = index; p->nodes[index] = node; @@ -553,10 +591,10 @@ void proc_node_add(Pool *pool, i64 proc, i64 node) { } void proc_node_remove(Pool *pool, i64 proc, i64 node) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[proc].is_enabled); - assert(pool->entities[proc].type == ENTITY_PROC); - assert(pool->entities[node].type == ENTITY_NODE); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[proc].is_enabled); + BX_ASSERT(pool->entities[proc].type == ENTITY_PROC); + BX_ASSERT(pool->entities[node].type == ENTITY_NODE); Proc *p = &pool->entities[proc].proc; Node *n = &pool->entities[node].node; @@ -564,11 +602,11 @@ void proc_node_remove(Pool *pool, i64 proc, i64 node) { // TODO // Implement large entities. - assert(n->index_in_proc != UNDEFINED); - assert(p->nodes[n->index_in_proc] == node); + BX_ASSERT(n->index_in_proc != UNDEFINED); + BX_ASSERT(p->nodes[n->index_in_proc] == node); if (n->op == CTRL_RET) { - assert(p->ret_index != UNDEFINED); + BX_ASSERT(p->ret_index != UNDEFINED); p->ret_index = UNDEFINED; } @@ -592,23 +630,23 @@ void unit_destroy(Pool *pool, i64 unit) { } void unit_proc_add(Pool *pool, i64 unit, i64 proc) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[unit].is_enabled); - assert(pool->entities[unit].type == ENTITY_UNIT); - assert(pool->entities[proc].is_enabled); - assert(pool->entities[proc].type == ENTITY_PROC); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[unit].is_enabled); + BX_ASSERT(pool->entities[unit].type == ENTITY_UNIT); + BX_ASSERT(pool->entities[proc].is_enabled); + BX_ASSERT(pool->entities[proc].type == ENTITY_PROC); Unit *u = &pool->entities[unit].unit; Proc *p = &pool->entities[proc].proc; - assert(p->index_in_unit == UNDEFINED); + BX_ASSERT(p->index_in_unit == UNDEFINED); // TODO // Implement large entities. i64 index = u->proc_count; - assert(index < MAX_PROC_COUNT); + BX_ASSERT(index < MAX_PROC_COUNT); p->index_in_unit = index; u->procs[index] = proc; @@ -616,10 +654,10 @@ void unit_proc_add(Pool *pool, i64 unit, i64 proc) { } void unit_proc_remove(Pool *pool, i64 unit, i64 proc) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[unit].is_enabled); - assert(pool->entities[unit].type == ENTITY_UNIT); - assert(pool->entities[proc].type == ENTITY_PROC); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[unit].is_enabled); + BX_ASSERT(pool->entities[unit].type == ENTITY_UNIT); + BX_ASSERT(pool->entities[proc].type == ENTITY_PROC); Unit *u = &pool->entities[unit].unit; Proc *p = &pool->entities[proc].proc; @@ -627,8 +665,8 @@ void unit_proc_remove(Pool *pool, i64 unit, i64 proc) { // TODO // Implement large entities. - assert(p->index_in_unit != UNDEFINED); - assert(u->procs[p->index_in_unit] == proc); + BX_ASSERT(p->index_in_unit != UNDEFINED); + BX_ASSERT(u->procs[p->index_in_unit] == proc); if (u->entry_point_index == p->index_in_unit) u->entry_point_index = UNDEFINED; @@ -638,11 +676,11 @@ void unit_proc_remove(Pool *pool, i64 unit, i64 proc) { } void unit_link_add(Pool *pool, i64 unit, i64 link_unit) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[unit].is_enabled); - assert(pool->entities[unit].type == ENTITY_UNIT); - assert(pool->entities[link_unit].is_enabled); - assert(pool->entities[link_unit].type == ENTITY_UNIT); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[unit].is_enabled); + BX_ASSERT(pool->entities[unit].type == ENTITY_UNIT); + BX_ASSERT(pool->entities[link_unit].is_enabled); + BX_ASSERT(pool->entities[link_unit].type == ENTITY_UNIT); Unit *u = &pool->entities[unit].unit; @@ -650,15 +688,15 @@ void unit_link_add(Pool *pool, i64 unit, i64 link_unit) { if (u->links[i] == link_unit) return; - assert(u->link_count < MAX_LINK_COUNT); + BX_ASSERT(u->link_count < MAX_LINK_COUNT); u->links[u->link_count++] = link_unit; } void unit_link_remove(Pool *pool, i64 unit, i64 link_unit) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[unit].is_enabled); - assert(pool->entities[unit].type == ENTITY_UNIT); - assert(pool->entities[link_unit].type == ENTITY_UNIT); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[unit].is_enabled); + BX_ASSERT(pool->entities[unit].type == ENTITY_UNIT); + BX_ASSERT(pool->entities[link_unit].type == ENTITY_UNIT); Unit *u = &pool->entities[unit].unit; @@ -668,31 +706,31 @@ void unit_link_remove(Pool *pool, i64 unit, i64 link_unit) { return; } - assert(0); + BX_ASSERT(0); } void unit_set_name(Pool *pool, i64 unit, i64 name_size, c8 *name) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[unit].is_enabled); - assert(pool->entities[unit].type == ENTITY_UNIT); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[unit].is_enabled); + BX_ASSERT(pool->entities[unit].type == ENTITY_UNIT); // TODO // Implement large entities. - assert(name_size <= MAX_NAME_SIZE); - assert(name_size >= 0); + BX_ASSERT(name_size <= MAX_NAME_SIZE); + BX_ASSERT(name_size >= 0); Unit *u = &pool->entities[unit].unit; u->name_size = name_size; if (name_size > 0) - memcpy(u->name, name, name_size); + bx_memcpy(u->name, name, name_size); } void unit_set_entry_point(Pool *pool, i64 unit, i64 entry_point_proc) { - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[unit].is_enabled); - assert(pool->entities[unit].type == ENTITY_UNIT); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[unit].is_enabled); + BX_ASSERT(pool->entities[unit].type == ENTITY_UNIT); Unit *u = &pool->entities[unit].unit; @@ -701,13 +739,13 @@ void unit_set_entry_point(Pool *pool, i64 unit, i64 entry_point_proc) { return; } - assert(pool->entities[entry_point_proc].is_enabled); - assert(pool->entities[entry_point_proc].type == ENTITY_PROC); + BX_ASSERT(pool->entities[entry_point_proc].is_enabled); + BX_ASSERT(pool->entities[entry_point_proc].type == ENTITY_PROC); Proc *p = &pool->entities[entry_point_proc].proc; - assert(p->index_in_unit != UNDEFINED); - assert(u->procs[p->index_in_unit] == entry_point_proc); + BX_ASSERT(p->index_in_unit != UNDEFINED); + BX_ASSERT(u->procs[p->index_in_unit] == entry_point_proc); pool->entities[unit].unit.entry_point_index = p->index_in_unit; } @@ -729,10 +767,10 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data // https://github.com/llvm/llvm-project/blob/main/lld/ELF/OutputSections.cpp#L469 // - assert(pool != NULL && pool->entities != NULL); - assert(pool->entities[unit].is_enabled); - assert(pool->entities[unit].unit.entry_point_index != UNDEFINED); - assert(target == (FORMAT_ELF | ARCH_X86_64)); + BX_ASSERT(pool != NULL && pool->entities != NULL); + BX_ASSERT(pool->entities[unit].is_enabled); + BX_ASSERT(pool->entities[unit].unit.entry_point_index != UNDEFINED); + BX_ASSERT(target == (FORMAT_ELF | ARCH_X86_64)); // ELF config // @@ -771,8 +809,8 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data u64 code_address = base_address + code_offset; u64 entry = code_address + entry_offset; - assert((code_offset % align) == 0); - assert((code_size % align) == 0); + BX_ASSERT((code_offset % align) == 0); + BX_ASSERT((code_size % align) == 0); // ELF header // @@ -837,17 +875,17 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data if (u->links[i] == UNDEFINED) continue; - i64 index = u->links[i]; + i64 index = u->links[i]; Unit *l = &pool->entities[index].unit; - assert(pool->entities[index].is_enabled); - assert(l->type == UNIT_LIBRARY_STATIC); - assert(l->name_size > 0 && l->name_size <= MAX_NAME_SIZE); + BX_ASSERT(pool->entities[index].is_enabled); + BX_ASSERT(l->type == UNIT_LIBRARY_STATIC); + BX_ASSERT(l->name_size > 0 && l->name_size <= MAX_NAME_SIZE); i64 f = io_open_read(l->name_size, l->name, io_user_data); c8 buf0_[MAX_NAME_SIZE + 1] = { 0 }; - memcpy(buf0_, l->name, l->name_size); + bx_memcpy(buf0_, l->name, l->name_size); printf("\nReading `%s` library...\n\n", buf0_); i64 n = 0, current_offset = 0; @@ -860,14 +898,14 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data n = io_read(f, sizeof magic, magic, io_user_data); if (n == 0) continue; current_offset += n; - assert(magic[0] == '!'); - assert(magic[1] == '<'); - assert(magic[2] == 'a'); - assert(magic[3] == 'r'); - assert(magic[4] == 'c'); - assert(magic[5] == 'h'); - assert(magic[6] == '>'); - assert(magic[7] == '\n'); + BX_ASSERT(magic[0] == '!'); + BX_ASSERT(magic[1] == '<'); + BX_ASSERT(magic[2] == 'a'); + BX_ASSERT(magic[3] == 'r'); + BX_ASSERT(magic[4] == 'c'); + BX_ASSERT(magic[5] == 'h'); + BX_ASSERT(magic[6] == '>'); + BX_ASSERT(magic[7] == '\n'); u32 static offsets[10000] = { 0 }; c8 static symbols[10000][256] = { 0 }; @@ -875,13 +913,13 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data i64 num_symbols = 0; for (;;) { - c8 id[17] = { 0 }; - c8 timestamp[13] = { 0 }; - c8 owner[7] = { 0 }; - c8 group[7] = { 0 }; - c8 mode[9] = { 0 }; - c8 size[11] = { 0 }; - c8 end[2] = { 0 }; + c8 id[17] = { 0 }; + c8 timestamp[13] = { 0 }; + c8 owner[7] = { 0 }; + c8 group[7] = { 0 }; + c8 mode[9] = { 0 }; + c8 size[11] = { 0 }; + c8 end[2] = { 0 }; i64 file_offset = current_offset; @@ -893,11 +931,11 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data n = io_read(f, (sizeof size) - 1, size, io_user_data); if (n == 0) break; current_offset += n; n = io_read(f, sizeof end, end, io_user_data); if (n == 0) break; current_offset += n; - assert(end[0] == '\x60'); - assert(end[1] == '\x0a'); + BX_ASSERT(end[0] == '\x60'); + BX_ASSERT(end[1] == '\x0a'); - if (strcmp(id, "/ ") == 0) { - // Symbol table + if (bx_str_eq(id, "/ ")) { + // AR symbol table // u32 count_be; @@ -911,7 +949,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data ((count_be >> 24) & 0xffu); printf("Symbol table - %lld symbols.\n\n", num_symbols); - assert(num_symbols <= (i64) (sizeof offsets / sizeof *offsets)); + BX_ASSERT(num_symbols <= (i64) (sizeof offsets / sizeof *offsets)); for (u32 j = 0; j < num_symbols; ++j) { u32 offset_be; @@ -937,7 +975,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data ++byte_count; if (c == '\0') break; - assert(symbol_size < 256); + BX_ASSERT(symbol_size < 256); if (symbol_size < 256) symbols[j][symbol_size] = c; } @@ -950,13 +988,9 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data io_seek(f, 1, IO_SEEK_CURSOR, io_user_data); current_offset += 1; } - } else if (strcmp(id, "// ") == 0) { + } else if (bx_str_eq(id, "// ")) { // String table // - // Skip file - // - - printf("String table\n\n"); i64 byte_count = atoi(size); if ((byte_count & 1) == 1) @@ -984,28 +1018,30 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data } } } else { - if (strstr(id, "/") != NULL) - *strstr(id, "/") = '\0'; - if (strstr(size, " ") != NULL) - *strstr(size, " ") = '\0'; - - b8 symbol_found = 0; - for (i64 symbol_index = 0; symbol_index < num_symbols; ++symbol_index) - if (offsets[symbol_index] == file_offset) { - printf("%08x: %-16s - %-50s- %5s bytes\n", - (u32) file_offset, - id, - symbols[symbol_index], - size); - found[symbol_index] = 1; - symbol_found = 1; - } - if (!symbol_found) - printf("%08x: %-16s - %-50s- %5s bytes\n", - (u32) file_offset, - id, - "<SYMBOLS NOT FOUND>", - size); + if (bx_find_char(id, '/') != NULL) + *bx_find_char(id, '/') = '\0'; + if (bx_find_char(size, ' ') != NULL) + *bx_find_char(size, ' ') = '\0'; + + printf("%08llx %-16s - %5s bytes\n\n", + file_offset, + id, + size); + + // Search for symbols pointing to the current file + // + { + b8 symbol_found = 0; + for (i64 symbol_index = 0; symbol_index < num_symbols; ++symbol_index) + if (offsets[symbol_index] == file_offset) { + printf(" %-50s\n", + symbols[symbol_index]); + found[symbol_index] = 1; + symbol_found = 1; + } + if (!symbol_found) + printf(" <SYMBOLS NOT FOUND>\n"); + } // Decode ELF object file // @@ -1021,16 +1057,16 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data current_offset += n; byte_count -= n; - assert(buf[0] == 0x7f); - assert(buf[1] == 'E'); - assert(buf[2] == 'L'); - assert(buf[3] == 'F'); + BX_ASSERT(buf[0] == 0x7f); + BX_ASSERT(buf[1] == 'E'); + BX_ASSERT(buf[2] == 'L'); + BX_ASSERT(buf[3] == 'F'); - assert(buf[4] == elf_class); - assert(buf[5] == elf_data); - assert(buf[6] == elf_ver); - assert(buf[7] == 0 || buf[7] == 3); // SysV or Linux - assert(buf[8] == elf_abi_ver); + BX_ASSERT(buf[4] == elf_class); + BX_ASSERT(buf[5] == elf_data); + BX_ASSERT(buf[6] == elf_ver); + BX_ASSERT(buf[7] == 0 || buf[7] == 3); // SysV or Linux + BX_ASSERT(buf[8] == elf_abi_ver); #define READ(x) do { \ n = io_read(f, sizeof (x), \ @@ -1073,16 +1109,16 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data READ(section_count); READ(strings_index); - assert(type == 1); // relocatable - assert(machine == elf_machine); - assert(ver == 1); // current version - assert(entry == 0); - assert(program_header_offset == 0); - assert(flags == 0); - assert(elf_header_size == 64); - assert(program_header_size == 0); - assert(program_header_count == 0); - assert(section_header_size == 64); + BX_ASSERT(type == 1); // relocatable + BX_ASSERT(machine == elf_machine); + BX_ASSERT(ver == 1); // current version + BX_ASSERT(entry == 0); + BX_ASSERT(program_header_offset == 0); + BX_ASSERT(flags == 0); + BX_ASSERT(elf_header_size == 64); + BX_ASSERT(program_header_size == 0); + BX_ASSERT(program_header_count == 0); + BX_ASSERT(section_header_size == 64); u64 section_offset = section_header_offset - (current_offset - begin_offset); @@ -1090,7 +1126,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data byte_count -= section_offset; current_offset += section_offset; - // Fild offset to section names string table data + // Find offset to the string table data // { i64 prev_offset = current_offset; @@ -1135,11 +1171,16 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data if (type == 2 || type == 4 || type == 9) // sym/rela/rel printf("%s", "\x1b[32m"); - else if ((flags & 2) != 0) // alloc + else if ((flags & 2) != 0) // alloc printf("%s", "\x1b[34m"); + else if (type == 3) // string table + printf("%s", "\x1b[33m"); else printf("%s", "\x1b[31m"); + // NOTE + // Only alloc (flags & 2) sections should be written to the output binary. + // Search for the name in the string table // { @@ -1166,6 +1207,8 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data current_offset = prev_offset; } + printf("%s", "\x1b[37m"); + printf( "%-10s", type >= 1 && type <= 9 ? @@ -1201,10 +1244,56 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data if (size > 0) printf(" - %lld bytes", size); - // NOTE - // Only alloc sections should be written to the output binary. + printf("\n"); + + if (type == 2) { + // Find symbol addresses + // + + BX_ASSERT(entsize == 24); + + i64 prev_offset = current_offset; + i64 prev_byte_count = byte_count; + io_seek(f, + begin_offset + offset, + IO_SEEK_BEGIN, io_user_data); + + for (byte_count = size; byte_count > 0;) { + 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(" %-4d %-5lld", sym_shndx, sym_value); + + printf("%-8s ", + (sym_info & 0xf) <= 4 ? (c8 const *[]) { + "No type", + "Object", + "Func", + "Section", + "File", + }[sym_info & 0xf] : "" + ); + + if (sym_size != 0) + printf("- %lld bytes", sym_size); + printf("\n"); + } - printf("%s\n", "\x1b[37m"); + io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); + current_offset = prev_offset; + byte_count = prev_byte_count; + } } printf("\n"); @@ -1216,19 +1305,11 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data } } - b8 all_found = 1; - for (i64 symbol_index = 0; symbol_index < num_symbols; ++symbol_index) - if (!found[symbol_index]) { + if (!found[symbol_index]) printf(" ? : %-16s - %-50s\n", "<FILE NOT FOUND>", symbols[symbol_index]); - all_found = 0; - } - - printf("\n"); - if (all_found) - printf("All files found!\n"); io_close(f, io_user_data); } @@ -1279,17 +1360,30 @@ void io_chmod_exe(i64 f, void *user_data) { #ifndef DISABLE_HELPERS #include <stdio.h> +#include <stdlib.h> +#include <string.h> #ifdef __unix__ #include <sys/types.h> #include <sys/stat.h> #endif +// Assert +// + +void bx_assert(b8 condition, c8 const *message, u32 line, c8 const *file) { + if (condition) + return; + + fprintf(stderr, "\x1b[31mASSERTION:\x1b[37m `\x1b[33m%s\x1b[37m` is false in \x1b[36m%s:%d\x1b[37m\n", message, file, line); + exit(-1); +} + // IO dispatch procedure // void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data) { - assert(id != NULL); + BX_ASSERT(id != NULL); (void) user_data; @@ -1299,60 +1393,60 @@ void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data) { switch (op) { case IO_OPEN_READ: case IO_OPEN_WRITE: - assert(size != NULL); - assert(*size > 0 && *size < MAX_NAME_SIZE); - assert(data != NULL); + BX_ASSERT(size != NULL); + BX_ASSERT(*size > 0 && *size < MAX_NAME_SIZE); + BX_ASSERT(data != NULL); - memcpy(buf, data, *size); + bx_memcpy(buf, data, *size); *f = fopen(buf, op == IO_OPEN_READ ? "rb" : "wb"); - assert(*f != NULL); + BX_ASSERT(*f != NULL); break; case IO_CLOSE: - assert(*f != NULL); - assert(size == NULL); - assert(data == NULL); + BX_ASSERT(*f != NULL); + BX_ASSERT(size == NULL); + BX_ASSERT(data == NULL); fclose(*f); break; case IO_SEEK: { - assert(*f != NULL); - assert(size != NULL); - assert(data != NULL); + BX_ASSERT(*f != NULL); + BX_ASSERT(size != NULL); + BX_ASSERT(data != NULL); u16 *origin = (u16 *) data; if (!(*origin == IO_SEEK_CURSOR && *size == 0)) { - assert(*origin == IO_SEEK_CURSOR || *origin == IO_SEEK_BEGIN || *origin == IO_SEEK_END); + BX_ASSERT(*origin == IO_SEEK_CURSOR || *origin == IO_SEEK_BEGIN || *origin == IO_SEEK_END); i32 s = fseek(*f, *size, *origin == IO_SEEK_CURSOR ? SEEK_CUR : *origin == IO_SEEK_BEGIN ? SEEK_SET : SEEK_END); - assert(s == 0); + BX_ASSERT(s == 0); } } break; case IO_READ: - assert(*f != NULL); - assert(size != NULL); - assert(data != NULL); - assert(*size > 0); + BX_ASSERT(*f != NULL); + BX_ASSERT(size != NULL); + BX_ASSERT(data != NULL); + BX_ASSERT(*size > 0); *size = fread(data, 1, *size, *f); break; case IO_WRITE: - assert(*f != NULL); - assert(size != NULL); - assert(data != NULL); - assert(*size > 0); + BX_ASSERT(*f != NULL); + BX_ASSERT(size != NULL); + BX_ASSERT(data != NULL); + BX_ASSERT(*size > 0); *size = fwrite(data, 1, *size, *f); break; case IO_CHMOD_EXE: - assert(*f != NULL); - assert(size == NULL); + BX_ASSERT(*f != NULL); + BX_ASSERT(size == NULL); #ifdef __unix__ fchmod(fileno(*f), 0775); @@ -1360,7 +1454,7 @@ void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data) { break; default: - assert(0); + BX_ASSERT(0); } } |