From d2a6383201d9cb85f42b3df333e2e32f5593be74 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Sat, 13 Jul 2024 14:11:18 +0200 Subject: Decoding AR ELF in memory --- bxgen.c | 558 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file 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] = "!\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); -- cgit v1.2.3