From 6a213202a41d744464ba7f19ce4781beb3e8fef8 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Wed, 24 Jul 2024 15:53:02 +0200 Subject: Relocations --- bxgen.c | 262 +++++++++++++++++++++++----------------------------------------- 1 file changed, 94 insertions(+), 168 deletions(-) (limited to 'bxgen.c') diff --git a/bxgen.c b/bxgen.c index db0a693..bf0eda7 100755 --- a/bxgen.c +++ b/bxgen.c @@ -1230,6 +1230,10 @@ void write_u64(u32 ordering, u64 x, u8 *v, u8 *v_end) { } } +i16 read_i8(u32 ordering, void *v, void *v_end) { + return (i8) read_u8(ordering, v, v_end); +} + i16 read_i16(u32 ordering, void *v, void *v_end) { return (i16) read_u16(ordering, v, v_end); } @@ -1257,6 +1261,10 @@ f64 read_f64(u32 ordering, void *v, void *v_end) { return *(f64 *) p; } +void write_i8(u32 ordering, i8 x, void *v, void *v_end) { + write_u8(ordering, (u8) x, v, v_end); +} + void write_i16(u32 ordering, i16 x, void *v, void *v_end) { write_u16(ordering, (u16) x, v, v_end); } @@ -1583,7 +1591,7 @@ typedef struct { typedef struct { Symbol_Entry symbol; - i64 dst; + i64 offset; u32 type; i64 addent; } Relx_Entry; @@ -1869,7 +1877,6 @@ Relx_Entry elf_rel( Offset_Size symbol_table, Offset_Size string_table, Offset_Size relocations, - Offset_Size dst, i64 rel_index ) { u8 *begin = b.begin + relocations.offset + rel_index * ELF_REL_ENTRY_SIZE; @@ -1883,11 +1890,9 @@ Relx_Entry elf_rel( u32 rel_type = read_u32(LE, begin + 8, end); i64 rel_sym = (i64) read_u32(LE, begin + 12, end); - BX_CHECK(rel_offset < dst.size, "Buffer overflow", (Rel_Entry) {0}); - return (Relx_Entry) { .symbol = elf_symbol(b, symbol_table, string_table, rel_sym), - .dst = dst.offset + rel_offset, + .offset = rel_offset, .type = rel_type, .addent = 0, }; @@ -1898,7 +1903,6 @@ Relx_Entry elf_rela( Offset_Size symbol_table, Offset_Size string_table, Offset_Size relocations, - Offset_Size dst, i64 rela_index ) { u8 *begin = b.begin + relocations.offset + rela_index * ELF_RELA_ENTRY_SIZE; @@ -1913,11 +1917,9 @@ Relx_Entry elf_rela( i64 rela_sym = (i64) read_u32(LE, begin + 12, end); i64 rela_addent = read_i64(LE, begin + 16, end); - BX_CHECK(rela_offset < dst.size, "Buffer overflow", (Rel_Entry) {0}); - return (Relx_Entry) { .symbol = elf_symbol(b, symbol_table, string_table, rela_sym), - .dst = dst.offset + rela_offset, + .offset = rela_offset, .type = rela_type, .addent = rela_addent, }; @@ -2045,18 +2047,16 @@ void elf_dump(u32 log_level, Buffer_Context b) { break; case SEC_RELA: { - 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) { - Relx_Entry relx = elf_rela(b, symtab, strtab, section.data, dst, rela_index); + Relx_Entry relx = elf_rela(b, symtab, strtab, section.data, rela_index); BX_LOG( log_level, " %-16s %08llx %-+5lld <= %s%08llx\x1b[37m%s\x1b[37m \"%s\"", REL_NAMES[relx.type], - relx.dst, + relx.offset, relx.addent, relx.symbol.bind == BIND_WEAK ? "\x1b[33m" : "\x1b[32m", relx.symbol.value.offset + elf_section(b, relx.symbol.section).data.offset, @@ -2075,18 +2075,16 @@ void elf_dump(u32 log_level, Buffer_Context b) { } break; case SEC_REL: { - 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) { - Relx_Entry relx = elf_rel(b, symtab, strtab, section.data, dst, rel_index); + Relx_Entry relx = elf_rel(b, symtab, strtab, section.data, rel_index); BX_LOG( log_level, " %-16s %08llx <= %s%08llx\x1b[37m%s\x1b[37m \"%s\"", REL_NAMES[relx.type], - relx.dst, + relx.offset, relx.symbol.bind == BIND_WEAK ? "\x1b[33m" : "\x1b[32m", relx.symbol.value.offset + elf_section(b, relx.symbol.section).data.offset, relx.symbol.type == SYM_DATA ? " \x1b[34mdata" : @@ -2383,15 +2381,14 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data if (src_sec.type != SEC_REL && src_sec.type != SEC_RELA) continue; - i64 dst_index = elf_find_related_section_index(buf, sec_index); - Offset_Size dst = elf_section(buf, dst_index).data; + i64 dst_index = elf_find_related_section_index(buf, sec_index); BX_CHECK(dst_index >= 0 && dst_index < pool->max_num_sections, "Buffer overflow",); for (i64 entry_index = 0; entry_index < src_sec.num_entries; ++entry_index) { Relx_Entry relx = (src_sec.type == SEC_REL) ? - elf_rel (buf, symtab, strtab, src_sec.data, dst, entry_index) : - elf_rela(buf, symtab, strtab, src_sec.data, dst, entry_index); + elf_rel (buf, symtab, strtab, src_sec.data, entry_index) : + elf_rela(buf, symtab, strtab, src_sec.data, entry_index); c8 *sym_name = elf_name_from_offset(buf, relx.symbol.name); @@ -2399,11 +2396,22 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data if (relx.symbol.section == 0) { for (i64 i = 0; i < num_symbols; ++i) - if (pool->symbols[i].name_size == relx.symbol.name.size && bx_mem_eq(pool->symbols[i].name, sym_name, relx.symbol.name.size)) { + if (pool->symbols[i].name_size == relx.symbol.name.size && + bx_mem_eq( + pool->symbols[i].name, + sym_name, + relx.symbol.name.size + )) { symbol = pool->symbols[i]; break; } - if (symbol.name_size == 0 && bx_find_str_in_table(pool->not_found_buffer, pool->not_found_buffer + not_found_size, sym_name, sym_name + relx.symbol.name.size) == NULL) { + if (symbol.name_size == 0 && + bx_find_str_in_table( + pool->not_found_buffer, + pool->not_found_buffer + not_found_size, + sym_name, + sym_name + relx.symbol.name.size + ) == NULL) { BX_LOG(WARNING, "Symbol not found: %s", sym_name); BX_CHECK(not_found_size + relx.symbol.name.size + 1 <= pool->max_not_found_size, "Out of memory",); bx_mem_cpy(pool->not_found_buffer + not_found_size, sym_name, relx.symbol.name.size); @@ -2415,152 +2423,70 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data .address = relx.symbol.value.offset, }; + i64 A = relx.addent; // Represents the addend used to compute the value of the relocatable field. + i64 B = pool->section_addresses[dst_index]; // Represents the base address at which a shared object has been loaded into memory during execution. Generally, a shared object is built with a 0 base virtual address, but the execution address will be different. + i64 G = symbol.address - base_address - data_offset; // Represents the offset into the global offset table at which the relocation entry's symbol will reside during execution. + i64 GOT = base_address + data_offset; // Represents the address of the global offset table. + i64 L = base_address + data_offset; // Represents the place (section offset or address) of the Procedure Linkage Table entry for a symbol. + i64 P = pool->section_addresses[dst_index] + relx.offset; // Represents the place (section offset or address) of the storage unit being relocated (computed using r_offset). + i64 S = symbol.address; // Represents the value of the symbol whose index resides in the relocation entry. + + u8 *dst = buf.begin + elf_section(buf, dst_index).data.offset + relx.offset; + switch (relx.type) { - // val = symbol.value.offset - case R_X86_64_NONE: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_64: { - // TODO - i64 x = - read_i64(LE, buf.begin + dst.offset, buf.end) + - symbol.address + relx.addent; - write_i64(LE, x, buf.begin + dst.offset, buf.end); - } break; - case R_X86_64_PC32: { - // TODO - i64 x = - read_i32(LE, buf.begin + dst.offset, buf.end) + - symbol.address + relx.addent; - write_i32(LE, (i32) x, buf.begin + dst.offset, buf.end); - } break; - case R_X86_64_GOT32: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_PLT32: { - // TODO - i64 x = - read_i32(LE, buf.begin + dst.offset, buf.end) + - symbol.address + relx.addent; - write_i32(LE, (i32) x, buf.begin + dst.offset, buf.end); - } break; - case R_X86_64_COPY: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_GLOB_DAT: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_JUMP_SLOT: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_RELATIVE: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_GOTPCREL: { - // TODO - //BX_FAIL("Not implemented",); - } break; - case R_X86_64_32: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_32S: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_16: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_PC16: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_8: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_PC8: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_DTPMOD64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_DTPOFF64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_TPOFF64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_TLSGD: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_TLSLD: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_DTPOFF32: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_GOTTPOFF: { - // TODO - //BX_FAIL("Not implemented",); - } break; - case R_X86_64_TPOFF32: { - // TODO - i64 x = - read_i32(LE, buf.begin + dst.offset, buf.end) + - symbol.address + relx.addent - pool->section_addresses[symbol.section]; - write_i32(LE, (i32) x, buf.begin + dst.offset, buf.end); - } break; - case R_X86_64_PC64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_GOTOFF64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_GOTPC32: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_GOT64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_GOTPCREL64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_GOTPC64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_GOTPLT64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_PLTOFF64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_SIZE32: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_SIZE64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_GOTPC32_TLSDESC: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_TLSDESC_CALL: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_TLSDESC: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_IRELATIVE: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_RELATIVE64: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_GOTPCRELX: { - BX_FAIL("Not implemented",); - } break; - case R_X86_64_REX_GOTPCRELX: { - // TODO - //BX_FAIL("Not implemented",); - } break; - default: - BX_LAX(0, "Unknown relocation type"); + #define ADD_(BITS, OP) \ + do { \ + i64 x_ = read_i##BITS(LE, dst, buf.end) + (OP); \ + write_i##BITS(LE, (i##BITS) x_, dst, buf.end); \ + } while (0) + + #define TODO_ BX_FAIL("Not implemented",) + + case R_X86_64_NONE: /* do nothing */ break; + case R_X86_64_64: ADD_(64, S + A); break; + case R_X86_64_PC32: ADD_(32, S + A - P); break; + case R_X86_64_GOT32: ADD_(32, G + A); break; + case R_X86_64_PLT32: ADD_(32, L + A - P); break; + case R_X86_64_COPY: /* do nothing */ break; + case R_X86_64_GLOB_DAT: ADD_(64, S); break; + case R_X86_64_JUMP_SLOT: ADD_(64, S); break; + case R_X86_64_RELATIVE: ADD_(64, B + A); break; + case R_X86_64_GOTPCREL: ADD_(64, G + GOT + A - P); break; + case R_X86_64_32: ADD_(32, S + A); break; + case R_X86_64_32S: ADD_(32, S + A); break; + case R_X86_64_16: ADD_(16, S + A); break; + case R_X86_64_PC16: ADD_(16, S + A - P); break; + case R_X86_64_8: ADD_(8, S + A); break; + case R_X86_64_PC8: ADD_(8, S + A - P); break; + case R_X86_64_DTPMOD64: TODO_; break; + case R_X86_64_DTPOFF64: TODO_; break; + case R_X86_64_TPOFF64: TODO_; break; + case R_X86_64_TLSGD: TODO_; break; + case R_X86_64_TLSLD: TODO_; break; + case R_X86_64_DTPOFF32: TODO_; break; + case R_X86_64_GOTTPOFF: ADD_(32, S - GOT); break; + case R_X86_64_TPOFF32: ADD_(32, S + A - B); break; + case R_X86_64_PC64: ADD_(64, S + A - P); break; + case R_X86_64_GOTOFF64: TODO_; break; + case R_X86_64_GOTPC32: TODO_; break; + case R_X86_64_GOT64: TODO_; break; + case R_X86_64_GOTPCREL64: TODO_; break; + case R_X86_64_GOTPC64: TODO_; break; + case R_X86_64_GOTPLT64: TODO_; break; + case R_X86_64_PLTOFF64: TODO_; break; + case R_X86_64_SIZE32: TODO_; break; + case R_X86_64_SIZE64: TODO_; break; + case R_X86_64_GOTPC32_TLSDESC: TODO_; break; + case R_X86_64_TLSDESC_CALL: TODO_; break; + case R_X86_64_TLSDESC: TODO_; break; + case R_X86_64_IRELATIVE: TODO_; break; + case R_X86_64_RELATIVE64: TODO_; break; + case R_X86_64_GOTPCRELX: TODO_; break; + case R_X86_64_REX_GOTPCRELX: ADD_(32, GOT - P + G - 4); break; + default: BX_LAX(0, "Unknown relocation type"); + + #undef ADD_ + #undef TODO_ } } } -- cgit v1.2.3