From ef9133af166ca531ee9818d01fdeb58e56eaef37 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sun, 10 Oct 2021 13:10:57 -0700 Subject: Use Elf64_Rela for relocations. The x86_64 psABI[0] says that > The AMD64 LP64 ABI architecture uses only Elf64_Rela relocation > entries with explicit addends. The r_addend member serves as the > relocation addend. [0] https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-draft.pdf --- main.c | 21 ++++++++++----------- minias.h | 1 + 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/main.c b/main.c index 147aede..227a3d2 100644 --- a/main.c +++ b/main.c @@ -136,16 +136,16 @@ static void initsections(void) { text->hdr.sh_addralign = 4; textrel = newsection(); - textrel->hdr.sh_type = SHT_REL; + textrel->hdr.sh_type = SHT_RELA; textrel->hdr.sh_info = text->idx; textrel->hdr.sh_link = symtab->idx; - textrel->hdr.sh_entsize = sizeof(Elf64_Rel); + textrel->hdr.sh_entsize = sizeof(Elf64_Rela); datarel = newsection(); - datarel->hdr.sh_type = SHT_REL; + datarel->hdr.sh_type = SHT_RELA; datarel->hdr.sh_info = data->idx; datarel->hdr.sh_link = symtab->idx; - datarel->hdr.sh_entsize = sizeof(Elf64_Rel); + datarel->hdr.sh_entsize = sizeof(Elf64_Rela); } Relocation *newreloc() { @@ -415,6 +415,8 @@ static void assemblereloc(const char *l, int64_t c, int nbytes, int type) { reloc->section = cursection; reloc->sym = sym; reloc->offset = cursection->hdr.sh_size; + reloc->addend = c; + c = 0; } assembleconstant(c, nbytes); } @@ -1035,9 +1037,7 @@ static void resolvereloc(Relocation *reloc) { switch (reloc->type) { case R_X86_64_32: { rdata = &reloc->section->data[reloc->offset]; - addend = (int32_t)rdata[0] | (int32_t)(rdata[1] << 8) | - (int32_t)(rdata[2] << 16) | (int32_t)(rdata[3] << 24); - value = sym->offset - reloc->offset + addend; + value = sym->offset - reloc->offset + reloc->addend; rdata[0] = ((uint32_t)value & 0xff); rdata[1] = ((uint32_t)value & 0xff00) >> 8; rdata[2] = ((uint32_t)value & 0xff0000) >> 16; @@ -1046,9 +1046,7 @@ static void resolvereloc(Relocation *reloc) { } case R_X86_64_PC32: { rdata = &reloc->section->data[reloc->offset]; - addend = (int32_t)rdata[0] | (int32_t)(rdata[1] << 8) | - (int32_t)(rdata[2] << 16) | (int32_t)(rdata[3] << 24); - value = sym->offset - reloc->offset + addend; + value = sym->offset - reloc->offset + reloc->addend; rdata[0] = ((uint32_t)value & 0xff); rdata[1] = ((uint32_t)value & 0xff00) >> 8; rdata[2] = ((uint32_t)value & 0xff0000) >> 16; @@ -1063,7 +1061,7 @@ static void resolvereloc(Relocation *reloc) { static void appendreloc(Relocation *reloc) { Symbol *sym; Section *relsection; - Elf64_Rel elfrel; + Elf64_Rela elfrel; memset(&elfrel, 0, sizeof(elfrel)); @@ -1080,6 +1078,7 @@ static void appendreloc(Relocation *reloc) { case R_X86_64_32: elfrel.r_info = ELF64_R_INFO(sym->idx, reloc->type); elfrel.r_offset = reloc->offset; + elfrel.r_addend = reloc->addend; break; default: unreachable(); diff --git a/minias.h b/minias.h index abf1f06..750f481 100644 --- a/minias.h +++ b/minias.h @@ -35,6 +35,7 @@ typedef struct { Symbol *sym; int type; int64_t offset; + int64_t addend; } Relocation; typedef enum { -- cgit v1.2.3