summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-07-09 04:31:50 +0200
committerMitya Selivanov <automainint@guattari.tech>2024-07-09 04:31:50 +0200
commitb25e2ea8093067faa6e9bbc094e4a6a042c97cd1 (patch)
tree15af26b4cd31046297a420e261fce8f190bf4579
parent023f8a42e1e53cd69100e861b12f6dd6e16dfbf9 (diff)
downloadbxgen-b25e2ea8093067faa6e9bbc094e4a6a042c97cd1.zip
Decoding string tables
-rwxr-xr-xbxgen.c195
1 files 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
"<SYMBOLS NOT FOUND>",
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("<EMPTY>\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: