diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2024-08-01 02:25:22 +0200 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2024-08-01 02:25:22 +0200 |
commit | 7ee8702456a8f2dc4e04f48879eef42a26dbabe8 (patch) | |
tree | 9f3abf80d744702b2374ffa3923da9cdf0c75ce6 | |
parent | 15f6e03347418caf2fdd178480c84295d417bae0 (diff) | |
download | bxgen-7ee8702456a8f2dc4e04f48879eef42a26dbabe8.zip |
Add .got segment
-rwxr-xr-x | bxgen.c | 177 |
1 files changed, 120 insertions, 57 deletions
@@ -84,7 +84,8 @@ #/ #/ Bugs #/ -#/ - Segfault at 0x58fdf9 +#/ - Segfault at 0x58fe2d (after 0x401c3f, 0x58fe2d) +#/ - in 0x58fabc #/ #/ Done features #/ @@ -711,7 +712,7 @@ i64 bx_str_len_or(c8 *s, c8 *s_max, i64 or_val) { return or_val; } -c8 *bx_find_char(c8 *s, c8 *s_end, c8 c) { +c8 *find_char(c8 *s, c8 *s_end, c8 c) { CHECK(s != NULL, "Invalid arguments", NULL); CHECK(s_end != NULL, "Invalid arguments", NULL); @@ -721,7 +722,7 @@ c8 *bx_find_char(c8 *s, c8 *s_end, c8 c) { return *s == c ? s : NULL; } -c8 *bx_find_str(c8 *s, c8 *s_end, c8 *sub, c8 *sub_end) { +c8 *find_str(c8 *s, c8 *s_end, c8 *sub, c8 *sub_end) { CHECK(s != NULL, "Invalid arguments", NULL); CHECK(s_end != NULL, "Invalid arguments", NULL); CHECK(sub != NULL, "Invalid arguments", NULL); @@ -741,7 +742,7 @@ c8 *bx_find_str(c8 *s, c8 *s_end, c8 *sub, c8 *sub_end) { return NULL; } -c8 *bx_find_str_in_table(c8 *buf, c8 *buf_end, c8 *sub, c8 *sub_end) { +c8 *find_str_in_table(c8 *buf, c8 *buf_end, c8 *sub, c8 *sub_end) { CHECK(buf != NULL, "Invalid arguments", NULL); CHECK(buf_end != NULL, "Invalid arguments", NULL); CHECK(sub != NULL, "Invalid arguments", NULL); @@ -757,7 +758,7 @@ c8 *bx_find_str_in_table(c8 *buf, c8 *buf_end, c8 *sub, c8 *sub_end) { return NULL; } -u64 bx_u64_from_dec_str(c8 *s, c8 *s_end) { +u64 u64_from_dec_str(c8 *s, c8 *s_end) { CHECK(s != NULL && s_end != NULL, "Invalid arguments", 0); CHECK(s < s_end, "Buffer overflow", 0); CHECK(*s >= '0' && *s <= '9', "Parsing failed", 0); @@ -1548,6 +1549,7 @@ enum { ELF_SYMBOL_ENTRY_SIZE = 24, ELF_REL_ENTRY_SIZE = 16, ELF_RELA_ENTRY_SIZE = 24, + ELF_GOT_ENTRY_SIZE = 8, ELF_DYNAMIC_ENTRY_SIZE = 16, SEC_NONE = 0, @@ -1717,14 +1719,12 @@ c8 AR_MAGIC[8] = "!<arch>\n"; c8 AR_SYMBOL_TABLE[] = "/ "; c8 AR_STRING_TABLE[] = "// "; -c8 SECTION_TEXT[] = ".text"; -c8 SECTION_RELA_TEXT[] = ".rela.text"; -c8 SECTION_DATA[] = ".data"; -c8 SECTION_BSS[] = ".bss"; -c8 SECTION_RODATA[] = ".rodata"; -c8 SECTION_SYMTAB[] = ".symtab"; -c8 SECTION_STRTAB[] = ".strtab"; -c8 SECTION_SHSTRTAB[] = ".shstrtab"; +c8 SECTION_SYMTAB[] = ".symtab"; +c8 SECTION_STRTAB[] = ".strtab"; +c8 SECTION_GOT[] = ".got"; +c8 SECTION_PLT[] = ".plt"; +c8 SECTION_INIT[] = ".init"; +c8 SECTION_FINI[] = ".fini"; typedef struct { i64 offset; @@ -1760,6 +1760,7 @@ typedef struct { u8 bind; i64 section; Offset_Size value; + i64 _index; } Elf_Symbol_Entry; typedef struct { @@ -2437,6 +2438,7 @@ Elf_Symbol_Entry elf_symbol( .offset = sym_value, .size = sym_size, }, + ._index = symbol_index, }; } @@ -2657,7 +2659,7 @@ i64 unit_write_in_memory( emit_unit(pool, codegen, unit, arch); - u16 num_program_headers = 6; + u16 num_program_headers = 7; i64 program_offset = bx_align(ELF_HEADER_SIZE + ELF_PROGRAM_HEADER_SIZE * num_program_headers, X86_64_ALIGNMENT); i64 base_address = X86_64_BASE_ADDRESS; @@ -2670,7 +2672,8 @@ i64 unit_write_in_memory( i64 rw_zval_size = 0; i64 rw_data_size = 0; i64 ro_data_size = codegen->offset_ro_data; - i64 ro_dynamic_size = ELF_DYNAMIC_ENTRY_SIZE; + i64 rw_got_size = ELF_GOT_ENTRY_SIZE; + i64 rw_dynamic_size = ELF_DYNAMIC_ENTRY_SIZE; i64 num_sections_total = 0; i64 num_symbols = 0; @@ -2693,46 +2696,77 @@ i64 unit_write_in_memory( Elf_Section_Header section = elf_section(buf, sec_index); + c8 *name = elf_name_from_offset(buf, section.name); + + if (section.type == SEC_PROGBITS && section.name.size == sizeof SECTION_GOT - 1 && mem_eq(name, SECTION_GOT, sizeof SECTION_GOT - 1)) { + FAIL("Not implemented", 0); + } + + if (section.type == SEC_PROGBITS && section.name.size == sizeof SECTION_PLT - 1 && mem_eq(name, SECTION_PLT, sizeof SECTION_PLT - 1)) { + FAIL("Not implemented", 0); + } + if (!section.alloc || section.data.size == 0) continue; + if (section.type == SEC_DYNAMIC) { + FAIL("Not implemented", 0); + } + + if (section.type == SEC_PROGBITS && section.exec && section.name.size == sizeof SECTION_INIT - 1 && mem_eq(name, SECTION_INIT, sizeof SECTION_INIT - 1)) { + FAIL("Not implemented", 0); + } + + if (section.type == SEC_PROGBITS && section.exec && section.name.size == sizeof SECTION_FINI - 1 && mem_eq(name, SECTION_FINI, sizeof SECTION_FINI - 1)) { + FAIL("Not implemented", 0); + } + if (section.exec) { + CHECK(!section.write, "Not implemented", 0); + linker->section_offsets[num_sections_total] = rx_code_size; linker->section_addresses[num_sections_total] = rx_code_size; rx_code_size += bx_align(section.data.size, X86_64_ALIGNMENT); - } else if (section.write && section.type == SEC_NOBITS) { + continue; + } + + if (section.write && section.type == SEC_NOBITS) { linker->section_addresses[num_sections_total] = rw_zval_size; rw_zval_size += bx_align(section.data.size, X86_64_ALIGNMENT); - } else if (section.write) { + continue; + } + + if (section.write) { linker->section_offsets[num_sections_total] = rw_data_size; linker->section_addresses[num_sections_total] = rw_data_size; rw_data_size += bx_align(section.data.size, X86_64_ALIGNMENT); - } else if (section.data.size > 0) { - linker->section_offsets[num_sections_total] = ro_data_size; - linker->section_addresses[num_sections_total] = ro_data_size; - ro_data_size += bx_align(section.data.size, X86_64_ALIGNMENT); - } else { - LAX(0, "Unsupported section type"); continue; } + + linker->section_offsets[num_sections_total] = ro_data_size; + linker->section_addresses[num_sections_total] = ro_data_size; + ro_data_size += bx_align(section.data.size, X86_64_ALIGNMENT); } } - rx_code_size = bx_align(rx_code_size, X86_64_PAGE_SIZE); - rw_zval_size = bx_align(rw_zval_size, X86_64_PAGE_SIZE); - rw_data_size = bx_align(rw_data_size, X86_64_PAGE_SIZE); - ro_data_size = bx_align(ro_data_size, X86_64_PAGE_SIZE); - ro_dynamic_size = bx_align(ro_dynamic_size, X86_64_PAGE_SIZE); + rx_code_size = bx_align(rx_code_size, X86_64_PAGE_SIZE); + rw_zval_size = bx_align(rw_zval_size, X86_64_PAGE_SIZE); + rw_data_size = bx_align(rw_data_size, X86_64_PAGE_SIZE); + ro_data_size = bx_align(ro_data_size, X86_64_PAGE_SIZE); + rw_got_size = bx_align(rw_got_size, X86_64_PAGE_SIZE); + rw_dynamic_size = bx_align(rw_dynamic_size, X86_64_PAGE_SIZE); i64 rw_zval_address = rx_code_address + rx_code_size; i64 rw_data_address = rw_zval_address + rw_zval_size; i64 ro_data_address = rw_data_address + rw_data_size; - i64 ro_dynamic_address = ro_data_address + ro_data_size; + i64 rw_got_address = ro_data_address + ro_data_size; + i64 rw_dynamic_address = rw_got_address + rw_got_size; i64 rx_code_offset = program_offset; i64 rw_data_offset = rx_code_offset + rx_code_size; i64 ro_data_offset = rw_data_offset + rw_data_size; - i64 ro_dynamic_offset = ro_data_offset + ro_data_size; + i64 rw_got_offset = ro_data_offset + ro_data_size; + i64 rw_dynamic_offset = rw_got_offset + rw_got_size; for (i64 elf_index = 0, sec_index_global = 0; elf_index < linker->num_obj_files; ++elf_index) { Buffer_Context buf = elf_buffer_context(pool, linker, linker->num_obj_files, elf_index); @@ -2819,6 +2853,7 @@ i64 unit_write_in_memory( // // TODO Add runtime library symbols // + // __ehdr_start // _GLOBAL_OFFSET_TABLE_ // _DYNAMIC // @@ -2832,7 +2867,6 @@ i64 unit_write_in_memory( // _fini // _end // _dl_rtld_map - // __ehdr_start // __pthread_initialize_minimal // __init_array_start // __init_array_end @@ -2872,12 +2906,21 @@ i64 unit_write_in_memory( .size = ELF_HEADER_SIZE, }; + // Add the dummy _GLOBAL_OFFSET_TABLE_ segment + + linker->symbols[num_symbols++] = (Symbol_Entry) { + .name_size = 21, + .name = "_GLOBAL_OFFSET_TABLE_", + .address = rw_got_address, + .size = ELF_GOT_ENTRY_SIZE, + }; + // Add the dummy _DYNAMIC segment linker->symbols[num_symbols++] = (Symbol_Entry) { .name_size = 8, .name = "_DYNAMIC", - .address = ro_dynamic_address, + .address = rw_dynamic_address, .size = ELF_DYNAMIC_ENTRY_SIZE, }; @@ -2920,7 +2963,7 @@ i64 unit_write_in_memory( break; } if (symbol.address == 0 && - bx_find_str_in_table( + find_str_in_table( linker->not_found_buffer, linker->not_found_buffer + not_found_size, sym_name, @@ -2961,13 +3004,13 @@ i64 unit_write_in_memory( i64 Z = symbol.size; // Represents the address of the global offset table. - i64 GOT = S; + i64 GOT = rw_got_address; // Represents the offset into the global offset table at which the relocation entry's symbol will reside during execution. - i64 G = 0; + i64 G = 8; // TODO // Represents the place (section offset or address) of the Procedure Linkage Table entry for a symbol. - i64 L = S; + i64 L = S; // TODO // if (S == 0x5a2478 || S + A == 0x5a2478) { // LOG(VERBOSE, "%s: type %d, S=0x%llx, A=0x%llx, P=0x%llx", sym_name, relx.type, S, A, P); @@ -2975,6 +3018,10 @@ i64 unit_write_in_memory( // } // LOG(VERBOSE, "--"); + // if (S + A == 0x58fa84) { + // LOG(TRACE, "Symbol: %s, Obj: %lld, Section: %lld, Index: %lld", sym_name, elf_index, relx.symbol.section, relx.symbol._index); + // } + switch (relx.type) { #define SKIP_(x) \ if (relx.symbol.name.size == sizeof(#x) - 1 && \ @@ -3164,7 +3211,8 @@ i64 unit_write_in_memory( + rw_zval_size + rw_data_size + ro_data_size - + ro_dynamic_size, + + rw_got_size + + rw_dynamic_size, X86_64_ALIGNMENT); CHECK(output_size <= linker->max_output_size, "Out of memory",); @@ -3177,7 +3225,8 @@ i64 unit_write_in_memory( LOG(VERBOSE, "r/w zval - %7lld bytes", rw_zval_size); LOG(VERBOSE, "r/w data - %7lld bytes", rw_data_size); LOG(VERBOSE, "r/o data - %7lld bytes", ro_data_size); - LOG(VERBOSE, "r/o dynamic - %7lld bytes", ro_dynamic_size); + LOG(VERBOSE, "r/w GOT - %7lld bytes", rw_got_size); + LOG(VERBOSE, "r/w dynamic - %7lld bytes", rw_dynamic_size); LOG(VERBOSE, "Writing ELF x86_64 executable"); @@ -3213,10 +3262,11 @@ i64 unit_write_in_memory( // Program headers // - CHECK(rx_code_offset % X86_64_PAGE_SIZE == rx_code_address % X86_64_PAGE_SIZE, "Invalid alignment",); - CHECK(rw_data_offset % X86_64_PAGE_SIZE == rw_data_address % X86_64_PAGE_SIZE, "Invalid alignment",); - CHECK(ro_data_offset % X86_64_PAGE_SIZE == ro_data_address % X86_64_PAGE_SIZE, "Invalid alignment",); - CHECK(ro_dynamic_offset % X86_64_PAGE_SIZE == ro_dynamic_offset % X86_64_PAGE_SIZE, "Invalid alignemtn",); + CHECK(rx_code_offset % X86_64_PAGE_SIZE == rx_code_address % X86_64_PAGE_SIZE, "Invalid alignment",); + CHECK(rw_data_offset % X86_64_PAGE_SIZE == rw_data_address % X86_64_PAGE_SIZE, "Invalid alignment",); + CHECK(ro_data_offset % X86_64_PAGE_SIZE == ro_data_address % X86_64_PAGE_SIZE, "Invalid alignment",); + CHECK(rw_got_offset % X86_64_PAGE_SIZE == rw_got_address % X86_64_PAGE_SIZE, "Invalid alignemtn",); + CHECK(rw_dynamic_offset % X86_64_PAGE_SIZE == rw_dynamic_address % X86_64_PAGE_SIZE, "Invalid alignemtn",); // r/o elf header u8 *h = o + ELF_HEADER_SIZE; @@ -3274,14 +3324,25 @@ i64 unit_write_in_memory( write_i64(LE, X86_64_ALIGNMENT, h + 48, o_end); h += ELF_PROGRAM_HEADER_SIZE; - // r/o dynamic - write_u32(LE, 1, h, o_end); // type (PT_LOAD) - write_u32(LE, 4, h + 4, o_end); // flags (PF_R) - write_i64(LE, ro_dynamic_offset, h + 8, o_end); - write_i64(LE, ro_dynamic_address, h + 16, o_end); // virtual address - write_i64(LE, ro_dynamic_address, h + 24, o_end); // phisical address - write_i64(LE, ro_dynamic_size, h + 32, o_end); // size in file - write_i64(LE, ro_dynamic_size, h + 40, o_end); // size in memory + // r/w GOT + write_u32(LE, 1, h, o_end); // type (PT_LOAD) + write_u32(LE, 6, h + 4, o_end); // flags (PF_R | PF_W) + write_i64(LE, rw_got_offset, h + 8, o_end); + write_i64(LE, rw_got_address, h + 16, o_end); // virtual address + write_i64(LE, rw_got_address, h + 24, o_end); // phisical address + write_i64(LE, rw_got_size, h + 32, o_end); // size in file + write_i64(LE, rw_got_size, h + 40, o_end); // size in memory + write_i64(LE, X86_64_ALIGNMENT, h + 48, o_end); + h += ELF_PROGRAM_HEADER_SIZE; + + // r/w dynamic + write_u32(LE, 2, h, o_end); // type (PT_DYNAMIC) + write_u32(LE, 6, h + 4, o_end); // flags (PF_R | PF_W) + write_i64(LE, rw_dynamic_offset, h + 8, o_end); + write_i64(LE, rw_dynamic_address, h + 16, o_end); // virtual address + write_i64(LE, rw_dynamic_address, h + 24, o_end); // phisical address + write_i64(LE, rw_dynamic_size, h + 32, o_end); // size in file + write_i64(LE, rw_dynamic_size, h + 40, o_end); // size in memory write_i64(LE, X86_64_ALIGNMENT, h + 48, o_end); h += ELF_PROGRAM_HEADER_SIZE; @@ -3316,6 +3377,10 @@ i64 unit_write_in_memory( } } + // GOT + + write_u64(LE, rw_dynamic_address, o + rw_got_offset, o_end); + // ============================================================== return output_size; @@ -3378,21 +3443,21 @@ void unit_write( u8 *f_end = f_begin + 58; u8 *f_data = f_begin + 60; - i64 size = (i64) bx_u64_from_dec_str((c8 *) f_size, (c8 *) f_size + 10); + i64 size = (i64) u64_from_dec_str((c8 *) f_size, (c8 *) f_size + 10); size = bx_align(size, 2); CHECK(mem_eq(f_end, "\x60\x0a", 2), "Invalid AR file",); - CHECK(f_begin + size <= ar_end, "Buffer overflow",); + CHECK(f_begin + size <= ar_end, "Buffer overflow",); - if (!mem_eq(f_id, AR_SYMBOL_TABLE, 16) && - !mem_eq(f_id, AR_STRING_TABLE, 16)) { + if (!mem_eq(f_id, AR_SYMBOL_TABLE, sizeof AR_SYMBOL_TABLE - 1) && + !mem_eq(f_id, AR_STRING_TABLE, sizeof AR_STRING_TABLE - 1)) { // Read ELF object file i64 delta_size = bx_align(size, X86_64_ALIGNMENT); CHECK(obj_files_size + delta_size < linker->max_dependencies_size, "Out of memory",); - CHECK(linker->num_obj_files + 1 < linker->max_num_obj_files, "Out of memory",); + CHECK(linker->num_obj_files + 1 < linker->max_num_obj_files, "Out of memory",); mem_cpy(linker->dependencies_buffer + obj_files_size, f_data, size); @@ -3949,8 +4014,6 @@ b8 link_with_libc(void) { i32 main(i32 argc, c8 **argv) { LOG(INFO, "bxgen " VERSION); - i32 status = 0; - i32 num_tests = 0; i32 num_passed = 0; |