summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-07-17 20:42:51 +0200
committerMitya Selivanov <automainint@guattari.tech>2024-07-17 20:42:51 +0200
commitfcccfe7dd006abb3833220f48837ab5e8b03f233 (patch)
tree9cc5e23906d9501838cd9acb8d2908350c29aacb
parentf6e0b59f79fc413b9556b25eceb05b24608fc415 (diff)
downloadbxgen-fcccfe7dd006abb3833220f48837ab5e8b03f233.zip
Add section info values
-rwxr-xr-xbxgen.c1209
1 files changed, 291 insertions, 918 deletions
diff --git a/bxgen.c b/bxgen.c
index 30f2b9f..af34b1a 100755
--- a/bxgen.c
+++ b/bxgen.c
@@ -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);
}