summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-07-20 14:02:56 +0200
committerMitya Selivanov <automainint@guattari.tech>2024-07-20 14:02:56 +0200
commit7e3434b2a388862defb60256e53d4979bbb76d29 (patch)
tree4235767fbfeaea8a0c1997a082bba1272b54c41a
parent779364a0d5ef25fc20ee34d0ee4ffe8be3876fbc (diff)
downloadbxgen-7e3434b2a388862defb60256e53d4979bbb76d29.zip
Search symbols (incomplete)
-rwxr-xr-xbxgen.c242
1 files changed, 190 insertions, 52 deletions
diff --git a/bxgen.c b/bxgen.c
index 7bfd9dc..f6ad60b 100755
--- a/bxgen.c
+++ b/bxgen.c
@@ -80,7 +80,8 @@ gcc \
-Wall -Wextra -Werror -pedantic \
-O0 -fsanitize=undefined,address,leak -mshstk \
-o $BIN $SRC && \
- ./$BIN $@
+ ./$BIN $@ && \
+ rm $BIN
exit $? # */
#endif
// ================================================================
@@ -106,7 +107,7 @@ exit $? # */
#endif
#ifndef LOG_BLOCKING
-#define LOG_BLOCKING 1
+#define LOG_BLOCKING 0
#endif
#ifndef TRACE_BLOCKING
@@ -1162,7 +1163,8 @@ f64 read_f64(u32 ordering, void *v, void *v_end) {
if ((ordering & F64_DWORD_ORDER_MASK) != host_f64_dword_order())
x = ((x & 0xffffffffull) << 32) | ((x >> 32) & 0xffffffffull);
- return *(f64 *) &x;
+ void *p = &x;
+ return *(f64 *) p;
}
void write_i16(u32 ordering, i16 x, void *v, void *v_end) {
@@ -1179,15 +1181,17 @@ void write_i64(u32 ordering, i64 x, void *v, void *v_end) {
void write_f32(u32 ordering, f32 x, void *v, void *v_end) {
host_f64_dword_order(); // FIXME
- write_u32(ordering, *(u32 *) &x, v, v_end);
+ void *p = &x;
+ write_u32(ordering, *(u32 *) p, v, v_end);
}
void write_f64(u32 ordering, f64 x, void *v, void *v_end) {
+ void *p = &x;
if ((ordering & F64_DWORD_ORDER_MASK) == host_f64_dword_order())
- write_u64(ordering, *(u64 *) &x, v, v_end);
+ write_u64(ordering, *(u64 *) p, v, v_end);
else {
- write_u32(ordering, *(((u32 *) &x) + 1), (u8 *) v, v_end);
- write_u32(ordering, * (u32 *) &x, ((u8 *) v) + 4, v_end);
+ write_u32(ordering, *(((u32 *) p) + 1), (u8 *) v, v_end);
+ write_u32(ordering, * (u32 *) p, ((u8 *) v) + 4, v_end);
}
}
@@ -1377,6 +1381,22 @@ c8 *SEC_TYPE_NAMES[] = {
[SEC_SYMTAB_SHNDX] = "symtab shndx",
};
+c8 *SYM_TYPE_NAMES[] = {
+ [SYM_NONE] = "none",
+ [SYM_PROC] = "proc",
+ [SYM_DATA] = "data",
+ [SYM_COMMON] = "common",
+ [SYM_TLS] = "tls",
+ [SYM_SECTION] = "section",
+ [SYM_SPECIFIC] = "spec",
+};
+
+c8 *BIND_TYPE_NAMES[] = {
+ [BIND_LOCAL] = "local",
+ [BIND_GLOBAL] = "global",
+ [BIND_WEAK] = "weak",
+};
+
c8 *REL_NAMES[] = {
[R_X86_64_NONE] = "none",
[R_X86_64_64] = "64",
@@ -1862,22 +1882,6 @@ void elf_checks(Buffer_Context b) {
BX_LAX( read_u16(LE, begin + 58, end) == ELF_SECTION_HEADER_SIZE, "Invalid section header size");
}
-void elf_relocate_symbols(
- Buffer_Context b,
- Section_Header symtab,
- i64 sec_index,
- i64 dst_address
-) {
- u8 *begin = b.begin + symtab.data.offset;
- u8 *end = begin + symtab.data.size;
-
- for (i64 i = 0; i < symtab.num_entries; ++i) {
- u8 *sym_begin = begin + i * ELF_SYMBOL_ENTRY_SIZE;
- if ((i64) read_u16(LE, sym_begin + 6, end) == sec_index)
- write_i64(LE, dst_address + read_i64(LE, sym_begin + 8, end), sym_begin + 8, end);
- }
-}
-
void elf_apply_relocations(
Buffer_Context b,
i64 sec_index,
@@ -1891,7 +1895,7 @@ void elf_dump(u32 log_level, Buffer_Context b) {
Offset_Size strtab = elf_find_section_by_name(b, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
Offset_Size symtab = elf_find_section_by_name(b, SECTION_SYMTAB, sizeof SECTION_SYMTAB - 1).data;
- for (i64 sec_index = 0; sec_index < headers.num; ++sec_index) {
+ for (i64 sec_index = 1; sec_index < headers.num; ++sec_index) {
Section_Header section = elf_section(b, sec_index);
c8 *name = elf_name_from_offset(b, section.name);
@@ -1921,7 +1925,7 @@ void elf_dump(u32 log_level, Buffer_Context b) {
case SEC_SYMTAB:
BX_LOG(log_level, " - -");
- for (i64 sym_index = 0; sym_index < section.num_entries; ++sym_index) {
+ for (i64 sym_index = 1; sym_index < section.num_entries; ++sym_index) {
Symbol_Entry sym = elf_symbol(b, section.data, strtab, (u16) sym_index);
c8 *name = elf_name_from_offset(b, sym.name);
@@ -1930,7 +1934,7 @@ void elf_dump(u32 log_level, Buffer_Context b) {
BX_LOG(
log_level,
- " %s%s%s\x1b[37m%s %.*s %s\x1b[37m",
+ " %s%s%s\x1b[37m%s %.*s %s%-7s %s\x1b[37m",
*name != '\0' ? "\"" : "",
sym.bind == BIND_GLOBAL ? "\x1b[32m" :
sym.bind == BIND_WEAK ? "\x1b[35m" :
@@ -1939,13 +1943,17 @@ void elf_dump(u32 log_level, Buffer_Context b) {
*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 " :
- " "
+ sym.type == SYM_PROC ? "\x1b[32m" :
+ sym.type == SYM_DATA ? "\x1b[32m" :
+ sym.type == SYM_COMMON ? "\x1b[33m" :
+ sym.type == SYM_TLS ? "\x1b[35m" :
+ sym.type == SYM_SECTION ? "\x1b[31m" :
+ sym.type == SYM_SPECIFIC ? "\x1b[31m" :
+ "",
+ SYM_TYPE_NAMES[sym.type],
+ sym.section == 0 ? (
+ sym.bind == BIND_GLOBAL || sym.bind == BIND_WEAK ?
+ "\x1b[33mundefined" : "\x1b[31mundefined") : ""
);
}
@@ -2134,7 +2142,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
// ==========================================================
//
- // Calculate section offsets, relocate symbols
+ // Calculate section offsets
i64 sec_index_global = 0;
@@ -2144,10 +2152,9 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
elf_checks(buf);
elf_dump(VERBOSE, buf);
- Offset_Num headers = elf_section_headers(buf);
- Section_Header symtab = elf_find_section_by_name(buf, SECTION_SYMTAB, sizeof SECTION_SYMTAB - 1);
+ Offset_Num headers = elf_section_headers(buf);
- for (i64 sec_index = 0; sec_index < headers.num; ++sec_index, ++sec_index_global) {
+ for (i64 sec_index = 1; sec_index < headers.num; ++sec_index, ++sec_index_global) {
pool->section_offsets[sec_index_global] = 0;
Section_Header section = elf_section(buf, sec_index);
@@ -2171,9 +2178,132 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
BX_LAX(0, "Unsupported section type");
continue;
}
+ }
+ }
+
+ // ==========================================================
+ //
+ // Relocate defined symbols
+
+ sec_index_global = 0;
- elf_relocate_symbols(buf, symtab, sec_index, base_address + data_offset + pool->section_offsets[sec_index_global]);
+ for (i64 elf_index = 0; elf_index < num_obj_files; ++elf_index) {
+ Buffer_Context buf = elf_buffer_context(pool, num_obj_files, elf_index);
+
+ Offset_Num headers = elf_section_headers(buf);
+ Offset_Size strtab = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
+
+ for (i64 sec_index = 1; sec_index < headers.num; ++sec_index) {
+ Section_Header tab = elf_section(buf, sec_index);
+ if (tab.type != SEC_SYMTAB)
+ continue;
+
+ for (i64 sym_index = 1; sym_index < tab.num_entries; ++sym_index) {
+ Symbol_Entry sym = elf_symbol(buf, tab.data, strtab, sym_index);
+ c8 * sym_name = elf_name_from_offset(buf, sym.name);
+
+ if (sym.section == 0)
+ continue;
+
+ i64 sec_index = sec_index_global + sym.section - 1;
+
+ u8 *begin = buf.begin + tab.data.offset + sym_index * ELF_SYMBOL_ENTRY_SIZE;
+ u8 *end = begin + tab.data.size;
+
+ write_i64(LE, pool->section_offsets[sec_index] + sym.value.offset, begin + 8, end);
+ }
}
+
+ sec_index_global += elf_section_headers(buf).num - 1;
+ }
+
+ // ==========================================================
+ //
+ // Resolve undefined symbols
+ //if (0)
+ {
+ sec_index_global = 0;
+
+ for (i64 elf_index = 0; elf_index < num_obj_files; ++elf_index) {
+ Buffer_Context buf = elf_buffer_context(pool, num_obj_files, elf_index);
+
+ i64 num_sections = elf_section_headers(buf).num;
+ Offset_Size strtab = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
+
+ for (i64 sec_index = 1; sec_index < num_sections; ++sec_index) {
+ Section_Header tab = elf_section(buf, sec_index);
+ if (tab.type != SEC_SYMTAB)
+ continue;
+
+ for (i64 sym_index = 1; sym_index < tab.num_entries; ++sym_index) {
+ Symbol_Entry sym = elf_symbol(buf, tab.data, strtab, sym_index);
+ c8 * sym_name = elf_name_from_offset(buf, sym.name);
+
+ if (sym.section != 0 ||
+ sym.bind == BIND_LOCAL)
+ continue;
+
+ // Global search for the symbol
+ //
+
+ i64 sec_index = 0;
+ i64 offset = 0;
+ b8 found = 0;
+
+ for (i64 search_index = 0; search_index < num_obj_files; ++search_index) {
+ Buffer_Context search_buf = elf_buffer_context(pool, num_obj_files, search_index);
+
+ Offset_Size search_strtab = elf_find_section_by_name(search_buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
+
+ i64 search_num_sections = elf_section_headers(search_buf).num;
+
+ for (i64 search_sec = 1; search_sec < search_num_sections; ++search_sec) {
+ Section_Header search_symtab = elf_section(search_buf, search_sec);
+ if (search_symtab.type != SEC_SYMTAB)
+ continue;
+
+ for (i64 k = 1; k < search_symtab.num_entries; ++k) {
+ Symbol_Entry search_sym = elf_symbol(search_buf, search_symtab.data, search_strtab, k);
+
+ if (search_sym.bind == BIND_LOCAL ||
+ search_sym.section == 0 ||
+ search_sym.name.size != sym.name.size)
+ continue;
+
+ c8 *search_name = elf_name_from_offset(search_buf, search_sym.name);
+
+ if (!bx_mem_eq(sym_name, search_name, sym.name.size))
+ continue;
+
+ sec_index += search_sym.section - 1;
+ offset = search_sym.value.offset;
+ found = 1;
+ break;
+ }
+
+ if (found == 1)
+ break;
+ }
+
+ if (found == 1)
+ break;
+
+ sec_index += elf_section_headers(search_buf).num - 1;
+ }
+
+ if (!found)
+ BX_LOG(ERROR, "Symbol not found: %s", sym_name);
+ else {
+ u8 *begin = buf.begin + tab.data.offset + sym_index * ELF_SYMBOL_ENTRY_SIZE;
+ u8 *end = begin + tab.data.size;
+
+ write_i64(LE, pool->section_offsets[sec_index] + sym.value.offset, begin + 8, end);
+ }
+ }
+ }
+
+ sec_index_global += elf_section_headers(buf).num - 1;
+ }
}
// ==============================================================
@@ -2188,9 +2318,9 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
elf_checks(buf);
elf_dump(VERBOSE, buf);
- Offset_Num headers = elf_section_headers(buf);
+ Offset_Num headers = elf_section_headers(buf);
- for (i64 sec_index = 0; sec_index < headers.num; ++sec_index, ++sec_index_global)
+ for (i64 sec_index = 1; sec_index < headers.num; ++sec_index, ++sec_index_global)
if (elf_section(buf, sec_index).alloc)
elf_apply_relocations(buf, sec_index, base_address + pool->section_offsets[sec_index_global]);
}
@@ -2202,22 +2332,29 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
for (i64 elf_index = 0; elf_index < num_obj_files; ++elf_index) {
Buffer_Context buf = elf_buffer_context(pool, num_obj_files, elf_index);
- Offset_Num headers = elf_section_headers(buf);
Offset_Size strtab = elf_find_section_by_name(buf, SECTION_STRTAB, sizeof SECTION_STRTAB - 1).data;
- for (i64 sec_index = 0; sec_index < headers.num; ++sec_index) {
- Section_Header section = elf_section(buf, sec_index);
-
- if (section.type == SEC_SYMTAB)
- for (i64 sym_index = 0; sym_index < section.num_entries; ++sym_index) {
- Symbol_Entry sym = elf_symbol(buf, section.data, strtab, (u16) sym_index);
+ i64 num_sections = elf_section_headers(buf).num;
- 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;
- }
+ for (i64 sec_index = 1; sec_index < num_sections; ++sec_index) {
+ Section_Header section = elf_section(buf, sec_index);
+ if (section.type != SEC_SYMTAB)
+ continue;
+
+ for (i64 sym_index = 1; sym_index < section.num_entries; ++sym_index) {
+ Symbol_Entry sym = elf_symbol(buf, section.data, strtab, (u16) sym_index);
+
+ if (sym.bind == BIND_LOCAL ||
+ sym.section == 0 ||
+ sym.name.size != 6)
+ continue;
+
+ if (bx_mem_eq(elf_name_from_offset(buf, sym.name), "printf", 6)) {
+ if (sym_printf.section != 0)
+ BX_LAX(0, "Symbol redefinition");
+ sym_printf = sym;
}
+ }
}
}
@@ -2237,6 +2374,7 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data
BX_LOG(VERBOSE, "");
+ BX_CHECK(sym_printf.section != 0, "Symbol not found: printf",);
BX_LOG(VERBOSE, "Found printf: %08llx", sym_printf.value.offset);
#define WRITE(x, n) io_write( io_out, n, x, io_user_data )