summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-08-01 02:25:22 +0200
committerMitya Selivanov <automainint@guattari.tech>2024-08-01 02:25:22 +0200
commit7ee8702456a8f2dc4e04f48879eef42a26dbabe8 (patch)
tree9f3abf80d744702b2374ffa3923da9cdf0c75ce6
parent15f6e03347418caf2fdd178480c84295d417bae0 (diff)
downloadbxgen-7ee8702456a8f2dc4e04f48879eef42a26dbabe8.zip
Add .got segment
-rwxr-xr-xbxgen.c177
1 files changed, 120 insertions, 57 deletions
diff --git a/bxgen.c b/bxgen.c
index c5c5884..d0805f9 100755
--- a/bxgen.c
+++ b/bxgen.c
@@ -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;