diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2024-07-13 22:14:29 +0200 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2024-07-13 22:14:29 +0200 |
commit | 9984d86a47d53d331b5bcb674393a2632e9f116e (patch) | |
tree | 5dcab9bc78dec5c58598830352f2239a83ec4bd6 /bxgen.c | |
parent | 90dfcfd6913b24700b956e9b21661f58b0913e88 (diff) | |
download | bxgen-9984d86a47d53d331b5bcb674393a2632e9f116e.zip |
Add ELF decoding procs
Diffstat (limited to 'bxgen.c')
-rwxr-xr-x | bxgen.c | 700 |
1 files changed, 435 insertions, 265 deletions
@@ -397,7 +397,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 bx_assert(b8 condition, c8 *message, u32 line, c8 *file); void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data); #ifndef DISABLE_HELPERS @@ -448,22 +448,22 @@ i64 bx_align(i64 x, i64 a) { return x + ((a - (x % a)) % a); } -void bx_mem_cpy(void *dst, void const *src, i64 size) { +void bx_mem_cpy(void *dst, void *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]; + ((u8 *)dst)[i] = ((u8 *)src)[i]; } -b8 bx_mem_eq(void const *a, void const *b, i64 size) { +b8 bx_mem_eq(void *a, void *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; + u8 *x = (u8 *) a; + u8 *y = (u8 *) b; for (i64 i = 0; i < size; ++i) if (x[i] != y[i]) @@ -472,9 +472,17 @@ b8 bx_mem_eq(void const *a, void const *b, i64 size) { return 1; } +i64 bx_str_len(c8 *s, c8 *s_max) { + for (i64 len = 0; s + len < s_max; ++len) + if (s[len] == '\0') + return len; + BX_ASSERT(0); + return 0; +} + b8 bx_str_eq( - c8 const *a, c8 const *a_end, - c8 const *b, c8 const *b_end + c8 *a, c8 *a_end, + c8 *b, c8 *b_end ) { BX_ASSERT(a != NULL && a_end != NULL); BX_ASSERT(b != NULL && b_end != NULL); @@ -817,188 +825,203 @@ void unit_set_entry_point(Pool *pool, i64 unit, i64 entry_point_proc) { // // ================================================================ -u16 read_u16(i32 endianness, void const *v) { +u16 read_u16(i32 endianness, u8 *v, u8 *v_end) { BX_ASSERT(v != NULL); + BX_ASSERT(v + 2 <= v_end); - u8 const *u = (u8 const *) v; - if (endianness == LE) - return ((u16) u[0]) | - (((u16) u[1]) << 8); + return ((u16) v[0]) | + (((u16) v[1]) << 8); if (endianness == BE) - return ((u16) u[1]) | - (((u16) u[0]) << 8); + return ((u16) v[1]) | + (((u16) v[0]) << 8); BX_ASSERT(0); return 0; } -u32 read_u32(i32 endianness, void const *v) { +u32 read_u32(i32 endianness, u8 *v, u8 *v_end) { BX_ASSERT(v != NULL); - - u8 const *u = (u8 const *) v; + BX_ASSERT(v + 4 <= v_end); if (endianness == LE) - return ((u32) u[0]) | - (((u32) u[1]) << 8) | - (((u32) u[2]) << 16) | - (((u32) u[3]) << 24); + return ((u32) v[0]) | + (((u32) v[1]) << 8) | + (((u32) v[2]) << 16) | + (((u32) v[3]) << 24); if (endianness == BE) - return ((u32) u[3]) | - (((u32) u[2]) << 8) | - (((u32) u[1]) << 16) | - (((u32) u[0]) << 24); + return ((u32) v[3]) | + (((u32) v[2]) << 8) | + (((u32) v[1]) << 16) | + (((u32) v[0]) << 24); BX_ASSERT(0); return 0; } -u64 read_u64(i32 endianness, void const *v) { +u64 read_u64(i32 endianness, u8 *v, u8 *v_end) { BX_ASSERT(v != NULL); - - u8 const *u = (u8 const *) v; + BX_ASSERT(v + 8 <= v_end); 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); + return ((u64) v[0]) | + (((u64) v[1]) << 8) | + (((u64) v[2]) << 16) | + (((u64) v[3]) << 24) | + (((u64) v[4]) << 32) | + (((u64) v[5]) << 40) | + (((u64) v[6]) << 48) | + (((u64) v[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); + return ((u64) v[7]) | + (((u64) v[6]) << 8) | + (((u64) v[5]) << 16) | + (((u64) v[4]) << 24) | + (((u64) v[3]) << 32) | + (((u64) v[2]) << 40) | + (((u64) v[1]) << 48) | + (((u64) v[0]) << 56); BX_ASSERT(0); return 0; } -void write_u16(i32 endianness, u16 x, void *v) { +void write_u16(i32 endianness, u16 x, u8 *v, u8 *v_end) { BX_ASSERT(v != NULL); - - u8 *u = (u8 *) v; + BX_ASSERT(v + 2 <= v_end); if (endianness == LE) { - u[0] = (u8) ( x & 0xff); - u[1] = (u8) ((x >> 8) & 0xff); + v[0] = (u8) ( x & 0xff); + v[1] = (u8) ((x >> 8) & 0xff); } if (endianness == BE) { - u[1] = (u8) ( x & 0xff); - u[0] = (u8) ((x >> 8) & 0xff); + v[1] = (u8) ( x & 0xff); + v[0] = (u8) ((x >> 8) & 0xff); } BX_ASSERT(0); } -void write_u32(i32 endianness, u32 x, void *v) { +void write_u32(i32 endianness, u32 x, u8 *v, u8 *v_end) { BX_ASSERT(v != NULL); - - u8 *u = (u8 *) v; + BX_ASSERT(v + 4 <= v_end); 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); + v[0] = (u8) ( x & 0xff); + v[1] = (u8) ((x >> 8) & 0xff); + v[2] = (u8) ((x >> 16) & 0xff); + v[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); + v[3] = (u8) ( x & 0xff); + v[2] = (u8) ((x >> 8) & 0xff); + v[1] = (u8) ((x >> 16) & 0xff); + v[0] = (u8) ((x >> 24) & 0xff); } BX_ASSERT(0); } -void write_u64(i32 endianness, u64 x, void *v) { +void write_u64(i32 endianness, u64 x, u8 *v, u8 *v_end) { BX_ASSERT(v != NULL); - - u8 *u = (u8 *) v; + BX_ASSERT(v + 8 <= v_end); 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); + v[0] = (u8) ( x & 0xff); + v[1] = (u8) ((x >> 8) & 0xff); + v[2] = (u8) ((x >> 16) & 0xff); + v[3] = (u8) ((x >> 24) & 0xff); + v[4] = (u8) ((x >> 32) & 0xff); + v[5] = (u8) ((x >> 40) & 0xff); + v[6] = (u8) ((x >> 48) & 0xff); + v[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); + v[7] = (u8) ( x & 0xff); + v[6] = (u8) ((x >> 8) & 0xff); + v[5] = (u8) ((x >> 16) & 0xff); + v[4] = (u8) ((x >> 24) & 0xff); + v[3] = (u8) ((x >> 32) & 0xff); + v[2] = (u8) ((x >> 40) & 0xff); + v[1] = (u8) ((x >> 48) & 0xff); + v[0] = (u8) ((x >> 56) & 0xff); } BX_ASSERT(0); } -i16 read_i16(i32 endianness, void *v) { - return (i16) read_u16(endianness, v); +i16 read_i16(i32 endianness, void *v, void *v_end) { + return (i16) read_u16(endianness, v, v_end); } -i32 read_i32(i32 endianness, void *v) { - return (i32) read_u32(endianness, v); +i32 read_i32(i32 endianness, void *v, void *v_end) { + return (i32) read_u32(endianness, v, v_end); } -i64 read_i64(i32 endianness, void *v) { - return (i64) read_u64(endianness, v); +i64 read_i64(i32 endianness, void *v, void *v_end) { + return (i64) read_u64(endianness, v, v_end); } -f32 read_f32(i32 endianness, void *v) { - return *(f32 *) &(u32) { read_u32(endianness, v) }; +f32 read_f32(i32 endianness, void *v, void *v_end) { + return *(f32 *) &(u32) { read_u32(endianness, v, v_end) }; } -f32 read_f64(i32 endianness, void *v) { - return *(f64 *) &(u64) { read_u64(endianness, v) }; +f32 read_f64(i32 endianness, void *v, void *v_end) { + return *(f64 *) &(u64) { read_u64(endianness, v, v_end) }; } -void write_i16(i32 endianness, i16 x, void *v) { - write_u16(endianness, (u16) x, v); +void write_i16(i32 endianness, i16 x, void *v, void *v_end) { + write_u16(endianness, (u16) x, v, v_end); } -void write_i32(i32 endianness, i32 x, void *v) { - write_u32(endianness, (u32) x, v); +void write_i32(i32 endianness, i32 x, void *v, void *v_end) { + write_u32(endianness, (u32) x, v, v_end); } -void write_i64(i32 endianness, i64 x, void *v) { - write_u64(endianness, (u64) x, v); +void write_i64(i32 endianness, i64 x, void *v, void *v_end) { + write_u64(endianness, (u64) x, v, v_end); } -void write_f32(i32 endianness, f32 x, void *v) { - write_u32(endianness, *(u32 *) &x, v); +void write_f32(i32 endianness, f32 x, void *v, void *v_end) { + write_u32(endianness, *(u32 *) &x, v, v_end); } -void write_f64(i32 endianness, f64 x, void *v) { - write_u64(endianness, *(u64 *) &x, v); +void write_f64(i32 endianness, f64 x, void *v, void *v_end) { + write_u64(endianness, *(u64 *) &x, v, v_end); } // ================================================================ // // * Code generation and linking // +// ---------------------------------------------------------------- +// +// Docs and helpful materials +// +// AR https://man.freebsd.org/cgi/man.cgi?query=ar&sektion=5 +// ELF https://man7.org/linux/man-pages/man5/elf.5.html +// +// Relocation types +// https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ +// https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/chapter7-2/index.html +// +// https://web.archive.org/web/20150324024617/http://mylinuxbook.com/readelf-command/ +// +// LLVM impl https://github.com/llvm/llvm-project/blob/main/lld/ELF/Driver.cpp#L2822 +// https://github.com/llvm/llvm-project/blob/main/lld/ELF/Writer.cpp#L304 +// https://github.com/llvm/llvm-project/blob/main/lld/ELF/OutputSections.cpp#L469 +// +// Online assembler +// https://defuse.ca/online-x86-assembler.htm +// https://shell-storm.org/online/Online-Assembler-and-Disassembler/ +// // ================================================================ #include <stdio.h> // TEMP @@ -1060,59 +1083,204 @@ typedef struct { Input_Section_Info input_sections[MAX_INPUT_SECTIONS]; } Binary_Output; -void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data) { - // Docs - // - // AR https://man.freebsd.org/cgi/man.cgi?query=ar&sektion=5 - // ELF https://man7.org/linux/man-pages/man5/elf.5.html - // - // Relocation types - // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ - // https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/chapter7-2/index.html - // - // https://web.archive.org/web/20150324024617/http://mylinuxbook.com/readelf-command/ - // - // LLVM impl https://github.com/llvm/llvm-project/blob/main/lld/ELF/Driver.cpp#L2822 - // https://github.com/llvm/llvm-project/blob/main/lld/ELF/Writer.cpp#L304 - // https://github.com/llvm/llvm-project/blob/main/lld/ELF/OutputSections.cpp#L469 - // - // Online assembler - // https://defuse.ca/online-x86-assembler.htm - // https://shell-storm.org/online/Online-Assembler-and-Disassembler/ +// ================================================================ - 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)); +typedef struct { + u64 offset; + u64 size; +} Offset_Size; - // ============================================================== +typedef struct { + u64 offset; + u16 count; +} Offset_Count; + +typedef struct { + Offset_Size name; + u32 type; + u64 flags; + Offset_Size data; +} Section_Header; + +typedef struct { + Offset_Size name; + u8 info; + Offset_Size section; + Offset_Size value; +} Symbol_Entry; - c8 ELF_MAGIC[4] = "\x7f" "ELF"; +typedef struct { + Offset_Size dst; + Offset_Size symbol; + u32 type; +} Rel_Entry; - 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; +typedef struct { + Offset_Size dst; + Offset_Size symbol; + u32 type; + i64 addent; +} Rela_Entry; + +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"; +c8 AR_SYMBOL_TABLE[] = "/ "; +c8 AR_STRING_TABLE[] = "// "; +c8 STRTAB[] = ".strtab"; - 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; +u32 ar_find_symbol_offset_by_name(u8 *ar_symbol_table, u8 *ar_end, c8 *name, c8 *name_end) { + BX_ASSERT(ar_symbol_table != NULL); + BX_ASSERT(name != NULL); + BX_ASSERT(name_end > name); - c8 AR_MAGIC[8] = "!<arch>\n"; + u32 count = read_u32(BE, ar_symbol_table, ar_end); - c8 AR_SYMBOL_TABLE[] = "/ "; - c8 AR_STRING_TABLE[] = "// "; + i64 len = name_end - name; + + c8 *s = (c8 *) (ar_symbol_table + 4 * (count + 1)); + u32 index = 0; + + for (; index < count; ++index) { + BX_ASSERT(s + len <= (c8 *) ar_end); + if (s[len] == '\0' && bx_mem_eq(s, name, len)) + return read_u32(BE, ar_symbol_table + 4 * (index + 1), ar_end); + while (*s != '\0' && s < (c8 *) ar_end) + ++s; + BX_ASSERT(s < (c8 *) ar_end); + BX_ASSERT(*s == '\0'); + ++s; + } + + BX_ASSERT(0); + return 0; +} + +u16 elf_section_names_table_index( + u8 *elf_begin, + u8 *elf_end +) { + return read_u16(LE, elf_begin + 62, elf_end); +} + +Offset_Count elf_section_headers( + u8 *elf_begin, + u8 *elf_end +) { + return (Offset_Count) { + .offset = read_u64(LE, elf_begin + 40, elf_end), + .count = read_u16(LE, elf_begin + 60, elf_end), + }; +} + +u64 elf_section_header_offset( + u8 *elf_begin, + u8 *elf_end, + u16 index +) { + return elf_section_headers(elf_begin, elf_end).offset + ELF_SECTION_HEADER_SIZE * index; +} + +Offset_Size elf_section_names_data( + u8 *elf_begin, + u8 *elf_end +) { + u16 string_table_index = elf_section_names_table_index(elf_begin, elf_end); + + u8 *begin = elf_begin + elf_section_header_offset(elf_begin, elf_end, string_table_index); + + return (Offset_Size) { + .offset = read_u64(LE, begin + 24, elf_end), + .size = read_u64(LE, begin + 32, elf_end), + }; +} + +Offset_Size elf_name_in_string_table( + u8 * elf_begin, + u8 * elf_end, + Offset_Size string_table, + u32 name_offset +) { + u64 offset = string_table.offset + name_offset; + c8 *begin = (c8 *) (elf_begin + offset); + c8 *end = begin + string_table.size; + + BX_ASSERT(end <= (c8 *) elf_end); + + return (Offset_Size) { + .offset = offset, + .size = bx_str_len(begin, end), + }; +} + +u64 elf_find_section_header_by_name( + u8 * elf_begin, + u8 * elf_end, + c8 * name, + u32 name_size +) { + Offset_Count headers = elf_section_headers(elf_begin, elf_end); + Offset_Size names = elf_section_names_data(elf_begin, elf_end); + + for (u16 i = 0; i < headers.count; ++i) { + u8 *begin = elf_begin + headers.offset + i * ELF_SECTION_HEADER_SIZE; + u32 name_offset = read_u32(LE, begin, elf_end); + + if (name_offset + name_size <= names.size && + bx_mem_eq(elf_begin + names.offset + name_offset, name, name_size)) + return headers.offset + i * ELF_SECTION_HEADER_SIZE; + } + + BX_ASSERT(0); + return 0; +} + +Section_Header elf_section_data_by_offset( + u8 *elf_begin, + u8 *elf_end, + u64 offset +) { + Offset_Size names = elf_section_names_data(elf_begin, elf_end); + u8 * begin = elf_begin + offset; + u32 name_index = read_u32(LE, begin, elf_end); + + return (Section_Header) { + .name = elf_name_in_string_table( + elf_begin, + elf_end, + names, + name_index + ), + .type = read_u32(LE, begin + 4, elf_end), + .flags = read_u64(LE, begin + 8, elf_end), + .data = { + .offset = read_u64(LE, begin + 24, elf_end), + .size = read_u64(LE, begin + 32, elf_end), + }, + }; +} + +void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data) { + 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)); - c8 STRTAB[] = ".strtab"; - // ============================================================== #define WRITE(x, n) io_write( io_out, n, x, io_user_data ) @@ -1197,143 +1365,145 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data // Intermediate buffer // + if (0) { + u8 static in_buffer[1024 * 1024 * 300]; // 300 MB + i64 static ar_offsets[128]; + i64 ar_count = 0; - u8 static in_buffer[1024 * 1024 * 300]; // 300 MB - i64 static 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)); + // 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); + 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 + 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_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; + u8 *ar_symbol_table = NULL; + u8 *ar_string_table = NULL; - BX_ASSERT(bx_mem_eq(ar_begin, AR_MAGIC, 8)); + BX_ASSERT(bx_mem_eq(ar_begin, AR_MAGIC, 8)); - u8 *f_begin = ar_begin + 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; + 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); - } + 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); + 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); + 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 - // + if (bx_mem_eq(f_id, AR_SYMBOL_TABLE, 16)) { + // AR symbol table + // - ar_symbol_table = f_data; + ar_symbol_table = f_data; - f_begin = f_data + fn_size; - } else if (bx_mem_eq(f_id, AR_STRING_TABLE, 16)) { - // String table - // + f_begin = f_data + fn_size; + } else if (bx_mem_eq(f_id, AR_STRING_TABLE, 16)) { + // String table + // - ar_string_table = f_data; + ar_string_table = f_data; - f_begin = f_data + fn_size; - } else { - // ======================================================== - // - // Decode ELF object file + f_begin = f_data + fn_size; + } else { + // ======================================================== + // + // Decode ELF object file - u8 *elf_begin = f_data; - f_begin += fn_size; + u8 *elf_begin = f_data; + u8 *elf_end = f_begin + fn_size; + f_begin = elf_end; - u64 section_header_offset; - u16 section_count; - u16 string_table_index; - u16 string_table_offset; + 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(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 + BX_ASSERT(read_u16(LE, elf_begin + 16, elf_end) == ELF_RELOCATABLE); + BX_ASSERT(read_u16(LE, elf_begin + 18, elf_end) == ELF_X86_64); + BX_ASSERT(read_u32(LE, elf_begin + 20, elf_end) == ELF_VERSION); + BX_ASSERT(read_u64(LE, elf_begin + 24, elf_end) == 0); // entry + BX_ASSERT(read_u64(LE, elf_begin + 32, elf_end) == 0); // program header offset - section_header_offset = read_u64(LE, elf_begin + 40); + section_header_offset = read_u64(LE, elf_begin + 40, elf_end); - 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); + BX_ASSERT(read_u32(LE, elf_begin + 48, elf_end) == 0); // flags + BX_ASSERT(read_u16(LE, elf_begin + 52, elf_end) == ELF_HEADER_SIZE); + BX_ASSERT(read_u16(LE, elf_begin + 54, elf_end) == 0); // program header size + BX_ASSERT(read_u16(LE, elf_begin + 56, elf_end) == 0); // program header count + BX_ASSERT(read_u16(LE, elf_begin + 58, elf_end) == ELF_SECTION_HEADER_SIZE); - section_count = read_u16(LE, elf_begin + 60); - string_table_index = read_u16(LE, elf_begin + 62); + section_count = read_u16(LE, elf_begin + 60, elf_end); + string_table_index = read_u16(LE, elf_begin + 62, elf_end); - string_table_offset = read_u64(LE, elf_begin + section_header_offset + string_table_index * ELF_SECTION_HEADER_SIZE + 24); + string_table_offset = read_u64(LE, elf_begin + section_header_offset + string_table_index * ELF_SECTION_HEADER_SIZE + 24, elf_end); - (void) ar_symbol_table; - (void) ar_string_table; + (void) ar_symbol_table; + (void) ar_string_table; - (void) section_header_offset; - (void) section_count; - (void) string_table_index; - (void) string_table_offset; + (void) section_header_offset; + (void) section_count; + (void) string_table_index; + (void) string_table_offset; - f_begin = f_data + fn_size; + f_begin = f_data + fn_size; - // ======================================================== + // ======================================================== + } } } - } - return; + return; + } // ============================================================== @@ -1555,7 +1725,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data u64 strings_offset; u64 symbol_names_offset; - u32 symbol_names_size; + u64 symbol_names_size; b8 symbol_names_found = 0; // ELF header @@ -1630,7 +1800,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data IO_SEEK_BEGIN, io_user_data); u32 name; u64 offset; - u32 size; + u64 size; READ(name); io_seek(f, 20, IO_SEEK_CURSOR, io_user_data); @@ -1734,7 +1904,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data printf( "%-10s", type >= 1 && type <= 9 ? - (c8 const *[]) { + (c8 *[]) { "Program", "Symbols", "Strings", @@ -1850,7 +2020,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data printf("%08llx ", sym_value); // symbol address printf("%-8s ", - (sym_info & 0xf) <= 4 ? (c8 const *[]) { + (sym_info & 0xf) <= 4 ? (c8 *[]) { "No type", "Data", "Func", @@ -1888,18 +2058,18 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data printf("\n"); for (byte_count = size; byte_count > 0;) { - u64 rela_offset; - u64 rela_info; + u64 rel_offset; + u64 rel_info; - READ(rela_offset); BX_ASSERT(n != 0); - READ(rela_info); BX_ASSERT(n != 0); + READ(rel_offset); BX_ASSERT(n != 0); + READ(rel_info); BX_ASSERT(n != 0); - u32 rela_sym = (u32) (rela_info >> 32); - u32 rela_type = (u32) (rela_info & 0xffffffff); + u32 rel_sym = (u32) (rel_info >> 32); + u32 rel_type = (u32) (rel_info & 0xffffffff); printf(" "); - printf("%08llx sym %-2d type %-2d", rela_offset, rela_sym, rela_type); + printf("%08llx sym %-2d type %-2d", rel_offset, rel_sym, rel_type); printf("\n"); } @@ -2104,7 +2274,7 @@ void io_chmod_exe(i64 f, void *user_data) { // Assert // -void bx_assert(b8 condition, c8 const *message, u32 line, c8 const *file) { +void bx_assert(b8 condition, c8 *message, u32 line, c8 *file) { if (condition) return; @@ -2313,8 +2483,8 @@ int main(int argc, char **argv) { i64 u = u_new(); u_add(u, main); u_entry_point(u, main); - l_static(u, "/lib/x86_64-linux-gnu/libc.a"); - // l_static(u, "libtest.a"); + // l_static(u, "/lib/x86_64-linux-gnu/libc.a"); + l_static(u, "libtest.a"); printf("Writing ELF x86_64 executable...\n"); u_elf_x86_64(u, "test_foo"); |