summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-07-24 15:53:02 +0200
committerMitya Selivanov <automainint@guattari.tech>2024-07-24 15:53:02 +0200
commit6a213202a41d744464ba7f19ce4781beb3e8fef8 (patch)
treee0b48e3889939027e361b2ea0ccf8f9c15c4faec
parent82380dfa047e0775f46fbd27538bb62c0a295921 (diff)
downloadbxgen-6a213202a41d744464ba7f19ce4781beb3e8fef8.zip
Relocations
-rwxr-xr-xbxgen.c262
1 files changed, 94 insertions, 168 deletions
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_
}
}
}