summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-07-13 14:11:18 +0200
committerMitya Selivanov <automainint@guattari.tech>2024-07-13 14:11:18 +0200
commitd2a6383201d9cb85f42b3df333e2e32f5593be74 (patch)
treecd00401ecbac95955f74e0e8819f4fbb93b6fa18
parentda1b4ac8ed13a8a013989f5f7ff56639cf594d46 (diff)
downloadbxgen-d2a6383201d9cb85f42b3df333e2e32f5593be74.zip
Decoding AR ELF in memory
-rwxr-xr-xbxgen.c558
1 files changed, 477 insertions, 81 deletions
diff --git a/bxgen.c b/bxgen.c
index 9d6781c..3efa7e3 100755
--- a/bxgen.c
+++ b/bxgen.c
@@ -90,8 +90,6 @@ typedef unsigned long long u64;
typedef float f32;
typedef double f64;
typedef signed char b8; // 8-bit boolean
-typedef int b32; // 32-bit boolean
-typedef int s32; // 32-bit status code
typedef char c8; // 8-bit character
// ================================================================
@@ -119,7 +117,14 @@ enum {
ARCH_RISC_V = 64,
ARCH_I386,
ARCH_X86_64,
- ARCH_ARM,
+ ARCH_ARM32,
+ ARCH_ARM64,
+
+ // Endianness
+ //
+
+ LE = 1,
+ BE = 2,
// Sea of Nodes flow type
//
@@ -154,6 +159,11 @@ enum {
UNIT_LIBRARY_STATIC,
UNIT_LIBRARY_DYNAMIC,
+ // String tables
+ //
+
+ STRING_TABLE_ALIGNMENT = 16, // TODO
+
// Entity types
//
@@ -179,6 +189,7 @@ enum {
IO_OPEN_WRITE,
IO_CLOSE,
IO_SEEK,
+ IO_TELL,
IO_READ,
IO_WRITE,
IO_CHMOD_EXE,
@@ -188,6 +199,20 @@ enum {
IO_SEEK_END,
};
+// TODO
+typedef struct {
+ i64 size;
+ i64 index;
+} String_Handle;
+
+// TODO
+typedef struct {
+ i64 size;
+ i64 capacity;
+ u8 *data;
+ u8 *occupied;
+} Strint_Table;
+
typedef struct {
i16 size;
i16 type;
@@ -255,9 +280,9 @@ typedef struct {
} Unit;
// An entity can be any of:
-// - `Node`
-// - `Proc`
-// - `Unit`
+// - Node
+// - Proc
+// - Unit
//
// Every entity can be referenced by it's unique index
// in the entity pool.
@@ -324,6 +349,7 @@ 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);
b8 io_seek(i64 f, i64 offset, u16 origin, void *user_data);
+i64 io_tell(i64 f, 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);
@@ -373,7 +399,12 @@ void l_static(i64 unit, c8 *static_library);
#define BX_ASSERT(condition) \
bx_assert((condition), #condition, __LINE__, __FILE__)
-static void bx_memcpy(void *dst, void const *src, i64 size) {
+static i64 bx_align(i64 x, i64 a) {
+ BX_ASSERT(a > 0);
+ return x + ((a - (x % a)) % a);
+}
+
+static void bx_mem_cpy(void *dst, void const *src, i64 size) {
BX_ASSERT(dst != NULL);
BX_ASSERT(src != NULL);
BX_ASSERT(size > 0);
@@ -382,22 +413,41 @@ static void bx_memcpy(void *dst, void const *src, i64 size) {
((u8 *)dst)[i] = ((u8 const *)src)[i];
}
-static b8 bx_str_eq(c8 const *a, c8 const *b) {
+static b8 bx_mem_eq(void const *a, void const *b, i64 size) {
BX_ASSERT(a != NULL);
BX_ASSERT(b != NULL);
+ BX_ASSERT(size > 0);
+
+ u8 const *x = (u8 const *) a;
+ u8 const *y = (u8 const *) b;
+
+ for (i64 i = 0; i < size; ++i)
+ if (x[i] != y[i])
+ return 0;
+
+ return 1;
+}
+
+static b8 bx_str_eq(
+ c8 const *a, c8 const *a_end,
+ c8 const *b, c8 const *b_end
+) {
+ BX_ASSERT(a != NULL && a_end != NULL);
+ BX_ASSERT(b != NULL && b_end != NULL);
- while (*a == *b && *a != '\0' && *b != '\0') {
+ while (*a == *b && a != a_end && b != b_end) {
++a;
++b;
}
- return *a == '\0' && *b == '\0';
+ return a == a_end && b == b_end;
}
-static c8 *bx_find_char(c8 *s, c8 c) {
+static c8 *bx_find_char(c8 *s, c8 *s_end, c8 c) {
BX_ASSERT(s != NULL);
+ BX_ASSERT(s_end != NULL);
- while (*s != '\0' && *s != c)
+ while (s != s_end && *s != c)
++s;
return *s == c ? s : NULL;
@@ -455,7 +505,7 @@ i64 node_ctrl_call(Pool *pool, i16 convention, i64 target_proc, i64 arg_count, V
};
if (arg_count > 0)
- bx_memcpy(call.args, args, arg_count * sizeof *args);
+ bx_mem_cpy(call.args, args, arg_count * sizeof *args);
return node_init(pool, (Node) {
.op = CTRL_CALL,
@@ -473,9 +523,9 @@ i64 node_ctrl_call_by_name(Pool *pool, i16 convention, i64 name_size, c8 *name,
};
if (name_size > 0)
- bx_memcpy(call.target_name, name, name_size);
+ bx_mem_cpy(call.target_name, name, name_size);
if (arg_count > 0)
- bx_memcpy(call.args, args, arg_count * sizeof *args);
+ bx_mem_cpy(call.args, args, arg_count * sizeof *args);
return node_init(pool, (Node) {
.op = CTRL_CALL,
@@ -489,7 +539,7 @@ i64 node_ctrl_ret(Pool *pool, i64 value_count, Var *values) {
Ret ret = { .val_count = value_count, };
if (value_count > 0)
- bx_memcpy(ret.vals, values, value_count * sizeof *values);
+ bx_mem_cpy(ret.vals, values, value_count * sizeof *values);
return node_init(pool, (Node) {
.op = CTRL_RET,
@@ -531,7 +581,7 @@ void proc_set_name(Pool *pool, i64 proc, i64 name_size, c8 *name) {
p->name_size = name_size;
if (name_size > 0)
- bx_memcpy(p->name, name, name_size);
+ bx_mem_cpy(p->name, name, name_size);
}
void proc_node_add(Pool *pool, i64 proc, i64 node) {
@@ -685,7 +735,7 @@ void unit_set_name(Pool *pool, i64 unit, i64 name_size, c8 *name) {
u->name_size = name_size;
if (name_size > 0)
- bx_memcpy(u->name, name, name_size);
+ bx_mem_cpy(u->name, name, name_size);
}
void unit_set_entry_point(Pool *pool, i64 unit, i64 entry_point_proc) {
@@ -711,6 +761,175 @@ void unit_set_entry_point(Pool *pool, i64 unit, i64 entry_point_proc) {
pool->entities[unit].unit.entry_point_index = p->index_in_unit;
}
+// Serialization
+//
+
+u16 read_u16(i32 endianness, void const *v) {
+ u8 const *u = (u8 const *) v;
+
+ if (endianness == LE)
+ return ((u16) u[0]) |
+ (((u16) u[1]) << 8);
+
+ if (endianness == BE)
+ return ((u16) u[1]) |
+ (((u16) u[0]) << 8);
+
+ BX_ASSERT(0);
+ return 0;
+}
+
+u32 read_u32(i32 endianness, void const *v) {
+ u8 const *u = (u8 const *) v;
+
+ if (endianness == LE)
+ return ((u32) u[0]) |
+ (((u32) u[1]) << 8) |
+ (((u32) u[2]) << 16) |
+ (((u32) u[3]) << 24);
+
+ if (endianness == BE)
+ return ((u32) u[3]) |
+ (((u32) u[2]) << 8) |
+ (((u32) u[1]) << 16) |
+ (((u32) u[0]) << 24);
+
+
+ BX_ASSERT(0);
+ return 0;
+}
+
+u64 read_u64(i32 endianness, void const *v) {
+ u8 const *u = (u8 const *) v;
+
+ if (endianness == LE)
+ return ((u64) u[0]) |
+ (((u64) u[1]) << 8) |
+ (((u64) u[2]) << 16) |
+ (((u64) u[3]) << 24) |
+ (((u64) u[4]) << 32) |
+ (((u64) u[5]) << 40) |
+ (((u64) u[6]) << 48) |
+ (((u64) u[7]) << 56);
+
+ if (endianness == BE)
+ return ((u64) u[7]) |
+ (((u64) u[6]) << 8) |
+ (((u64) u[5]) << 16) |
+ (((u64) u[4]) << 24) |
+ (((u64) u[3]) << 32) |
+ (((u64) u[2]) << 40) |
+ (((u64) u[1]) << 48) |
+ (((u64) u[0]) << 56);
+
+ BX_ASSERT(0);
+ return 0;
+}
+
+void write_u16(i32 endianness, u16 x, void *v) {
+ u8 *u = (u8 *) v;
+
+ if (endianness == LE) {
+ u[0] = (u8) ( x & 0xff);
+ u[1] = (u8) ((x >> 8) & 0xff);
+ }
+
+ if (endianness == BE) {
+ u[1] = (u8) ( x & 0xff);
+ u[0] = (u8) ((x >> 8) & 0xff);
+ }
+
+ BX_ASSERT(0);
+}
+
+void write_u32(i32 endianness, u32 x, void *v) {
+ u8 *u = (u8 *) v;
+
+ if (endianness == LE) {
+ u[0] = (u8) ( x & 0xff);
+ u[1] = (u8) ((x >> 8) & 0xff);
+ u[2] = (u8) ((x >> 16) & 0xff);
+ u[3] = (u8) ((x >> 24) & 0xff);
+ }
+
+ if (endianness == BE) {
+ u[3] = (u8) ( x & 0xff);
+ u[2] = (u8) ((x >> 8) & 0xff);
+ u[1] = (u8) ((x >> 16) & 0xff);
+ u[0] = (u8) ((x >> 24) & 0xff);
+ }
+
+ BX_ASSERT(0);
+}
+
+void write_u64(i32 endianness, u64 x, void *v) {
+ u8 *u = (u8 *) v;
+
+ if (endianness == LE) {
+ u[0] = (u8) ( x & 0xff);
+ u[1] = (u8) ((x >> 8) & 0xff);
+ u[2] = (u8) ((x >> 16) & 0xff);
+ u[3] = (u8) ((x >> 24) & 0xff);
+ u[4] = (u8) ((x >> 32) & 0xff);
+ u[5] = (u8) ((x >> 40) & 0xff);
+ u[6] = (u8) ((x >> 48) & 0xff);
+ u[7] = (u8) ((x >> 56) & 0xff);
+ }
+
+ if (endianness == BE) {
+ u[7] = (u8) ( x & 0xff);
+ u[6] = (u8) ((x >> 8) & 0xff);
+ u[5] = (u8) ((x >> 16) & 0xff);
+ u[4] = (u8) ((x >> 24) & 0xff);
+ u[3] = (u8) ((x >> 32) & 0xff);
+ u[2] = (u8) ((x >> 40) & 0xff);
+ u[1] = (u8) ((x >> 48) & 0xff);
+ u[0] = (u8) ((x >> 56) & 0xff);
+ }
+
+ BX_ASSERT(0);
+}
+
+i16 read_i16(i32 endianness, void *v) {
+ return (i16) read_u16(endianness, v);
+}
+
+i32 read_i32(i32 endianness, void *v) {
+ return (i32) read_u32(endianness, v);
+}
+
+i64 read_i64(i32 endianness, void *v) {
+ return (i64) read_u64(endianness, v);
+}
+
+f32 read_f32(i32 endianness, void *v) {
+ return *(f32 *) &(u32) { read_u32(endianness, v) };
+}
+
+f32 read_f64(i32 endianness, void *v) {
+ return *(f64 *) &(u64) { read_u64(endianness, v) };
+}
+
+void write_i16(i32 endianness, i16 x, void *v) {
+ write_u16(endianness, (u16) x, v);
+}
+
+void write_i32(i32 endianness, i32 x, void *v) {
+ write_u32(endianness, (u32) x, v);
+}
+
+void write_i64(i32 endianness, i64 x, void *v) {
+ write_u64(endianness, (u64) x, v);
+}
+
+void write_f32(i32 endianness, f32 x, void *v) {
+ write_u32(endianness, *(u32 *) &x, v);
+}
+
+void write_f64(i32 endianness, f64 x, void *v) {
+ write_u64(endianness, *(u64 *) &x, v);
+}
+
// Code generation proc
//
@@ -794,15 +1013,35 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
BX_ASSERT(pool->entities[unit].unit.entry_point_index != UNDEFINED);
BX_ASSERT(target == (FORMAT_ELF | ARCH_X86_64));
- // ELF config
- //
+ // ================================================================
+
+ c8 ELF_MAGIC[4] = "\x7f" "ELF";
+
+ u8 ELF_64 = 2;
+ u8 ELF_2_LE = 1;
+ u8 ELF_VERSION = 1;
+ u8 ELF_SYS_V = 0;
+ u8 ELF_LINUX = 3;
+ u8 ELF_ABI_VERSION = 0;
+ u16 ELF_RELOCATABLE = 1;
+ u16 ELF_EXECUTABLE = 2;
+ u16 ELF_X86_64 = 62;
+
+ u16 ELF_HEADER_SIZE = 64;
+ u16 ELF_PROGRAM_HEADER_SIZE = 56;
+ u16 ELF_SECTION_HEADER_SIZE = 64;
+
+ u64 X86_64_BASE_ADDRESS = 0x400000;
+ u64 X86_64_ALIGNMENT = 8;
+
+ c8 AR_MAGIC[8] = "!<arch>\n";
- u8 elf_class = 2; // elf64
- u8 elf_data = 1; // 2's complement, little endian
- u8 elf_ver = 1; // current version
- u8 elf_abi = 0; // SysV
- u8 elf_abi_ver = 0; // ABI version
- u16 elf_machine = 62; // x86_64
+ c8 AR_SYMBOL_TABLE[] = "/ ";
+ c8 AR_STRING_TABLE[] = "// ";
+
+ c8 STRTAB[] = ".strtab";
+
+ // ================================================================
#define WRITE(x, n) io_write( io_out, n, x, io_user_data )
#define WRITE_V(...) io_write( io_out, sizeof((u8[]) {__VA_ARGS__}), (u8[]) {__VA_ARGS__}, io_user_data )
@@ -811,11 +1050,6 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
#define WRITE_4(x) io_write( io_out, 4, &(u32) { x }, io_user_data )
#define WRITE_8(x) io_write( io_out, 8, &(u64) { x }, io_user_data )
- u16 ehs = 64;
- u16 shs = 0;
- u16 phs = 56;
- u64 align = 8;
-
u8 code[16] = {
0xb8, // mov rax
0x3c, 0, 0, 0, // 60 // exit
@@ -823,60 +1057,60 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
0x0f, 0x05, // syscall
};
- u64 code_offset = ehs + phs;
- u64 code_size = sizeof code;
+ u64 code_offset = bx_align(ELF_HEADER_SIZE + ELF_PROGRAM_HEADER_SIZE, X86_64_ALIGNMENT);
+ u64 code_size = bx_align(sizeof code, X86_64_ALIGNMENT);
u64 entry_offset = 0;
- u64 base_address = 0x400000; // x86_64 base address
+ u64 base_address = X86_64_BASE_ADDRESS;
u64 code_address = base_address + code_offset;
u64 entry = code_address + entry_offset;
- BX_ASSERT((code_offset % align) == 0);
- BX_ASSERT((code_size % align) == 0);
+ BX_ASSERT((code_offset % X86_64_ALIGNMENT) == 0);
+ BX_ASSERT((code_size % X86_64_ALIGNMENT) == 0);
// ELF header
//
- WRITE_V( 0x7f, 'E', 'L', 'F' ); // magic
+ WRITE ( ELF_MAGIC, 4 );
- WRITE_V( elf_class );
- WRITE_V( elf_data );
- WRITE_V( elf_ver );
- WRITE_V( elf_abi );
- WRITE_V( elf_abi_ver );
+ WRITE_V( ELF_64 );
+ WRITE_V( ELF_2_LE );
+ WRITE_V( ELF_VERSION );
+ WRITE_V( ELF_SYS_V );
+ WRITE_V( ELF_ABI_VERSION );
WRITE_DUP(0, 7); // padding
- WRITE_2( 2 ); // executable
- WRITE_2( elf_machine );
- WRITE_4( 1 ); // current version
- WRITE_8( entry ); // entry point address
- WRITE_8( ehs ); // program header offset
- WRITE_8( 0 ); // section header offset
- WRITE_4( 0 ); // flags
- WRITE_2( ehs ); // ELF header size
- WRITE_2( phs ); // program header size
- WRITE_2( 1 ); // program header count
- WRITE_2( shs ); // section header size
- WRITE_2( 0 ); // section header count
- WRITE_2( 0 ); // string table section header index
+ WRITE_2( ELF_EXECUTABLE );
+ WRITE_2( ELF_X86_64 );
+ WRITE_4( ELF_VERSION );
+ WRITE_8( entry );
+ WRITE_8( ELF_HEADER_SIZE );
+ WRITE_8( 0 ); // section header offset
+ WRITE_4( 0 ); // flags
+ WRITE_2( ELF_HEADER_SIZE );
+ WRITE_2( ELF_PROGRAM_HEADER_SIZE );
+ WRITE_2( 1 ); // program header count
+ WRITE_2( 0 ); // section header size
+ WRITE_2( 0 ); // section header count
+ WRITE_2( 0 ); // string table section header index
// Program header
//
- WRITE_4( 1 ); // type (PT_LOAD)
- WRITE_4( 5 ); // flags (PF_X | PF_R)
- WRITE_8( code_offset ); // offset
- 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
+ WRITE_4( 1 ); // type (PT_LOAD)
+ WRITE_4( 5 ); // flags (PF_X | PF_R)
+ WRITE_8( code_offset );
+ 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( X86_64_ALIGNMENT );
// Code
//
- for (i64 i = code_offset - ehs - phs; i > 0; --i)
+ for (i64 i = code_offset - ELF_HEADER_SIZE - ELF_PROGRAM_HEADER_SIZE; i > 0; --i)
WRITE_V( 0 );
WRITE( code, code_size );
@@ -888,6 +1122,150 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
#undef WRITE
+ // ================================================================
+
+ // Intermediate buffer
+ //
+
+ static u8 in_buffer[1024 * 1024 * 300]; // 300 MB
+ static i64 ar_offsets[128];
+ i64 ar_count = 0;
+
+ // Read all dependency files into the memory
+ //
+ {
+ Unit *u = &pool->entities[unit].unit;
+
+ for (i64 link_index = 0; link_index < u->link_count; ++link_index) {
+ i64 id = u->links[link_index];
+ if (id == UNDEFINED)
+ continue;
+ BX_ASSERT(ar_count + 1 < (i64) (sizeof ar_offsets / sizeof *ar_offsets));
+
+ Unit *l = &pool->entities[id].unit;
+ BX_ASSERT(pool->entities[id].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);
+ io_seek(f, 0, IO_SEEK_END, io_user_data);
+ i64 size = io_tell(f, io_user_data);
+ io_seek(f, 0, IO_SEEK_BEGIN, io_user_data);
+ if (ar_count == 0)
+ ar_offsets[ar_count] = 0;
+ ar_offsets[ar_count + 1] = ar_offsets[ar_count] + bx_align(size, 8);
+ i64 n = io_read(f, size, in_buffer + ar_offsets[ar_count], io_user_data);
+ BX_ASSERT(n == size);
+ ++ar_count;
+ io_close(f, io_user_data);
+ }
+ }
+
+ for (i64 ar_index = 0; ar_index < ar_count; ++ar_index) {
+ // ================================================================
+ //
+ // Read AR library
+
+ u8 *ar_begin = in_buffer + ar_offsets[ar_index];
+ u8 *ar_end = in_buffer + ar_offsets[ar_index + 1];
+
+ u8 *ar_symbol_table = NULL;
+ u8 *ar_string_table = NULL;
+
+ BX_ASSERT(bx_mem_eq(ar_begin, AR_MAGIC, 8));
+
+ u8 *f_begin = ar_begin + 8;
+
+ while (f_begin + 60 < ar_end) {
+ u8 *f_id = f_begin;
+ u8 *f_size = f_begin + 48;
+ u8 *f_end = f_begin + 58;
+ u8 *f_data = f_begin + 60;
+
+ i64 fn_size;
+ {
+ c8 buf[7] = {0};
+ bx_mem_cpy(buf, f_size, 6);
+ fn_size = atoi(buf);
+ }
+
+ fn_size = bx_align(fn_size, 2);
+
+ BX_ASSERT(bx_mem_eq(f_end, "\x60\x0a", 2));
+ BX_ASSERT(f_begin + fn_size <= ar_end);
+
+ if (bx_mem_eq(f_id, AR_SYMBOL_TABLE, 16)) {
+ // AR symbol table
+ //
+
+ ar_symbol_table = f_data;
+
+ f_begin = f_data + fn_size;
+ } else if (bx_mem_eq(f_id, AR_STRING_TABLE, 16)) {
+ // String table
+ //
+
+ ar_string_table = f_data;
+
+ f_begin = f_data + fn_size;
+ } else {
+ // ================================================================
+ //
+ // Decode ELF object file
+
+ u8 *elf_begin = f_data;
+ f_begin += fn_size;
+
+ u64 section_header_offset;
+ u16 section_count;
+ u16 string_table_index;
+ u16 string_table_offset;
+
+ BX_ASSERT(bx_mem_eq(elf_begin, ELF_MAGIC, 4));
+ BX_ASSERT(elf_begin[4] == ELF_64);
+ BX_ASSERT(elf_begin[5] == ELF_2_LE);
+ BX_ASSERT(elf_begin[6] == ELF_VERSION);
+ BX_ASSERT(elf_begin[7] == ELF_SYS_V || elf_begin[7] == ELF_LINUX);
+ BX_ASSERT(elf_begin[8] == ELF_ABI_VERSION);
+
+ BX_ASSERT(read_u16(LE, elf_begin + 16) == ELF_RELOCATABLE);
+ BX_ASSERT(read_u16(LE, elf_begin + 18) == ELF_X86_64);
+ BX_ASSERT(read_u32(LE, elf_begin + 20) == ELF_VERSION);
+ BX_ASSERT(read_u64(LE, elf_begin + 24) == 0); // entry
+ BX_ASSERT(read_u64(LE, elf_begin + 32) == 0); // program header offset
+
+ section_header_offset = read_u64(LE, elf_begin + 40);
+
+ BX_ASSERT(read_u32(LE, elf_begin + 48) == 0); // flags
+ BX_ASSERT(read_u16(LE, elf_begin + 52) == ELF_HEADER_SIZE);
+ BX_ASSERT(read_u16(LE, elf_begin + 54) == 0); // program header size
+ BX_ASSERT(read_u16(LE, elf_begin + 56) == 0); // program header count
+ BX_ASSERT(read_u16(LE, elf_begin + 58) == ELF_SECTION_HEADER_SIZE);
+
+ section_count = read_u16(LE, elf_begin + 60);
+ string_table_index = read_u16(LE, elf_begin + 62);
+
+ string_table_offset = read_u64(LE, elf_begin + section_header_offset + string_table_index * ELF_SECTION_HEADER_SIZE + 24);
+
+ (void) ar_symbol_table;
+ (void) ar_string_table;
+
+ (void) section_header_offset;
+ (void) section_count;
+ (void) string_table_index;
+ (void) string_table_offset;
+
+ f_begin = f_data + fn_size;
+
+ // ================================================================
+ }
+ }
+ }
+
+ return;
+
+ // ================================================================
+
// Read dependencies
//
{
@@ -907,7 +1285,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
i64 f = io_open_read(l->name_size, l->name, io_user_data);
c8 buf0_[MAX_NAME_SIZE + 1] = { 0 };
- bx_memcpy(buf0_, l->name, l->name_size);
+ bx_mem_cpy(buf0_, l->name, l->name_size);
printf("\nReading `%s` library...\n\n", buf0_);
i64 n = 0, current_offset = 0;
@@ -957,7 +1335,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
BX_ASSERT(end[0] == '\x60');
BX_ASSERT(end[1] == '\x0a');
- if (bx_str_eq(id, "/ ")) {
+ if (bx_str_eq(id, id + 16, AR_SYMBOL_TABLE, AR_SYMBOL_TABLE + 16)) {
// AR symbol table
//
@@ -1011,7 +1389,7 @@ 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 (bx_str_eq(id, "// ")) {
+ } else if (bx_str_eq(id, id + 16, AR_STRING_TABLE, AR_STRING_TABLE + 16)) {
// String table
//
@@ -1041,10 +1419,10 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
}
}
} else {
- if (bx_find_char(id, '/') != NULL)
- *bx_find_char(id, '/') = '\0';
- if (bx_find_char(size, ' ') != NULL)
- *bx_find_char(size, ' ') = '\0';
+ if (bx_find_char(id, id + 16, '/') != NULL)
+ *bx_find_char(id, id + 16, '/') = '\0';
+ if (bx_find_char(size, size + 6, ' ') != NULL)
+ *bx_find_char(size, size + 6, ' ') = '\0';
printf("%08llx %-16s - %5s bytes\n\n",
file_offset,
@@ -1086,11 +1464,11 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
BX_ASSERT(buf[2] == 'L');
BX_ASSERT(buf[3] == 'F');
- 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);
+ BX_ASSERT(buf[4] == ELF_64);
+ BX_ASSERT(buf[5] == ELF_2_LE);
+ BX_ASSERT(buf[6] == ELF_VERSION);
+ BX_ASSERT(buf[7] == ELF_SYS_V || buf[7] == ELF_LINUX); // SysV or Linux
+ BX_ASSERT(buf[8] == ELF_ABI_VERSION);
#define READ(x) do { \
n = io_read(f, sizeof (x), \
@@ -1137,9 +1515,10 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
READ(section_count);
READ(strings_index);
- BX_ASSERT(type == 1); // relocatable
- BX_ASSERT(machine == elf_machine);
- BX_ASSERT(ver == 1); // current version
+ BX_ASSERT(type == ELF_RELOCATABLE);
+ BX_ASSERT(machine == ELF_X86_64);
+ BX_ASSERT(ver == ELF_VERSION);
+
BX_ASSERT(entry == 0);
BX_ASSERT(program_header_offset == 0);
BX_ASSERT(flags == 0);
@@ -1197,7 +1576,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
c8 buf[8];
n = io_read(f, sizeof buf, buf, io_user_data); if (n == 0) break;
- if (!bx_str_eq(buf, ".strtab"))
+ if (!bx_str_eq(buf, buf + 7, STRTAB, STRTAB + 7))
continue;
symbol_names_offset = offset;
@@ -1614,6 +1993,12 @@ b8 io_seek(i64 f, i64 offset, u16 origin, void *user_data) {
return 1;
}
+i64 io_tell(i64 f, void *user_data) {
+ i64 offset;
+ io_dispatch(IO_TELL, &f, &offset, NULL, user_data);
+ return offset;
+}
+
i64 io_read(i64 f, i64 size, void *data, void *user_data) {
io_dispatch(IO_READ, &f, &size, data, user_data);
return size;
@@ -1675,7 +2060,7 @@ void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data) {
BX_ASSERT(*size > 0 && *size < MAX_NAME_SIZE);
BX_ASSERT(data != NULL);
- bx_memcpy(buf, data, *size);
+ bx_mem_cpy(buf, data, *size);
*f = fopen(buf, op == IO_OPEN_READ ? "rb" : "wb");
BX_ASSERT(*f != NULL);
break;
@@ -1704,6 +2089,17 @@ void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data) {
}
} break;
+ case IO_TELL: {
+ BX_ASSERT(*f != NULL);
+ BX_ASSERT(size != NULL);
+ BX_ASSERT(data == NULL);
+
+ i64 n = (i64) ftell(*f);
+ BX_ASSERT(n >= 0);
+
+ *size = n;
+ } break;
+
case IO_READ:
BX_ASSERT(*f != NULL);
BX_ASSERT(size != NULL);