From b25e2ea8093067faa6e9bbc094e4a6a042c97cd1 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Tue, 9 Jul 2024 04:31:50 +0200 Subject: Decoding string tables --- bxgen.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 168 insertions(+), 27 deletions(-) diff --git a/bxgen.c b/bxgen.c index 46eaeb1..a5ddbe9 100755 --- a/bxgen.c +++ b/bxgen.c @@ -729,6 +729,16 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data assert(pool->entities[unit].unit.entry_point_index != UNDEFINED); assert(target == (FORMAT_ELF | ARCH_X86_64)); + // ELF config + // + + 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 + // Read dependencies // { @@ -848,8 +858,8 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data if ((byte_count & 1) == 1) { // align - n = io_seek(f, 1, IO_SEEK_CURSOR, io_user_data); if (n == 0) break; - current_offset += n; + io_seek(f, 1, IO_SEEK_CURSOR, io_user_data); + current_offset += 1; } } else if (strcmp(id, "// ") == 0) { // String table @@ -908,15 +918,143 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data "", size); - // Skip file + // Decode ELF object file // i64 byte_count = atoi(size); if ((byte_count & 1) == 1) ++byte_count; // align - n = io_seek(f, byte_count, IO_SEEK_CURSOR, io_user_data); if (n == 0) break; + i64 begin_offset = current_offset; + + u8 buf[16]; + n = io_read(f, sizeof buf, buf, io_user_data); if (n == 0) break; current_offset += n; + byte_count -= n; + + assert(buf[0] == 0x7f); + assert(buf[1] == 'E'); + assert(buf[2] == 'L'); + 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); + + #define READ(x) do { \ + n = io_read(f, sizeof (x), \ + &(x), \ + io_user_data); \ + current_offset += n; \ + byte_count -= n; \ + } while (0) + + u16 type; + u16 machine; + u32 ver; + u64 entry; + u64 program_header_offset; + u64 section_header_offset; + u32 flags; + u16 elf_header_size; + u16 program_header_size; + u16 program_header_count; + u16 section_header_size; + u16 section_header_count; + u16 strings_index; + + READ(type); + READ(machine); + READ(ver); + READ(entry); + READ(program_header_offset); + READ(section_header_offset); + READ(flags); + READ(elf_header_size); + READ(program_header_size); + READ(program_header_count); + READ(section_header_size); + READ(section_header_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); + + // TODO read string table + + i64 section_offset = section_header_offset - (current_offset - begin_offset); + + printf(" ^ Section header offset: %lld (+%lld)\n", section_header_offset, section_offset); + printf(" ^ Section headers: %d\n", section_header_count); + printf(" ^ Strings index: %d\n", strings_index); + + io_seek(f, section_offset, IO_SEEK_CURSOR, io_user_data); + byte_count -= section_offset; + current_offset += section_offset; + + for (u16 i = 0; i < section_header_count; ++i) { + u32 name; + u32 type; + u64 flags; + u64 addr; + u64 offset; + u64 size; + u32 link; + u32 info; + u64 addralign; + u64 entsize; + + READ(name); + READ(type); + READ(flags); + READ(addr); + READ(offset); + READ(size); + READ(link); + READ(info); + READ(addralign); + READ(entsize); + + if (type == 3) { + printf("\n String table - %lld bytes\n ", size); + + i64 prev_offset = current_offset; + io_seek(f, begin_offset + offset, IO_SEEK_BEGIN, io_user_data); + + static c8 buf[10000] = { 0 }; + assert(size < sizeof buf); + n = io_read(f, size, buf, io_user_data); if (n == 0) break; + + for (u64 j = 0; j < size; ++j) { + if (buf[j] != '\0') + printf("%c", buf[j]); + else if (j > 0 && buf[j - 1] == '\0') + printf("\n "); + else + printf("\n "); + } + + printf("\n"); + + io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); + current_offset = prev_offset; + } + } + + io_seek(f, byte_count, IO_SEEK_CURSOR, io_user_data); + current_offset += byte_count; + + #undef READ } } @@ -973,27 +1111,27 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data WRITE_V( 0x7f, 'E', 'L', 'F' ); // magic - WRITE_V( 2 ); // elf64 - WRITE_V( 1 ); // 2's complement, little endian - WRITE_V( 1 ); // current version - WRITE_V( 0 ); // ABI = SysV - WRITE_V( 0 ); // ABI version + WRITE_V( elf_class ); + WRITE_V( elf_data ); + WRITE_V( elf_ver ); + WRITE_V( elf_abi ); + WRITE_V( elf_abi_ver ); WRITE_DUP(0, 7); // padding - WRITE_2( 2 ); // executable - WRITE_2( 62 ); // x86_64 - 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( 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 // Program header // @@ -1110,11 +1248,14 @@ void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data) { assert(data != NULL); u16 *origin = (u16 *) data; - 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); + + if (!(*origin == IO_SEEK_CURSOR && *size == 0)) { + 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); + } } break; case IO_READ: -- cgit v1.2.3