diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2024-07-17 20:42:51 +0200 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2024-07-17 20:42:51 +0200 |
commit | fcccfe7dd006abb3833220f48837ab5e8b03f233 (patch) | |
tree | 9cc5e23906d9501838cd9acb8d2908350c29aacb | |
parent | f6e0b59f79fc413b9556b25eceb05b24608fc415 (diff) | |
download | bxgen-fcccfe7dd006abb3833220f48837ab5e8b03f233.zip |
Add section info values
-rwxr-xr-x | bxgen.c | 1209 |
1 files changed, 291 insertions, 918 deletions
@@ -99,6 +99,10 @@ exit $? # */ #define TESTING 1 #endif +#ifndef LOG_LEVEL +#define LOG_LEVEL 4 +#endif + // ================================================================ // // Basic declarations @@ -126,7 +130,7 @@ typedef char c8; // 8-bit character enum { // Log level - ERROR = 0, + ERROR = 1, WARNING, INFO, VERBOSE, @@ -364,7 +368,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_log(i32 log_level, c8 *message, u32 line, c8 *file); +void bx_log(i32 log_level, u32 line, c8 *file, c8 *format, ...); 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); @@ -413,25 +417,29 @@ void l_static(i64 unit, c8 *static_library); do { \ b8 ok_ = (condition); \ if (!ok_) { \ - bx_log(ERROR, error_string, __LINE__, __FILE__); \ + bx_log(ERROR, __LINE__, __FILE__, error_string); \ return fail_result; \ } \ } while (0) #else -# define BX_CHECK(condition, error_string, fail_result) \ +# define BX_CHECK(condition, error_string, fail_result) \ bx_assert((condition), error_string, __LINE__, __FILE__) #endif -#define BX_LAX(condition, error_string) \ - do { \ - if (!(condition)) { \ - bx_log(WARNING, error_string, __LINE__, __FILE__); \ - } \ - } while (0) +#ifdef NDEBUG +# define BX_LAX(condition, error_string) \ + do { \ + if (!(condition)) \ + bx_log(WARNING, __LINE__, __FILE__, error_string); \ + } while (0) +#else +# define BX_LAX(condition, error_string) \ + bx_assert((condition), error_string, __LINE__, __FILE__) +#endif #ifdef NDEBUG -# define BX_FAIL(error_string, fail_result) \ - bx_log(ERROR, error_string, __LINE__, __FILE__); \ +# define BX_FAIL(error_string, fail_result) \ + bx_log(ERROR, __LINE__, __FILE__, error_string); \ return fail_result #else # define BX_FAIL(error_string, fail_result) \ @@ -439,8 +447,11 @@ void l_static(i64 unit, c8 *static_library); return fail_result #endif -#define BX_LOG(log_level, message) bx_log(log_level, message, __LINE__, __FILE__) -#define BX_TRACE BX_LOG(TRACE,"") +#define BX_LOG(log_level, ...) \ + do { \ + if (log_level <= LOG_LEVEL) \ + bx_log(log_level, __LINE__, __FILE__, __VA_ARGS__); \ + } while (0) i64 bx_align(i64 x, i64 a) { BX_CHECK(a > 0, "Invalid arguments", 0); @@ -1209,11 +1220,25 @@ enum { ELF_REL_ENTRY_SIZE = 16, ELF_RELA_ENTRY_SIZE = 24, + SEC_NONE = 0, + SEC_PROGRAM, + SEC_SYMBOLS, + SEC_STRINGS, + SEC_RELA, + SEC_HASH, + SEC_DYNAMIC, + SEC_NOTE, + SEC_ZEROS, + SEC_REL, + SEC_GROUP, + SYM_NONE = 0, SYM_PROC, SYM_DATA, - SYM_DATA_UNDEFINED, + SYM_DATA_COMMON, SYM_DATA_THREAD_LOCAL, + SYM_SECTION, + SYM_LOOS, BIND_LOCAL = 0, BIND_GLOBAL, @@ -1252,8 +1277,10 @@ typedef struct { typedef struct { Offset_Size name; - u32 type; - u64 flags; + u32 type_; + b8 alloc; + b8 write; + b8 exec; u64 alignment; u64 entry_size; u32 num_entries; @@ -1351,7 +1378,7 @@ Offset_Size elf_name_in_string_table( Offset_Size string_table, u32 name_offset ) { - if (name_offset == 0 || name_offset >= string_table.size) + if (name_offset == 0) return (Offset_Size) { .offset = 0, .size = 0, @@ -1389,10 +1416,7 @@ u16 elf_find_section_index_by_name( return i; } - BX_LOG(TRACE, name); - BX_LAX(0, "Not found"); - - return 0; + BX_FAIL("Section not found", 0); } Section_Header elf_section( @@ -1407,12 +1431,26 @@ Section_Header elf_section( u32 name_index = read_u32(LE, begin, end); u64 size = read_u64(LE, begin + 32, end); u64 entry_size = read_u64(LE, begin + 56, end); - u32 num_entries = entry_size > 0 ? size / entry_size : 0; + u32 num_entries = entry_size > 0 ? (size / entry_size) : 0; + u32 type = read_u32(LE, begin + 4, end); + u64 flags = read_u64(LE, begin + 8, end); return (Section_Header) { .name = elf_name_in_string_table(b, names, name_index), - .type = read_u32(LE, begin + 4, end), - .flags = read_u64(LE, begin + 8, end), + .type_ = type == 1 ? SEC_PROGRAM : + type == 2 ? SEC_SYMBOLS : + type == 3 ? SEC_STRINGS : + type == 4 ? SEC_RELA : + type == 5 ? SEC_HASH : + type == 6 ? SEC_DYNAMIC : + type == 7 ? SEC_NOTE : + type == 8 ? SEC_ZEROS : + type == 9 ? SEC_REL : + type == 10 ? SEC_GROUP : + SEC_NONE, + .alloc = (flags & 2) == 2, + .write = (flags & 1) == 1, + .exec = (flags & 4) == 4, .alignment = read_u64(LE, begin + 48, end), .entry_size = entry_size, .num_entries = num_entries, @@ -1486,11 +1524,15 @@ Symbol_Entry elf_symbol( BX_CHECK(dst.size == 0 || sym_value + sym_size <= dst.size, "Buffer overflow", (Symbol_Entry) {0}); - u8 type = (sym_info & 0xf) == 1 ? SYM_DATA : - (sym_info & 0xf) == 2 ? SYM_PROC : - (sym_info & 0xf) == 5 ? SYM_DATA_UNDEFINED : - (sym_info & 0xf) == 6 ? SYM_DATA_THREAD_LOCAL : - SYM_NONE; + u8 type = (sym_info & 0xf) == 1 ? SYM_DATA : + (sym_info & 0xf) == 2 ? SYM_PROC : + (sym_info & 0xf) == 3 ? SYM_SECTION : + (sym_info & 0xf) == 5 ? SYM_DATA_COMMON : + (sym_info & 0xf) == 6 ? SYM_DATA_THREAD_LOCAL : + (sym_info & 0xf) == 10 ? SYM_LOOS : + SYM_NONE; + + BX_CHECK(type != SYM_NONE || (sym_info & 0xf) == 0, "Unknown symbol type", (Symbol_Entry) {0}); u8 bind = (sym_info >> 4) == 1 ? BIND_GLOBAL : (sym_info >> 4) == 2 ? BIND_WEAK : @@ -1689,921 +1731,248 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data // Intermediate buffer // - // if (0) - { - u8 static im_buffer[1024 * 1024 * 300]; // 300 MB - i64 static im_offsets[10000]; - i64 im_num = 0; - i64 im_size = 0; - - // Read all dependency files into the memory - // - { - u8 static in_buffer[1024 * 1024 * 100]; // 100 MB - - Unit *u = &pool->entities[unit].unit; - - for (i64 link_index = 0; link_index < u->num_links; ++link_index) { - i64 id = u->links[link_index]; - if (id == UNDEFINED) - continue; - Unit *l = &pool->entities[id].unit; - BX_CHECK(pool->entities[id].is_enabled, "Internal",); - BX_CHECK(l->type == UNIT_LIBRARY_STATIC, "Link type not supported",); - BX_CHECK(l->name_size > 0 && l->name_size <= MAX_NAME_SIZE, "Link name too big",); - - i64 f = io_open_read(l->name_size, l->name, io_user_data); - io_seek(f, 0, IO_SEEK_END, io_user_data); - - i64 in_size = io_tell(f, io_user_data); - BX_CHECK(in_size <= (i64) (sizeof in_buffer), "AR file too big",); - - io_seek(f, 0, IO_SEEK_BEGIN, io_user_data); - i64 n = io_read(f, in_size, in_buffer, io_user_data); - BX_CHECK(n == in_size, "Read failed",); - - io_close(f, io_user_data); - - // ======================================================== - // - // Read AR library - - u8 *ar_begin = in_buffer; - u8 *ar_end = in_buffer + in_size; - - BX_CHECK(bx_mem_eq(ar_begin, AR_MAGIC, 8), "Invalid AR file",); - - 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_CHECK(bx_mem_eq(f_end, "\x60\x0a", 2), "Invalid AR file",); - BX_CHECK(f_begin + fn_size <= ar_end, "Buffer overflow",); - - if (!bx_mem_eq(f_id, AR_SYMBOL_TABLE, 16) && - !bx_mem_eq(f_id, AR_STRING_TABLE, 16)) { - // Read ELF object file - - i64 delta_size = bx_align(fn_size, X86_64_ALIGNMENT); - - BX_CHECK(im_size + delta_size < (i64) (sizeof im_buffer), "Out of memory",); - BX_CHECK(im_num + 1 < (i64) (sizeof im_offsets / sizeof *im_offsets), "Out of memory",); - - bx_mem_cpy(im_buffer + im_size, f_data, fn_size); - - im_offsets[im_num] = im_size; - im_size += delta_size; - im_offsets[++im_num] = im_size; - } - - f_begin = f_data + fn_size; - } - } - - // ========================================================== - // - // Process ELF object files - - for (i64 elf_index = 0; elf_index < im_num; ++elf_index) { - u8 *elf_begin = im_buffer + im_offsets[elf_index]; - u8 *elf_end = im_buffer + im_offsets[elf_index + 1]; - - u8 osabi = read_u8(LE, elf_begin + 7, elf_end); - - BX_CHECK( read_u8 (LE, elf_begin, elf_end) == ELF_MAGIC[0], "Invalid ELF file",); - BX_CHECK( read_u8 (LE, elf_begin + 1, elf_end) == ELF_MAGIC[1], "Invalid ELF file",); - BX_CHECK( read_u8 (LE, elf_begin + 2, elf_end) == ELF_MAGIC[2], "Invalid ELF file",); - BX_CHECK( read_u8 (LE, elf_begin + 3, elf_end) == ELF_MAGIC[3], "Invalid ELF file",); - - BX_CHECK( read_u8 (LE, elf_begin + 4, elf_end) == ELF_64, "Unsupported ELF file",); - BX_CHECK( read_u8 (LE, elf_begin + 5, elf_end) == ELF_2_LE, "Unsupported ELF file",); - BX_CHECK( read_u8 (LE, elf_begin + 6, elf_end) == ELF_VERSION, "Unsupported ELF file",); - BX_CHECK( osabi == ELF_SYS_V || osabi == ELF_LINUX, "Unsupported ELF file",); - BX_CHECK( read_u8 (LE, elf_begin + 8, elf_end) == ELF_ABI_VERSION, "Unsupported ELF file",); - BX_CHECK( read_u16(LE, elf_begin + 16, elf_end) == ELF_RELOCATABLE, "Unsupported ELF file",); - BX_CHECK( read_u16(LE, elf_begin + 18, elf_end) == ELF_X86_64, "Unsupported ELF file",); - BX_CHECK( read_u32(LE, elf_begin + 20, elf_end) == ELF_VERSION, "Unsupported ELF file",); - - BX_LAX( read_u64(LE, elf_begin + 24, elf_end) == 0, "Invalid ELF file"); // entry - BX_LAX( read_u64(LE, elf_begin + 32, elf_end) == 0, "Invalid ELF file"); // program header offset - BX_LAX( read_u32(LE, elf_begin + 48, elf_end) == 0, "Invalid ELF file"); // flags - BX_LAX( read_u16(LE, elf_begin + 52, elf_end) == ELF_HEADER_SIZE, "Invalid ELF file"); - BX_LAX( read_u16(LE, elf_begin + 54, elf_end) == 0, "Invalid ELF file"); // program header size - BX_LAX( read_u16(LE, elf_begin + 56, elf_end) == 0, "Invalid ELF file"); // num program headers - BX_LAX( read_u16(LE, elf_begin + 58, elf_end) == ELF_SECTION_HEADER_SIZE, "Invalid ELF file"); - - Buffer_Context buf = { - .begin = im_buffer, - .end = im_buffer + im_offsets[im_num], - .elf = { - .offset = im_offsets[elf_index], - .size = im_offsets[elf_index + 1] - im_offsets[elf_index], - }, - }; - - Offset_Num section_headers = elf_section_headers(buf); - // Offset_Size section_names = elf_section_names_data(buf); - Offset_Size symbol_names = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data; - - for (u16 sec_index = 0; sec_index < section_headers.num; ++sec_index) { - Section_Header section = elf_section(buf, sec_index); - - if (section.type == 2 || section.type == 4 || section.type == 9) // sym/rela/rel - printf("\"%s", "\x1b[32m"); - else if ((section.flags & 2) != 0) // alloc - printf("\"%s", "\x1b[34m"); - else if (section.type == 3) // string table - printf("\"%s", "\x1b[33m"); - else - printf("\"%s", "\x1b[31m"); - - c8 *name = elf_name_from_offset(buf, section.name); - printf("%s", name); - printf("%s\"", "\x1b[37m"); - printf("%*s", - (i32) (section.name.size < 30 ? 30 - section.name.size : 1), ""); - - printf( - "%-10s", - section.type >= 1 && section.type <= 9 ? - (c8 *[]) { - "Program", - "Symbols", - "Strings", - "Rel add", - "Hash", - "Dynamic", - "Note", - "Zeros", - "Rel", - }[section.type - 1] : - section.type == 17 ? - "Group" : - "" - ); - - if ((section.flags & 2) == 2) - printf("R"); - else - printf("_"); - if ((section.flags & 1) == 1) - printf("W"); - else - printf("_"); - if ((section.flags & 4) == 4) - printf("X"); - else - printf("_"); - - if (section.data.size > 0) - printf(" - %lld bytes", section.data.size); - - printf("\n"); - - switch (section.type) { - case 2: { // sym - for (u32 sym_index = 0; sym_index < section.num_entries; ++sym_index) { - Symbol_Entry sym = elf_symbol(buf, section.data, symbol_names, (u16) sym_index); - printf(" %s\n", elf_name_from_offset(buf, sym.name)); - } - } break; - - case 4: { // rela - } break; - - case 9: { // rel - } break; - - default:; - } - } - - printf("\n"); - } - - // ========================================================== - } - return; - } - - // ============================================================== + u8 static im_buffer[1024 * 1024 * 300]; // 300 MB + i64 static im_offsets[10000]; + i64 im_num = 0; + i64 im_size = 0; - // Read dependencies + // Read all dependency files into the memory // { + u8 static in_buffer[1024 * 1024 * 100]; // 100 MB + Unit *u = &pool->entities[unit].unit; - for (i64 i = 0; i < u->num_links; ++i) { - if (u->links[i] == UNDEFINED) + for (i64 link_index = 0; link_index < u->num_links; ++link_index) { + i64 id = u->links[link_index]; + if (id == UNDEFINED) continue; - - i64 index = u->links[i]; - Unit *l = &pool->entities[index].unit; - - BX_CHECK(pool->entities[index].is_enabled, "",); - BX_CHECK(l->type == UNIT_LIBRARY_STATIC, "",); - BX_CHECK(l->name_size > 0 && l->name_size <= MAX_NAME_SIZE, "",); + Unit *l = &pool->entities[id].unit; + BX_CHECK(pool->entities[id].is_enabled, "Internal",); + BX_CHECK(l->type == UNIT_LIBRARY_STATIC, "Link type not supported",); + BX_CHECK(l->name_size > 0 && l->name_size <= MAX_NAME_SIZE, "Link name too big",); i64 f = io_open_read(l->name_size, l->name, io_user_data); + io_seek(f, 0, IO_SEEK_END, io_user_data); + + i64 in_size = io_tell(f, io_user_data); + BX_CHECK(in_size <= (i64) (sizeof in_buffer), "AR file too big",); - c8 buf0_[MAX_NAME_SIZE + 1] = { 0 }; - bx_mem_cpy(buf0_, l->name, l->name_size); - printf("\nReading `%s` library...\n\n", buf0_); + io_seek(f, 0, IO_SEEK_BEGIN, io_user_data); + i64 n = io_read(f, in_size, in_buffer, io_user_data); + BX_CHECK(n == in_size, "Read failed",); - i64 n = 0, current_offset = 0; + io_close(f, io_user_data); - // ========================================================== + // ======================================================== // // Read AR library - u8 magic[8]; - - n = io_read(f, sizeof magic, magic, io_user_data); if (n == 0) continue; - current_offset += n; - - BX_CHECK(magic[0] == '!', "",); - BX_CHECK(magic[1] == '<', "",); - BX_CHECK(magic[2] == 'a', "",); - BX_CHECK(magic[3] == 'r', "",); - BX_CHECK(magic[4] == 'c', "",); - BX_CHECK(magic[5] == 'h', "",); - BX_CHECK(magic[6] == '>', "",); - BX_CHECK(magic[7] == '\n', "",); - - u32 static offsets[10000] = { 0 }; - c8 static symbols[10000][256] = { 0 }; - b8 static found[10000] = { 0 }; - i64 num_symbols = 0; - - for (;;) { - c8 id[17] = { 0 }; - c8 timestamp[13] = { 0 }; - c8 owner[7] = { 0 }; - c8 group[7] = { 0 }; - c8 mode[9] = { 0 }; - c8 size[11] = { 0 }; - c8 end[2] = { 0 }; - - i64 file_offset = current_offset; - - n = io_read(f, (sizeof id) - 1, id, io_user_data); if (n == 0) break; current_offset += n; - n = io_read(f, (sizeof timestamp) - 1, timestamp, io_user_data); if (n == 0) break; current_offset += n; - n = io_read(f, (sizeof owner) - 1, owner, io_user_data); if (n == 0) break; current_offset += n; - n = io_read(f, (sizeof group) - 1, group, io_user_data); if (n == 0) break; current_offset += n; - n = io_read(f, (sizeof mode) - 1, mode, io_user_data); if (n == 0) break; current_offset += n; - n = io_read(f, (sizeof size) - 1, size, io_user_data); if (n == 0) break; current_offset += n; - n = io_read(f, sizeof end, end, io_user_data); if (n == 0) break; current_offset += n; - - BX_CHECK(end[0] == '\x60', "",); - BX_CHECK(end[1] == '\x0a', "",); - - if (bx_mem_eq(id, AR_SYMBOL_TABLE, 16)) { - // AR symbol table - // - - u32 num_be; - n = io_read(f, 4, &num_be, io_user_data); if (n == 0) break; - current_offset += n; - - num_symbols = - (( num_be & 0xffu) << 24) | - (((num_be >> 8) & 0xffu) << 16) | - (((num_be >> 16) & 0xffu) << 8) | - ((num_be >> 24) & 0xffu); - - printf("Symbol table - %lld symbols.\n\n", num_symbols); - BX_CHECK(num_symbols <= (i64) (sizeof offsets / sizeof *offsets), "",); - - for (u32 j = 0; j < num_symbols; ++j) { - u32 offset_be; - n = io_read(f, 4, &offset_be, io_user_data); if (n == 0) break; - current_offset += n; - - offsets[j] = - (( offset_be & 0xffu) << 24) | - (((offset_be >> 8) & 0xffu) << 16) | - (((offset_be >> 16) & 0xffu) << 8) | - ((offset_be >> 24) & 0xffu); - } - if (n == 0) break; - - i64 num_bytes = 0; - - for (u32 j = 0; j < num_symbols; ++j) { - i64 symbol_size = 0; - for (;; ++symbol_size) { - c8 c; - n = io_read(f, 1, &c, io_user_data); if (n == 0) break; - current_offset += n; - ++num_bytes; - if (c == '\0') - break; - BX_CHECK(symbol_size < 256, "",); - if (symbol_size < 256) - symbols[j][symbol_size] = c; - } - if (n == 0) break; - } - if (n == 0) break; - - if ((num_bytes & 1) == 1) { - // align - io_seek(f, 1, IO_SEEK_CURSOR, io_user_data); - current_offset += 1; - } - } else if (bx_mem_eq(id, AR_STRING_TABLE, 16)) { - // String table - // - - i64 num_bytes = atoi(size); - if ((num_bytes & 1) == 1) - ++num_bytes; // align - - b8 has_line = 0; - - while (num_bytes > 0) { - c8 c; - n = io_read(f, 1, &c, io_user_data); if (n == 0) break; - current_offset += n; - num_bytes -= n; - if (c == '\0') { - if (has_line) { - printf("\n"); - has_line = 0; - } - } else { - if (c == '/') { - if (!has_line) - printf("<EMPTY>"); - } else - printf("%c", c); - has_line = 1; - } - } - } else { - 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, - id, - size); - - // Search for symbols pointing to the current file - // - { - b8 symbol_found = 0; - for (i64 symbol_index = 0; symbol_index < num_symbols; ++symbol_index) - if (offsets[symbol_index] == file_offset) { - printf(" %-50s\n", - symbols[symbol_index]); - found[symbol_index] = 1; - symbol_found = 1; - } - if (!symbol_found) - printf(" <SYMBOLS NOT FOUND>\n"); - } - - // ====================================================== - // - // Decode ELF object file - - i64 num_bytes = atoi(size); - if ((num_bytes & 1) == 1) - ++num_bytes; // align - - 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; - num_bytes -= n; - - BX_CHECK(buf[0] == 0x7f, "",); - BX_CHECK(buf[1] == 'E', "",); - BX_CHECK(buf[2] == 'L', "",); - BX_CHECK(buf[3] == 'F', "",); - - BX_CHECK(buf[4] == ELF_64, "",); - BX_CHECK(buf[5] == ELF_2_LE, "",); - BX_CHECK(buf[6] == ELF_VERSION, "",); - BX_CHECK(buf[7] == ELF_SYS_V || buf[7] == ELF_LINUX, "",); - BX_CHECK(buf[8] == ELF_ABI_VERSION, "",); - - #define READ(x) do { \ - n = io_read(f, sizeof (x), \ - &(x), \ - io_user_data); \ - current_offset += n; \ - num_bytes -= n; \ - } while (0) - - u64 section_header_offset; - u16 num_sections; - u16 strings_index; - u64 strings_offset; - - u64 symbol_names_offset; - u64 symbol_names_size; - b8 symbol_names_found = 0; - - // ELF header - // - { - u16 type; - u16 machine; - u32 ver; - u64 entry; - u64 program_header_offset; - u32 flags; - u16 elf_header_size; - u16 program_header_size; - u16 num_program_headers; - u16 section_header_size; - - 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(num_program_headers); - READ(section_header_size); - READ(num_sections); - READ(strings_index); - - BX_CHECK(type == ELF_RELOCATABLE, "",); - BX_CHECK(machine == ELF_X86_64, "",); - BX_CHECK(ver == ELF_VERSION, "",); - - BX_CHECK(entry == 0, "",); - BX_CHECK(program_header_offset == 0, "",); - BX_CHECK(flags == 0, "",); - BX_CHECK(elf_header_size == 64, "",); - BX_CHECK(program_header_size == 0, "",); - BX_CHECK(num_program_headers == 0, "",); - BX_CHECK(section_header_size == 64, "",); - - u64 section_offset = section_header_offset - (current_offset - begin_offset); - - io_seek(f, section_offset, IO_SEEK_CURSOR, io_user_data); - num_bytes -= section_offset; - current_offset += section_offset; - - // Find offset to the section name string table data - // - { - i64 prev_offset = current_offset; - io_seek(f, - begin_offset + section_header_offset + strings_index * 64 + 24, - IO_SEEK_BEGIN, io_user_data); - - n = io_read(f, 8, &strings_offset, io_user_data); if (n == 0) break; - - io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); - current_offset = prev_offset; - } - - // Find offset to the symbol string table data - // - { - i64 prev_offset = current_offset; - i64 prev_num_bytes = num_bytes; - - for (u16 i = 0; i < num_sections; ++i) { - io_seek(f, - begin_offset + section_header_offset + i * 64, - IO_SEEK_BEGIN, io_user_data); - u32 name; - u64 offset; - u64 size; - - READ(name); - io_seek(f, 20, IO_SEEK_CURSOR, io_user_data); - READ(offset); - READ(size); - - // Search for the name in the string table - // - - io_seek(f, - begin_offset + strings_offset + name, - IO_SEEK_BEGIN, io_user_data); - - c8 buf[8]; - n = io_read(f, sizeof buf, buf, io_user_data); if (n == 0) break; - - if (!bx_mem_eq(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1)) - continue; - - symbol_names_offset = offset; - symbol_names_size = size; - symbol_names_found = 1; - break; - } - - io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); - current_offset = prev_offset; - num_bytes = prev_num_bytes; - } - } - - for (u16 i = 0; i < num_sections; ++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 == 0) { - printf("\n"); - continue; - } - - if (type == 2 || type == 4 || type == 9) // sym/rela/rel - printf("%s", "\x1b[32m"); - else if ((flags & 2) != 0) // alloc - printf("%s", "\x1b[34m"); - else if (type == 3) // string table - printf("%s", "\x1b[33m"); - else - printf("%s", "\x1b[31m"); - - // NOTE - // Only alloc (flags & 2) sections should be written to the output binary. - - // Search for the name in the string table - // - { - i64 prev_offset = current_offset; - io_seek(f, - begin_offset + strings_offset + name, - IO_SEEK_BEGIN, io_user_data); - - i32 padding = 50; - - printf(" "); - - for (;; --padding) { - c8 c; - n = io_read(f, 1, &c, io_user_data); if (n == 0) break; - if (c == '\0') - break; - printf("%c", c); - } - - if (padding > 0) - printf("%*s", padding, ""); - - io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); - current_offset = prev_offset; - } - - printf("%s", "\x1b[37m"); - - printf( - "%-10s", - type >= 1 && type <= 9 ? - (c8 *[]) { - "Program", - "Symbols", - "Strings", - "Rel add", - "Hash", - "Dynamic", - "Note", - "Zeros", - "Rel", - }[type - 1] : - type == 17 ? - "Group" : - "" - ); - - if ((flags & 2) == 2) - printf("R"); - else - printf("_"); - if ((flags & 1) == 1) - printf("W"); - else - printf("_"); - if ((flags & 4) == 4) - printf("X"); - else - printf("_"); - - if (size > 0) - printf(" - %lld bytes", size); - - printf("\n"); - - switch (type) { - // ================================================== - // - // Symbols - - case 2: { - // Find symbol addresses - // - - BX_CHECK(entsize == 24, "",); - - i64 prev_offset = current_offset; - i64 prev_num_bytes = num_bytes; - io_seek(f, - begin_offset + offset, - IO_SEEK_BEGIN, io_user_data); - current_offset = begin_offset + offset; - - printf("\n"); - - for (num_bytes = size; num_bytes > 0;) { - BX_CHECK(symbol_names_found, "",); - - u32 sym_name; - u8 sym_info; - u8 sym_other; - u16 sym_shndx; - u64 sym_value; - u64 sym_size; - - READ(sym_name); BX_CHECK(n != 0, "",); - READ(sym_info); BX_CHECK(n != 0, "",); - READ(sym_other); BX_CHECK(n != 0, "",); - READ(sym_shndx); BX_CHECK(n != 0, "",); - READ(sym_value); BX_CHECK(n != 0, "",); - READ(sym_size); BX_CHECK(n != 0, "",); - - printf(" "); - - if (sym_name != 0) { - if (sym_name < symbol_names_size) { - // Search for the symbol name in the string table - // - - i64 prev_offset = current_offset; - io_seek(f, - begin_offset + symbol_names_offset + sym_name, - IO_SEEK_BEGIN, io_user_data); - - i32 padding = 48; - - if ((sym_info & 0xf) == 1 || - (sym_info & 0xf) == 2) - printf("%s", "\x1b[32m"); - - printf("\""); - - for (;; --padding) { - c8 c; - n = io_read(f, 1, &c, io_user_data); if (n == 0) break; - if (c == '\0') - break; - printf("%c", c); - } - - printf("\""); - if ((sym_info & 0xf) == 1 || - (sym_info & 0xf) == 2) - printf("%s", "\x1b[37m"); - if (padding > 0) - printf("%*s", padding, ""); - - io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); - current_offset = prev_offset; - } else - printf("%-50d", sym_name); - } else - printf("%*s", 50, ""); - - printf("%08llx ", sym_value); // symbol address - - printf("%-8s ", - (sym_info & 0xf) <= 4 ? (c8 *[]) { - "No type", - "Data", - "Func", - "Section", - "File", - }[sym_info & 0xf] : "" - ); - - printf("%-3d", sym_shndx); - - if (sym_size != 0) - printf("- %lld bytes", sym_size); - printf("\n"); - } - - printf("\n"); - - io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); - current_offset = prev_offset; - num_bytes = prev_num_bytes; - } break; - - // ================================================== - // - // Relocarions without addends - - case 9: { - BX_CHECK(entsize == 16, "",); - - i64 prev_offset = current_offset; - i64 prev_num_bytes = num_bytes; - io_seek(f, begin_offset + offset, IO_SEEK_BEGIN, io_user_data); - current_offset = begin_offset + offset; - - printf("\n"); - - for (num_bytes = size; num_bytes > 0;) { - u64 rel_offset; - u64 rel_info; - - READ(rel_offset); BX_CHECK(n != 0, "",); - READ(rel_info); BX_CHECK(n != 0, "",); - - u32 rel_sym = (u32) (rel_info >> 32); - u32 rel_type = (u32) (rel_info & 0xffffffff); - - printf(" "); - - printf("%08llx sym %-2d type %-2d", rel_offset, rel_sym, rel_type); - printf("\n"); - } - - printf("\n"); - - io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); - current_offset = prev_offset; - num_bytes = prev_num_bytes; - } break; - - // ================================================== - // - // Relocarions with addends - // - // for .rela.NAME: - // - // .NAME[rela_offset] <- calc_reloc( - // B = base_memory_address - // P = rela_offset - // A = rela_addent - // S = .symtab[rela_sym].sym_value - // Z = .symtab[rela_sym].sym_size - // ) - - case 4: { - BX_CHECK(entsize == 24, "",); - - i64 prev_offset = current_offset; - i64 prev_num_bytes = num_bytes; - io_seek(f, begin_offset + offset, IO_SEEK_BEGIN, io_user_data); - current_offset = begin_offset + offset; - - printf("\n"); + u8 *ar_begin = in_buffer; + u8 *ar_end = in_buffer + in_size; - for (num_bytes = size; num_bytes > 0;) { - u64 rela_offset; - u64 rela_info; - i64 rela_addent; + BX_CHECK(bx_mem_eq(ar_begin, AR_MAGIC, 8), "Invalid AR file",); - READ(rela_offset); BX_CHECK(n != 0, "",); - READ(rela_info); BX_CHECK(n != 0, "",); - READ(rela_addent); BX_CHECK(n != 0, "",); + u8 *f_begin = ar_begin + 8; - u32 rela_sym = (u32) (rela_info >> 32); - u32 rela_type = (u32) (rela_info & 0xffffffff); + 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; - printf(" "); - - printf("%08llx sym %-2d type %-2d add %-2lld", rela_offset, rela_sym, rela_type, rela_addent); - - // Check value from destination address - // - { - i64 prev_offset = current_offset; - i64 prev_num_bytes = num_bytes; - - u64 sym_size = 0; - - // Go to the symbol table - for (u64 j = 0; j < num_sections; ++j) { - io_seek(f, begin_offset + section_header_offset + j * 64 + 4, IO_SEEK_BEGIN, io_user_data); - u32 type; - READ(type); - - if (type != 2) continue; - - io_seek(f, 16, IO_SEEK_CURSOR, io_user_data); - u64 offset; - READ(offset); - - io_seek(f, begin_offset + offset + rela_sym * 24 + 16, IO_SEEK_BEGIN, io_user_data); - READ(sym_size); - - break; - } + i64 fn_size; + { + c8 buf[7] = {0}; + bx_mem_cpy(buf, f_size, 6); + fn_size = atoi(buf); + } - if (sym_size > 0) { - // NOTE Ad hok - // Go to the previous section - io_seek(f, begin_offset + section_header_offset + (i - 1) * 64 + 24, IO_SEEK_BEGIN, io_user_data); + fn_size = bx_align(fn_size, 2); - u64 offset; - u64 size; - READ(offset); - READ(size); + BX_CHECK(bx_mem_eq(f_end, "\x60\x0a", 2), "Invalid AR file",); + BX_CHECK(f_begin + fn_size <= ar_end, "Buffer overflow",); - if (size > 0) { - io_seek(f, begin_offset + offset + rela_offset, IO_SEEK_BEGIN, io_user_data); - u8 static buf[4]; - if (sym_size > 4) - sym_size = 4; - io_read(f, sym_size, buf, io_user_data); + if (!bx_mem_eq(f_id, AR_SYMBOL_TABLE, 16) && + !bx_mem_eq(f_id, AR_STRING_TABLE, 16)) { + // Read ELF object file - for (u32 k = 0; k < sym_size; ++k) - BX_CHECK(buf[k] == 0, "",); - } - } + i64 delta_size = bx_align(fn_size, X86_64_ALIGNMENT); - io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); - current_offset = prev_offset; - num_bytes = prev_num_bytes; - } + BX_CHECK(im_size + delta_size < (i64) (sizeof im_buffer), "Out of memory",); + BX_CHECK(im_num + 1 < (i64) (sizeof im_offsets / sizeof *im_offsets), "Out of memory",); - printf("\n"); - } + bx_mem_cpy(im_buffer + im_size, f_data, fn_size); - printf("\n"); + im_offsets[im_num] = im_size; + im_size += delta_size; + im_offsets[++im_num] = im_size; + } - io_seek(f, prev_offset, IO_SEEK_BEGIN, io_user_data); - current_offset = prev_offset; - num_bytes = prev_num_bytes; - } break; + f_begin = f_data + fn_size; + } + } - // ================================================== + // ========================================================== + // + // Process ELF object files + + for (i64 elf_index = 0; elf_index < im_num; ++elf_index) { + u8 *elf_begin = im_buffer + im_offsets[elf_index]; + u8 *elf_end = im_buffer + im_offsets[elf_index + 1]; + + u8 osabi = read_u8(LE, elf_begin + 7, elf_end); + + BX_CHECK( read_u8 (LE, elf_begin, elf_end) == ELF_MAGIC[0], "Invalid ELF file",); + BX_CHECK( read_u8 (LE, elf_begin + 1, elf_end) == ELF_MAGIC[1], "Invalid ELF file",); + BX_CHECK( read_u8 (LE, elf_begin + 2, elf_end) == ELF_MAGIC[2], "Invalid ELF file",); + BX_CHECK( read_u8 (LE, elf_begin + 3, elf_end) == ELF_MAGIC[3], "Invalid ELF file",); + + BX_CHECK( read_u8 (LE, elf_begin + 4, elf_end) == ELF_64, "Unsupported ELF file",); + BX_CHECK( read_u8 (LE, elf_begin + 5, elf_end) == ELF_2_LE, "Unsupported ELF file",); + BX_CHECK( read_u8 (LE, elf_begin + 6, elf_end) == ELF_VERSION, "Unsupported ELF file",); + BX_CHECK( osabi == ELF_SYS_V || osabi == ELF_LINUX, "Unsupported ELF file",); + BX_CHECK( read_u8 (LE, elf_begin + 8, elf_end) == ELF_ABI_VERSION, "Unsupported ELF file",); + BX_CHECK( read_u16(LE, elf_begin + 16, elf_end) == ELF_RELOCATABLE, "Unsupported ELF file",); + BX_CHECK( read_u16(LE, elf_begin + 18, elf_end) == ELF_X86_64, "Unsupported ELF file",); + BX_CHECK( read_u32(LE, elf_begin + 20, elf_end) == ELF_VERSION, "Unsupported ELF file",); + + BX_LAX( read_u64(LE, elf_begin + 24, elf_end) == 0, "Invalid ELF file"); // entry + BX_LAX( read_u64(LE, elf_begin + 32, elf_end) == 0, "Invalid ELF file"); // program header offset + BX_LAX( read_u32(LE, elf_begin + 48, elf_end) == 0, "Invalid ELF file"); // flags + BX_LAX( read_u16(LE, elf_begin + 52, elf_end) == ELF_HEADER_SIZE, "Invalid ELF file"); + BX_LAX( read_u16(LE, elf_begin + 54, elf_end) == 0, "Invalid ELF file"); // program header size + BX_LAX( read_u16(LE, elf_begin + 56, elf_end) == 0, "Invalid ELF file"); // num program headers + BX_LAX( read_u16(LE, elf_begin + 58, elf_end) == ELF_SECTION_HEADER_SIZE, "Invalid ELF file"); + + Buffer_Context buf = { + .begin = im_buffer, + .end = im_buffer + im_offsets[im_num], + .elf = { + .offset = im_offsets[elf_index], + .size = im_offsets[elf_index + 1] - im_offsets[elf_index], + }, + }; + + Offset_Num section_headers = elf_section_headers(buf); + + for (u16 sec_index = 0; sec_index < section_headers.num; ++sec_index) { + Section_Header section = elf_section(buf, sec_index); + + if (section.type_ == SEC_SYMBOLS || + section.type_ == SEC_RELA || + section.type_ == SEC_REL) + printf("\"%s", "\x1b[32m"); + else if (section.alloc) + printf("\"%s", "\x1b[34m"); + else if (section.type_ == SEC_STRINGS) + printf("\"%s", "\x1b[33m"); + else + printf("\"%s", "\x1b[31m"); + + c8 *name = elf_name_from_offset(buf, section.name); + printf("%s", name); + printf("%s\"", "\x1b[37m"); + printf("%*s", + (i32) (section.name.size < 30 ? 30 - section.name.size : 1), ""); + + printf( + "%-10s", + (c8 *[]) { + "", + "Program", + "Symbols", + "Strings", + "Rel add", + "Hash", + "Dynamic", + "Note", + "Zeros", + "Rel", + "Group", + }[section.type_] + ); + + if (section.alloc) + printf("R"); + else + printf("_"); + if (section.write) + printf("W"); + else + printf("_"); + if (section.exec) + printf("X"); + else + printf("_"); + + if (section.data.size > 0) + printf(" - %lld bytes", section.data.size); - default:; - } - } + printf("\n"); - printf("\n"); + switch (section.type_) { + case SEC_SYMBOLS: { + Offset_Size symbol_names = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data; + + for (u32 sym_index = 0; sym_index < section.num_entries; ++sym_index) { + Symbol_Entry sym = elf_symbol(buf, section.data, symbol_names, (u16) sym_index); + + c8 *name = elf_name_from_offset(buf, sym.name); + + i32 len = *name == '\0' ? 4 : (i32) sym.name.size; + + printf(" "); + if (*name != '\0') + printf("\""); + + if (sym.bind == BIND_GLOBAL) + printf("\x1b[32m"); + else if (sym.bind == BIND_WEAK) + printf("\x1b[35m"); + else + printf("\x1b[31m"); + + if (*name != '\0') + printf("%s", name); + else + printf("<NONE>"); + printf("\x1b[37m"); + + if (*name != '\0') + printf("\""); + + printf(" "); + if (len < 32) + printf("%.*s ", 32 - len, "........................................"); + printf(" "); + + switch (sym.type) { + case SYM_PROC: printf("\x1b[32mproc "); break; + case SYM_DATA: printf("\x1b[32mdata "); break; + case SYM_DATA_COMMON: printf("\x1b[33mdata "); break; + case SYM_DATA_THREAD_LOCAL: printf("\x1b[35mdata "); break; + case SYM_SECTION: printf("\x1b[31msection"); break; + case SYM_LOOS: printf("\x1b[31mloos "); break; + default: printf(" "); + } + printf("\x1b[37m"); + printf("\n"); + } + } break; - io_seek(f, num_bytes, IO_SEEK_CURSOR, io_user_data); - current_offset += num_bytes; + case SEC_RELA: { + } break; - #undef READ + case SEC_REL: { + } break; - // ====================================================== + default:; } } - for (i64 symbol_index = 0; symbol_index < num_symbols; ++symbol_index) - if (!found[symbol_index]) - printf(" ? : %-16s - %-50s\n", - "<FILE NOT FOUND>", - symbols[symbol_index]); - - // ========================================================== - - io_close(f, io_user_data); + printf("\n"); } } } @@ -2660,25 +2029,29 @@ void io_chmod_exe(i64 f, void *user_data) { #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stdarg.h> #ifdef __unix__ #include <sys/types.h> #include <sys/stat.h> #endif -#define BX_LOGF(log_level, ...) \ - do { \ - c8 buf[1024] = {0}; \ - sprintf(buf, __VA_ARGS__); \ - BX_LOG(log_level, buf); \ - } while (0) +void bx_log(i32 log_level, u32 line, c8 *file, c8 *format, ...) { + if (file == NULL || format == NULL) + return; -void bx_log(i32 log_level, c8 *message, u32 line, c8 *file) { - if (*message == '\0' && log_level != TRACE) { + if (*format == '\0' && log_level != TRACE) { fprintf(log_level == ERROR || log_level == WARNING ? stderr : stdout, "\n"); return; } + c8 message[256]; + + va_list ap; + va_start(ap, format); + vsprintf(message, format, ap); + va_end(ap); + fflush(stdout); i32 len = 56 - (i32) bx_str_len_or(message, message + 56, 56); switch (log_level) { @@ -2729,7 +2102,7 @@ void bx_assert(b8 condition, c8 *message, u32 line, c8 *file) { if (condition) return; - bx_log(ERROR, message, line, file); + bx_log(ERROR, line, file, message); exit(-1); } |