summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-07-19 13:54:37 +0200
committerMitya Selivanov <automainint@guattari.tech>2024-07-19 13:54:37 +0200
commitd37f496059bba635eeb4ecd4262b9a05f088d09d (patch)
tree8eecfb4751c1d769f11499913a2624728cc9bec1
parentebd61b71171889b908de20d973e0a17c1f4e5149 (diff)
downloadbxgen-d37f496059bba635eeb4ecd4262b9a05f088d09d.zip
Separate ELF dump function
-rwxr-xr-xbxgen.c776
1 files changed, 417 insertions, 359 deletions
diff --git a/bxgen.c b/bxgen.c
index f293b87..f2fafe2 100755
--- a/bxgen.c
+++ b/bxgen.c
@@ -75,7 +75,7 @@ SRC=${0##*./}
BIN=${SRC%.*}
gcc \
-Wno-old-style-declaration -Wno-missing-braces \
- -Wno-unused-variable \
+ -Wno-unused-variable -Wno-unused-but-set-variable \
-Wall -Wextra -Werror -pedantic \
-O0 -fsanitize=undefined,address,leak -mshstk \
-o $BIN $SRC && \
@@ -108,6 +108,10 @@ exit $? # */
#define LOG_BLOCKING 1
#endif
+#ifndef TRACE_BLOCKING
+#define TRACE_BLOCKING 1
+#endif
+
// ================================================================
//
// Basic declarations
@@ -141,6 +145,22 @@ enum {
VERBOSE,
TRACE,
+ // Limits
+ //
+
+ MAX_OBJECT_FILE_SIZE = 10 * 1024 * 1024,
+ MAX_NUM_OBJECT_FILES = 10 * 1024,
+ MAX_DEPENDENCIES_SIZE = 300 * 1024 * 1024,
+ STRING_TABLE_ALIGNMENT = 16, // TODO
+ MAX_PATH_SIZE = 10 * 1024,
+ MAX_LITERAL_SIZE = 400,
+ MAX_NAME_SIZE = 80,
+ MAX_NUM_PROCS = 40,
+ MAX_NUM_NODES = 60,
+ MAX_NUM_LINKS = 20,
+ MAX_NUM_ARGS = 20,
+ MAX_NUM_ENTITIES = 16 * 1024,
+
// For indices
UNDEFINED = -1,
@@ -177,14 +197,6 @@ enum {
UNIT_LIBRARY_STATIC,
UNIT_LIBRARY_DYNAMIC,
- // Buffers
- //
-
- MAX_OBJECT_FILE_SIZE = 10 * 1024 * 1024,
- MAX_NUM_OBJECT_FILES = 10 * 1024,
- MAX_DEPENDENCIES_SIZE = 300 * 1024 * 1024,
- STRING_TABLE_ALIGNMENT = 16, // TODO
-
// Entity types
//
@@ -192,17 +204,6 @@ enum {
ENTITY_PROC,
ENTITY_UNIT,
- // Limits
- //
-
- MAX_LITERAL_SIZE = 400,
- MAX_NAME_SIZE = 80,
- MAX_NUM_PROCS = 40,
- MAX_NUM_NODES = 60,
- MAX_NUM_LINKS = 20,
- MAX_NUM_ARGS = 20,
- MAX_NUM_ENTITIES = 16 * 1024,
-
// IO dispatch operations
//
@@ -498,6 +499,8 @@ i64 bx_align(i64 x, i64 a) {
return x + ((a - (x % a)) % a);
}
+#define BX_TRACE BX_LOG(TRACE, "")
+
void bx_mem_cpy(void *dst, void *src, i64 size) {
BX_CHECK(dst != NULL, "Invalid arguments",);
BX_CHECK(src != NULL, "Invalid arguments",);
@@ -1291,8 +1294,8 @@ enum {
SYM_NONE = 0,
SYM_PROC,
SYM_DATA,
- SYM_DATA_COMMON,
- SYM_DATA_THREAD_LOCAL,
+ SYM_COMMON,
+ SYM_TLS,
SYM_SECTION,
SYM_SPECIFIC,
@@ -1710,12 +1713,12 @@ 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) == 0 ? SYM_NONE :
- (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 :
+ u8 type = (sym_info & 0xf) == 0 ? SYM_NONE :
+ (sym_info & 0xf) == 1 ? SYM_DATA :
+ (sym_info & 0xf) == 2 ? SYM_PROC :
+ (sym_info & 0xf) == 3 ? SYM_SECTION :
+ (sym_info & 0xf) == 5 ? SYM_COMMON :
+ (sym_info & 0xf) == 6 ? SYM_TLS :
SYM_SPECIFIC;
BX_CHECK(type != SYM_NONE || (sym_info & 0xf) == 0, "Unknown symbol type", (Symbol_Entry) {0});
@@ -1815,8 +1818,153 @@ Symbol_Entry elf_find_symbol_by_name(
BX_FAIL("Not found", (Symbol_Entry) {0});
}
-#include <stdio.h> // TEMP
-#include <stdlib.h> // TEMP
+void elf_dump(u32 log_level, Buffer_Context b) {
+ Offset_Num section_headers = elf_section_headers(b);
+ Offset_Size symbol_names = {0};
+ Offset_Size symbols = {0};
+
+ for (i64 sec_index = 0; sec_index < section_headers.num; ++sec_index) {
+ Section_Header section = elf_section(b, sec_index);
+
+ c8 *name = elf_name_from_offset(b, section.name);
+
+ BX_LOG(
+ log_level,
+ "\"%s%s\x1b[37m\"%*s%-14s%s%s%s%s%lld%s",
+ section.type == SEC_SYMTAB ||
+ section.type == SEC_RELA ||
+ section.type == SEC_REL ? "\x1b[32m" :
+ section.alloc ? "\x1b[34m" :
+ section.type == SEC_STRTAB ? "\x1b[33m" :
+ "\x1b[31m",
+ name,
+ (i32) (section.name.size < 30 ? 30 - section.name.size : 1),
+ "",
+ SEC_TYPE_NAMES[section.type],
+ section.alloc ? "R" : "_",
+ section.write ? "W" : "_",
+ section.exec ? "X" : "_",
+ section.data.size > 0 ? " - " : "",
+ section.data.size,
+ section.data.size > 0 ? " bytes" : "\b "
+ );
+
+ switch (section.type) {
+ case SEC_SYMTAB:
+ if (symbols.offset == 0)
+ symbols = section.data;
+
+ if (symbol_names.offset == 0)
+ symbol_names = elf_find_section_by_name(b, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
+
+ BX_LOG(log_level, " - -");
+
+ for (i64 sym_index = 0; sym_index < section.num_entries; ++sym_index) {
+ Symbol_Entry sym = elf_symbol(b, section.data, symbol_names, (u16) sym_index);
+
+ c8 *name = elf_name_from_offset(b, sym.name);
+
+ i32 len = (sym.name.size == 0) ? 4 : (i32) sym.name.size;
+
+ BX_LOG(
+ log_level,
+ " %s%s%s\x1b[37m%s %.*s %s\x1b[37m",
+ *name != '\0' ? "\"" : "",
+ sym.bind == BIND_GLOBAL ? "\x1b[32m" :
+ sym.bind == BIND_WEAK ? "\x1b[35m" :
+ "\x1b[31m",
+ *name != '\0' ? name : "<NONE>",
+ *name != '\0' ? "\"" : "",
+ 31 < len ? 1 : 32 - len,
+ 31 < len ? " " : "........................................",
+ sym.type == SYM_PROC ? "\x1b[32mproc " :
+ sym.type == SYM_DATA ? "\x1b[32mdata " :
+ sym.type == SYM_COMMON ? "\x1b[33mcommon " :
+ sym.type == SYM_TLS ? "\x1b[35mtls " :
+ sym.type == SYM_SECTION ? "\x1b[31msection" :
+ sym.type == SYM_SPECIFIC ? "\x1b[31mspec " :
+ " "
+ );
+ }
+
+ BX_LOG(log_level, " - -");
+ break;
+
+ case SEC_RELA: {
+ if (symbol_names.offset == 0)
+ symbol_names = elf_find_section_by_name(b, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
+ if (symbols.offset == 0)
+ symbols = elf_find_section_by_name(b, SECTION_SYMTAB, sizeof SECTION_SYMTAB - 1).data;
+
+ Offset_Size dst = elf_find_related_data(b, sec_index);
+
+ BX_LOG(log_level, " - -");
+
+ for (i64 rela_index = 0; rela_index < section.num_entries; ++rela_index) {
+ Rela_Entry rela = elf_rela(b, symbols, symbol_names, section.data, dst, rela_index);
+
+ BX_LOG(
+ log_level,
+ " %-16s %08llx %-+5lld <= %s%08llx\x1b[37m%s\x1b[37m \"%s\"",
+ REL_NAMES[rela.type],
+ rela.dst,
+ rela.addent,
+ rela.symbol.bind == BIND_WEAK ? "\x1b[33m" : "\x1b[32m",
+ rela.symbol.value.offset,
+ rela.symbol.type == SYM_DATA ||
+ rela.symbol.type == SYM_COMMON ||
+ rela.symbol.type == SYM_TLS ? " \x1b[34mdata" :
+ rela.symbol.type == SYM_PROC ? " \x1b[34mproc" :
+ rela.symbol.type == SYM_SECTION ? " \x1b[36msect" :
+ rela.symbol.type == SYM_SPECIFIC ? " \x1b[34mspec" :
+ " \x1b[33mnone",
+ elf_name_from_offset(b, rela.symbol.name)
+ );
+ }
+
+ BX_LOG(log_level, " - -");
+ } break;
+
+ case SEC_REL: {
+ if (symbol_names.offset == 0)
+ symbol_names = elf_find_section_by_name(b, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
+ if (symbols.offset == 0)
+ symbols = elf_find_section_by_name(b, SECTION_SYMTAB, sizeof SECTION_SYMTAB - 1).data;
+
+ Offset_Size dst = elf_find_related_data(b, sec_index);
+
+ BX_LOG(log_level, " - -");
+
+ for (i64 rel_index = 0; rel_index < section.num_entries; ++rel_index) {
+ Rel_Entry rel = elf_rel(b, symbols, symbol_names, section.data, dst, rel_index);
+
+ BX_LOG(
+ log_level,
+ " %-16s %08llx <= %s%08llx\x1b[37m%s\x1b[37m \"%s\"",
+ REL_NAMES[rel.type],
+ rel.dst,
+ rel.symbol.bind == BIND_WEAK ? "\x1b[33m" : "\x1b[32m",
+ rel.symbol.value.offset,
+ rel.symbol.type == SYM_DATA ||
+ rel.symbol.type == SYM_COMMON ||
+ rel.symbol.type == SYM_TLS ? " \x1b[34mdata" :
+ rel.symbol.type == SYM_PROC ? " \x1b[34mproc" :
+ rel.symbol.type == SYM_SECTION ? " \x1b[36msect" :
+ rel.symbol.type == SYM_SPECIFIC ? " \x1b[34mspec" :
+ " \x1b[33mnone",
+ elf_name_from_offset(b, rel.symbol.name)
+ );
+ }
+
+ BX_LOG(log_level, " - -");
+ } break;
+
+ default:;
+ }
+ }
+
+ BX_LOG(log_level, "");
+}
void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data) {
BX_CHECK(pool != NULL && pool->entities != NULL, "Invalid arguments",);
@@ -1829,13 +1977,8 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
BX_CHECK(pool->obj_file_offsets != NULL, "No object file offsets buffer",);
// ==============================================================
-
- #define WRITE(x, n) io_write( io_out, n, x, io_user_data )
- #define WRITE_V(...) io_write( io_out, sizeof((u8[]) {__VA_ARGS__}), (u8[]) {__VA_ARGS__}, io_user_data )
- #define WRITE_DUP(x, n) io_write( io_out, n, (u8[n]) { 0 }, io_user_data )
- #define WRITE_2(x) io_write( io_out, 2, &(u16) { x }, io_user_data )
- #define WRITE_4(x) io_write( io_out, 4, &(u32) { x }, io_user_data )
- #define WRITE_8(x) io_write( io_out, 8, &(u64) { x }, io_user_data )
+ //
+ // Our program
u8 code[32] = {
0xb8, 0x3c, 0x00, 0x00, 0x00, // mov eax, 60
@@ -1851,8 +1994,236 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
i64 code_address = base_address + code_offset;
i64 entry = code_address + entry_offset;
- BX_CHECK((code_offset % X86_64_ALIGNMENT) == 0, "Invalid alignment",);
- BX_CHECK((code_size % X86_64_ALIGNMENT) == 0, "Invalid alignment",);
+ Symbol_Entry sym_printf = {0};
+
+ i64 text_size = code_size;
+ i64 data_size = 0;
+ i64 bss_size = 0;
+ i64 rodata_size = 0;
+
+ // ==============================================================
+ //
+ // Reading dependencies
+
+ i64 im_num = 0;
+ i64 im_size = 0;
+
+ // Read all dependency files into the memory
+ //
+
+ 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 <= pool->max_obj_file_size, "AR file too big",);
+
+ io_seek(f, 0, IO_SEEK_BEGIN, io_user_data);
+ i64 n = io_read(f, in_size, pool->obj_file_buffer, io_user_data);
+ BX_CHECK(n == in_size, "Read failed",);
+
+ io_close(f, io_user_data);
+
+ // ========================================================
+ //
+ // Read AR library
+
+ u8 *ar_begin = pool->obj_file_buffer;
+ u8 *ar_end = pool->obj_file_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 size = bx_i64_from_str((c8 *) f_size, (c8 *) f_size + 10);
+
+ size = bx_align(size, 2);
+
+ BX_CHECK(bx_mem_eq(f_end, "\x60\x0a", 2), "Invalid AR file",);
+ BX_CHECK(f_begin + 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(size, X86_64_ALIGNMENT);
+
+ BX_CHECK(im_size + delta_size < pool->max_dependencies_size, "Out of memory",);
+ BX_CHECK(im_num + 1 < pool->max_num_obj_files, "Out of memory",);
+
+ bx_mem_cpy(pool->dependencies_buffer + im_size, f_data, size);
+
+ pool->obj_file_offsets[im_num] = im_size;
+ im_size += delta_size;
+ pool->obj_file_offsets[++im_num] = im_size;
+ }
+
+ f_begin = f_data + size;
+ }
+ }
+
+ // ==========================================================
+ //
+ // Process ELF object files
+
+ for (i64 elf_index = 0; elf_index < im_num; ++elf_index) {
+ u8 *elf_begin = pool->dependencies_buffer + pool->obj_file_offsets[elf_index];
+ u8 *elf_end = pool->dependencies_buffer + pool->obj_file_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 entry point");
+ BX_LAX( read_u64(LE, elf_begin + 32, elf_end) == 0, "Invalid program header offset");
+ BX_LAX( read_u32(LE, elf_begin + 48, elf_end) == 0, "Invalid flags");
+ BX_LAX( read_u16(LE, elf_begin + 52, elf_end) == ELF_HEADER_SIZE, "Invalid ELF header size");
+ BX_LAX( read_u16(LE, elf_begin + 54, elf_end) == 0, "Invalid program header size");
+ BX_LAX( read_u16(LE, elf_begin + 56, elf_end) == 0, "Invalid num program headers");
+ BX_LAX( read_u16(LE, elf_begin + 58, elf_end) == ELF_SECTION_HEADER_SIZE, "Invalid section header size");
+
+ Buffer_Context buf = {
+ .begin = pool->dependencies_buffer,
+ .end = pool->dependencies_buffer + pool->obj_file_offsets[im_num],
+ .elf = {
+ .offset = pool->obj_file_offsets[elf_index],
+ .size = pool->obj_file_offsets[elf_index + 1] - pool->obj_file_offsets[elf_index],
+ },
+ };
+
+ elf_dump(VERBOSE, buf);
+
+ Offset_Num section_headers = elf_section_headers(buf);
+ Offset_Size symbol_names = {0};
+ Offset_Size symbols = {0};
+
+ for (i64 sec_index = 0; sec_index < section_headers.num; ++sec_index) {
+ Section_Header section = elf_section(buf, sec_index);
+
+ i64 offset = 0;
+
+ if (section.alloc) {
+ if (section.exec) {
+ offset = text_size;
+ text_size += bx_align(section.data.size, X86_64_ALIGNMENT);
+ } else if (section.write && section.type == SEC_NOBITS) {
+ offset = bss_size;
+ bss_size += bx_align(section.data.size, X86_64_ALIGNMENT);
+ } else if (section.write) {
+ offset = data_size;
+ data_size += bx_align(section.data.size, X86_64_ALIGNMENT);
+ } else if (section.data.size > 0) {
+ offset = rodata_size;
+ rodata_size += bx_align(section.data.size, X86_64_ALIGNMENT);
+ } else
+ BX_LAX(0, "Unsupported section type");
+ }
+
+ switch (section.type) {
+ case SEC_SYMTAB:
+ if (symbols.offset == 0)
+ symbols = section.data;
+ if (symbol_names.offset == 0)
+ symbol_names = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
+
+ for (i64 sym_index = 0; sym_index < section.num_entries; ++sym_index) {
+ Symbol_Entry sym = elf_symbol(buf, section.data, symbol_names, (u16) sym_index);
+
+ if (sym.name.size == 6 && bx_mem_eq(elf_name_from_offset(buf, sym.name), "printf", 6)) {
+ if (sym_printf.value.offset != 0)
+ BX_LAX(0, "Symbol redefinition");
+ sym_printf = sym;
+ }
+ }
+
+ break;
+
+ case SEC_RELA: {
+ if (symbol_names.offset == 0)
+ symbol_names = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
+ if (symbols.offset == 0)
+ symbols = elf_find_section_by_name(buf, SECTION_SYMTAB, sizeof SECTION_SYMTAB - 1).data;
+
+ Offset_Size dst = elf_find_related_data(buf, sec_index);
+
+ for (i64 rela_index = 0; rela_index < section.num_entries; ++rela_index) {
+ Rela_Entry rela = elf_rela(buf, symbols, symbol_names, section.data, dst, rela_index);
+ }
+
+ } break;
+
+ case SEC_REL: {
+ if (symbol_names.offset == 0)
+ symbol_names = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
+ if (symbols.offset == 0)
+ symbols = elf_find_section_by_name(buf, SECTION_SYMTAB, sizeof SECTION_SYMTAB - 1).data;
+
+ Offset_Size dst = elf_find_related_data(buf, sec_index);
+
+ for (i64 rel_index = 0; rel_index < section.num_entries; ++rel_index) {
+ Rel_Entry rel = elf_rel(buf, symbols, symbol_names, section.data, dst, rel_index);
+ }
+
+ } break;
+
+ default:;
+ }
+ }
+ }
+
+ // ==============================================================
+
+ // TODO Write sections into the output buffer.
+ //
+
+ // ==============================================================
+ //
+ // Writing the ELF executable
+
+ BX_LOG(VERBOSE, "Total size");
+ BX_LOG(VERBOSE, ".text: %lld", text_size);
+ BX_LOG(VERBOSE, ".bss: %lld", bss_size);
+ BX_LOG(VERBOSE, ".data: %lld", data_size);
+ BX_LOG(VERBOSE, ".rodata: %lld", rodata_size);
+
+ BX_LOG(VERBOSE, "");
+
+ BX_LOG(VERBOSE, "Found printf: %d", sym_printf.value.offset);
+
+ #define WRITE(x, n) io_write( io_out, n, x, io_user_data )
+ #define WRITE_V(...) io_write( io_out, sizeof((u8[]) {__VA_ARGS__}), (u8[]) {__VA_ARGS__}, io_user_data )
+ #define WRITE_DUP(x, n) io_write( io_out, n, (u8[n]) { 0 }, io_user_data )
+ #define WRITE_2(x) io_write( io_out, 2, &(u16) { x }, io_user_data )
+ #define WRITE_4(x) io_write( io_out, 4, &(u32) { x }, io_user_data )
+ #define WRITE_8(x) io_write( io_out, 8, &(u64) { x }, io_user_data )
// ELF header
//
@@ -1907,321 +2278,6 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
#undef WRITE_64
#undef WRITE
-
- // ==============================================================
-
- // Intermediate buffer
- //
-
- i64 im_num = 0;
- i64 im_size = 0;
-
- // Read all dependency files into the memory
- //
- {
- 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 <= pool->max_obj_file_size, "AR file too big",);
-
- io_seek(f, 0, IO_SEEK_BEGIN, io_user_data);
- i64 n = io_read(f, in_size, pool->obj_file_buffer, io_user_data);
- BX_CHECK(n == in_size, "Read failed",);
-
- io_close(f, io_user_data);
-
- // ========================================================
- //
- // Read AR library
-
- u8 *ar_begin = pool->obj_file_buffer;
- u8 *ar_end = pool->obj_file_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 size = bx_i64_from_str((c8 *) f_size, (c8 *) f_size + 10);
-
- size = bx_align(size, 2);
-
- BX_CHECK(bx_mem_eq(f_end, "\x60\x0a", 2), "Invalid AR file",);
- BX_CHECK(f_begin + 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(size, X86_64_ALIGNMENT);
-
- BX_CHECK(im_size + delta_size < pool->max_dependencies_size, "Out of memory",);
- BX_CHECK(im_num + 1 < pool->max_num_obj_files, "Out of memory",);
-
- bx_mem_cpy(pool->dependencies_buffer + im_size, f_data, size);
-
- pool->obj_file_offsets[im_num] = im_size;
- im_size += delta_size;
- pool->obj_file_offsets[++im_num] = im_size;
- }
-
- f_begin = f_data + size;
- }
- }
-
- // ==========================================================
- //
- // Process ELF object files
-
- for (i64 elf_index = 0; elf_index < im_num; ++elf_index) {
- u8 *elf_begin = pool->dependencies_buffer + pool->obj_file_offsets[elf_index];
- u8 *elf_end = pool->dependencies_buffer + pool->obj_file_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 entry point");
- BX_LAX( read_u64(LE, elf_begin + 32, elf_end) == 0, "Invalid program header offset");
- BX_LAX( read_u32(LE, elf_begin + 48, elf_end) == 0, "Invalid flags");
- BX_LAX( read_u16(LE, elf_begin + 52, elf_end) == ELF_HEADER_SIZE, "Invalid ELF header size");
- BX_LAX( read_u16(LE, elf_begin + 54, elf_end) == 0, "Invalid program header size");
- BX_LAX( read_u16(LE, elf_begin + 56, elf_end) == 0, "Invalid num program headers");
- BX_LAX( read_u16(LE, elf_begin + 58, elf_end) == ELF_SECTION_HEADER_SIZE, "Invalid section header size");
-
- Buffer_Context buf = {
- .begin = pool->dependencies_buffer,
- .end = pool->dependencies_buffer + pool->obj_file_offsets[im_num],
- .elf = {
- .offset = pool->obj_file_offsets[elf_index],
- .size = pool->obj_file_offsets[elf_index + 1] - pool->obj_file_offsets[elf_index],
- },
- };
-
- Offset_Num section_headers = elf_section_headers(buf);
- Offset_Size symbol_names = {0};
- Offset_Size symbols = {0};
-
- for (i64 sec_index = 0; sec_index < section_headers.num; ++sec_index) {
- Section_Header section = elf_section(buf, sec_index);
-
- if (section.type == SEC_SYMTAB ||
- 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_STRTAB)
- 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("%-14s", SEC_TYPE_NAMES[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);
-
- printf("\n");
-
- switch (section.type) {
- case SEC_SYMTAB:
- if (symbols.offset == 0)
- symbols = section.data;
-
- if (symbol_names.offset == 0)
- symbol_names = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
-
- printf("\n");
-
- for (i64 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_SPECIFIC: printf("\x1b[31mspec "); break;
- default: printf(" ");
- }
- printf("\x1b[37m");
- printf("\n");
- }
-
- printf("\n");
- break;
-
- case SEC_RELA: {
- if (symbol_names.offset == 0)
- symbol_names = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
- if (symbols.offset == 0)
- symbols = elf_find_section_by_name(buf, SECTION_SYMTAB, sizeof SECTION_SYMTAB - 1).data;
-
- Offset_Size dst = elf_find_related_data(buf, sec_index);
-
- printf("\n");
-
- for (i64 rela_index = 0; rela_index < section.num_entries; ++rela_index) {
- Rela_Entry rela = elf_rela(buf, symbols, symbol_names, section.data, dst, rela_index);
-
- printf(" %-16s", REL_NAMES[rela.type]);
- printf(
- " %08llx %-+5lld <= ",
- rela.dst,
- rela.addent
- );
- if (rela.symbol.bind == BIND_WEAK)
- printf("\x1b[33m");
- else
- printf("\x1b[32m");
- printf("%08llx", rela.symbol.value.offset);
- printf("\x1b[37m");
- if (rela.symbol.type == SYM_DATA ||
- rela.symbol.type == SYM_DATA_COMMON ||
- rela.symbol.type == SYM_DATA_THREAD_LOCAL)
- printf(" \x1b[34mdata");
- else if (rela.symbol.type == SYM_PROC)
- printf(" \x1b[34mproc");
- else if (rela.symbol.type == SYM_SECTION)
- printf(" \x1b[36msect");
- else if (rela.symbol.type == SYM_SPECIFIC)
- printf(" \x1b[34mspec");
- else
- printf(" \x1b[33mnone");
- printf("\x1b[37m");
- printf(" \"%s\"", elf_name_from_offset(buf, rela.symbol.name));
- printf("\n");
- }
-
- printf("\n");
- } break;
-
- case SEC_REL: {
- if (symbol_names.offset == 0)
- symbol_names = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
- if (symbols.offset == 0)
- symbols = elf_find_section_by_name(buf, SECTION_SYMTAB, sizeof SECTION_SYMTAB - 1).data;
-
- Offset_Size dst = elf_find_related_data(buf, sec_index);
-
- printf("\n");
-
- for (i64 rel_index = 0; rel_index < section.num_entries; ++rel_index) {
- Rel_Entry rel = elf_rel(buf, symbols, symbol_names, section.data, dst, rel_index);
-
- printf(" %-16s", REL_NAMES[rel.type]);
- printf(" %08llx <= ", rel.dst);
- if (rel.symbol.bind == BIND_WEAK)
- printf("\x1b[33m");
- else
- printf("\x1b[32m");
- printf("%08llx", rel.symbol.value.offset);
- printf("\x1b[37m");
- if (rel.symbol.type == SYM_DATA ||
- rel.symbol.type == SYM_DATA_COMMON ||
- rel.symbol.type == SYM_DATA_THREAD_LOCAL)
- printf(" \x1b[34mdata");
- else if (rel.symbol.type == SYM_PROC)
- printf(" \x1b[34mproc");
- else if (rel.symbol.type == SYM_SECTION)
- printf(" \x1b[36msect");
- else if (rel.symbol.type == SYM_SPECIFIC)
- printf(" \x1b[31mspec");
- else
- printf(" \x1b[33mnone");
- printf("\x1b[37m");
- printf(" \"%s\"", elf_name_from_offset(buf, rel.symbol.name));
- printf("\n");
- }
-
- printf("\n");
- } break;
-
- default:;
- }
- }
-
- printf("\n");
- }
- }
}
i64 io_open_read(i64 name_size, c8 *name, void *user_data) {
@@ -2348,6 +2404,8 @@ void bx_log(i32 log_level, u32 line, c8 *file, c8 *format, ...) {
message, len,
"................................................................",
file, line);
+ if (TRACE_BLOCKING)
+ wait_any_input();
break;
default:;
@@ -2485,7 +2543,7 @@ i64 n_call(i16 convention, i64 target_proc, i64 num_args, Var *args) {
}
i64 n_call_by_name(i16 convention, c8 *name, i64 num_args, Var *args) {
- return node_ctrl_call_by_name(&g_pool, convention, strlen(name), name, num_args, args);
+ return node_ctrl_call_by_name(&g_pool, convention, bx_str_len(name, name + MAX_NAME_SIZE), name, num_args, args);
}
i64 n_ret(i64 num_vals, Var *vals) {
@@ -2494,7 +2552,7 @@ i64 n_ret(i64 num_vals, Var *vals) {
i64 p_new(c8 *name) {
i64 p = proc_init(&g_pool);
- proc_set_name(&g_pool, p, strlen(name), name);
+ proc_set_name(&g_pool, p, bx_str_len(name, name + MAX_NAME_SIZE), name);
return p;
}
@@ -2515,7 +2573,7 @@ void u_entry_point(i64 unit, i64 proc) {
}
void u_elf_x86_64(i64 unit, c8 *output_file_name) {
- i64 out = io_open_write(strlen(output_file_name), output_file_name, NULL);
+ i64 out = io_open_write(bx_str_len(output_file_name, output_file_name + MAX_PATH_SIZE), output_file_name, NULL);
unit_write(&g_pool, unit, FORMAT_ELF | ARCH_X86_64, out, NULL);
@@ -2529,13 +2587,13 @@ void l_code(i64 unit, i64 link_unit) {
void l_object(i64 unit, c8 *object_library) {
i64 l = unit_init(&g_pool, UNIT_LIBRARY_OBJECT);
- unit_set_name(&g_pool, l, strlen(object_library), object_library);
+ unit_set_name(&g_pool, l, bx_str_len(object_library, object_library + MAX_PATH_SIZE), object_library);
unit_link_add(&g_pool, unit, l);
}
void l_static(i64 unit, c8 *static_library) {
i64 l = unit_init(&g_pool, UNIT_LIBRARY_STATIC);
- unit_set_name(&g_pool, l, strlen(static_library), static_library);
+ unit_set_name(&g_pool, l, bx_str_len(static_library, static_library + MAX_PATH_SIZE), static_library);
unit_link_add(&g_pool, unit, l);
}