From 7e3434b2a388862defb60256e53d4979bbb76d29 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Sat, 20 Jul 2024 14:02:56 +0200 Subject: Search symbols (incomplete) --- bxgen.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 190 insertions(+), 52 deletions(-) (limited to 'bxgen.c') 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 ) -- cgit v1.2.3