From e2ccf3981d78dfeb390d22c74625b60310100abb Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Wed, 21 Feb 2018 23:16:20 +0000 Subject: New upstream version 0.9.27 --- x86_64-link.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 14 deletions(-) (limited to 'x86_64-link.c') diff --git a/x86_64-link.c b/x86_64-link.c index 602a8ef..a96144c 100644 --- a/x86_64-link.c +++ b/x86_64-link.c @@ -8,6 +8,7 @@ #define R_JMP_SLOT R_X86_64_JUMP_SLOT #define R_GLOB_DAT R_X86_64_GLOB_DAT #define R_COPY R_X86_64_COPY +#define R_RELATIVE R_X86_64_RELATIVE #define R_NUM R_X86_64_NUM @@ -29,18 +30,24 @@ int code_reloc (int reloc_type) case R_X86_64_32: case R_X86_64_32S: case R_X86_64_64: + case R_X86_64_GOTPC32: + case R_X86_64_GOTPC64: case R_X86_64_GOTPCREL: case R_X86_64_GOTPCRELX: case R_X86_64_REX_GOTPCRELX: case R_X86_64_GOTTPOFF: case R_X86_64_GOT32: + case R_X86_64_GOT64: case R_X86_64_GLOB_DAT: case R_X86_64_COPY: - case R_X86_64_RELATIVE: + case R_X86_64_RELATIVE: + case R_X86_64_GOTOFF64: return 0; case R_X86_64_PC32: + case R_X86_64_PC64: case R_X86_64_PLT32: + case R_X86_64_PLTOFF64: case R_X86_64_JUMP_SLOT: return 1; } @@ -49,7 +56,7 @@ int code_reloc (int reloc_type) return -1; } -/* Returns an enumerator to describe wether and when the relocation needs a +/* Returns an enumerator to describe whether and when the relocation needs a GOT and/or PLT entry to be created. See tcc.h for a description of the different values. */ int gotplt_entry_type (int reloc_type) @@ -58,23 +65,32 @@ int gotplt_entry_type (int reloc_type) case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: case R_X86_64_COPY: - case R_X86_64_RELATIVE: + case R_X86_64_RELATIVE: return NO_GOTPLT_ENTRY; + /* The following relocs wouldn't normally need GOT or PLT + slots, but we need them for simplicity in the link + editor part. See our caller for comments. */ case R_X86_64_32: case R_X86_64_32S: case R_X86_64_64: case R_X86_64_PC32: + case R_X86_64_PC64: return AUTO_GOTPLT_ENTRY; case R_X86_64_GOTTPOFF: return BUILD_GOT_ONLY; case R_X86_64_GOT32: + case R_X86_64_GOT64: + case R_X86_64_GOTPC32: + case R_X86_64_GOTPC64: + case R_X86_64_GOTOFF64: case R_X86_64_GOTPCREL: case R_X86_64_GOTPCRELX: - case R_X86_64_REX_GOTPCRELX: + case R_X86_64_REX_GOTPCRELX: case R_X86_64_PLT32: + case R_X86_64_PLTOFF64: return ALWAYS_GOTPLT_ENTRY; } @@ -91,7 +107,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_ modrm = 0x25; - /* empty PLT: create PLT0 entry that pushes the library indentifier + /* empty PLT: create PLT0 entry that pushes the library identifier (GOT + PTR_SIZE) and jumps to ld.so resolution routine (GOT + 2 * PTR_SIZE) */ if (plt->data_offset == 0) { @@ -154,7 +170,7 @@ void relocate_init(Section *sr) qrel = (ElfW_Rel *) sr->data; } -void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, addr_t val) +void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val) { int sym_index, esym_index; @@ -167,12 +183,12 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add qrel->r_offset = rel->r_offset; if (esym_index) { qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64); - qrel->r_addend = rel->r_addend; + qrel->r_addend = rel->r_addend; qrel++; break; } else { - qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); - qrel->r_addend = read64le(ptr) + val; + qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); + qrel->r_addend = read64le(ptr) + val; qrel++; } } @@ -207,10 +223,10 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add goto plt32pc32; case R_X86_64_PLT32: - /* fallthrough: val already holds the PLT slot address */ + /* fallthrough: val already holds the PLT slot address */ - plt32pc32: - { + plt32pc32: + { long long diff; diff = (long long)val - addr; if (diff < -2147483648LL || diff > 2147483647LL) { @@ -219,17 +235,43 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add add32le(ptr, diff); } break; + + case R_X86_64_PLTOFF64: + add64le(ptr, val - s1->got->sh_addr + rel->r_addend); + break; + + case R_X86_64_PC64: + if (s1->output_type == TCC_OUTPUT_DLL) { + /* DLL relocation */ + esym_index = s1->sym_attrs[sym_index].dyn_index; + if (esym_index) { + qrel->r_offset = rel->r_offset; + qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC64); + qrel->r_addend = read64le(ptr) + rel->r_addend; + qrel++; + break; + } + } + add64le(ptr, val - addr); + break; + case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: /* They don't need addend */ write64le(ptr, val - rel->r_addend); break; case R_X86_64_GOTPCREL: - case R_X86_64_GOTPCRELX: - case R_X86_64_REX_GOTPCRELX: + case R_X86_64_GOTPCRELX: + case R_X86_64_REX_GOTPCRELX: add32le(ptr, s1->got->sh_addr - addr + s1->sym_attrs[sym_index].got_offset - 4); break; + case R_X86_64_GOTPC32: + add32le(ptr, s1->got->sh_addr - addr + rel->r_addend); + break; + case R_X86_64_GOTPC64: + add64le(ptr, s1->got->sh_addr - addr + rel->r_addend); + break; case R_X86_64_GOTTPOFF: add32le(ptr, val - s1->got->sh_addr); break; @@ -237,7 +279,17 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add /* we load the got offset */ add32le(ptr, s1->sym_attrs[sym_index].got_offset); break; + case R_X86_64_GOT64: + /* we load the got offset */ + add64le(ptr, s1->sym_attrs[sym_index].got_offset); + break; + case R_X86_64_GOTOFF64: + add64le(ptr, val - s1->got->sh_addr); + break; case R_X86_64_RELATIVE: +#ifdef TCC_TARGET_PE + add32le(ptr, val - s1->pe_imagebase); +#endif /* do nothing */ break; } -- cgit v1.2.3