summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-07-10 03:04:24 +0200
committerMitya Selivanov <automainint@guattari.tech>2024-07-10 03:04:24 +0200
commit94725fda14c32b4c76b2f482049f71928063eec0 (patch)
tree31b2ce64d370b853cf515c55cff10ce14f3eca00
parentf6ef3f50bdbfd33741c56cfd0d6e05555d4d0582 (diff)
downloadbxgen-94725fda14c32b4c76b2f482049f71928063eec0.zip
Remove some dependencies; Decoding symbols
-rwxr-xr-xbxgen.c492
1 files changed, 293 insertions, 199 deletions
diff --git a/bxgen.c b/bxgen.c
index 4eeff93..3decce1 100755
--- a/bxgen.c
+++ b/bxgen.c
@@ -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);
}
}