Recognize more relocations as needing GOT/PLT entry

master
Thomas Preud'homme 2016-11-12 23:16:06 +08:00
parent cb273fdad8
commit 6cd23d1d8c
1 changed files with 41 additions and 16 deletions

View File

@ -1034,6 +1034,8 @@ ST_FUNC void build_got_entries(TCCState *s1)
type = ELFW(R_TYPE)(rel->r_info); type = ELFW(R_TYPE)(rel->r_info);
switch(type) { switch(type) {
#if defined(TCC_TARGET_I386) #if defined(TCC_TARGET_I386)
case R_386_PC16:
case R_386_PC32:
case R_386_GOT32: case R_386_GOT32:
case R_386_GOT32X: case R_386_GOT32X:
case R_386_GOTOFF: case R_386_GOTOFF:
@ -1046,7 +1048,8 @@ ST_FUNC void build_got_entries(TCCState *s1)
sym_index = ELFW(R_SYM)(rel->r_info); sym_index = ELFW(R_SYM)(rel->r_info);
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
/* look at the symbol got offset. If none, then add one */ /* look at the symbol got offset. If none, then add one */
if (type == R_386_GOT32 || type == R_386_GOT32X) if (type == R_386_GOT32 || type == R_386_GOT32X ||
type == R_386_16 || type == R_386_32)
reloc_type = R_386_GLOB_DAT; reloc_type = R_386_GLOB_DAT;
else else
reloc_type = R_386_JMP_SLOT; reloc_type = R_386_JMP_SLOT;
@ -1058,10 +1061,19 @@ ST_FUNC void build_got_entries(TCCState *s1)
case R_ARM_PC24: case R_ARM_PC24:
case R_ARM_CALL: case R_ARM_CALL:
case R_ARM_JUMP24: case R_ARM_JUMP24:
case R_ARM_GOT32:
case R_ARM_GOTOFF:
case R_ARM_GOTPC:
case R_ARM_PLT32: case R_ARM_PLT32:
case R_ARM_THM_PC22:
case R_ARM_MOVT_ABS:
case R_ARM_MOVW_ABS_NC:
case R_ARM_THM_MOVT_ABS:
case R_ARM_THM_MOVW_ABS_NC:
case R_ARM_PREL31:
case R_ARM_REL32:
case R_ARM_GOTPC:
case R_ARM_GOTOFF:
case R_ARM_GOT32:
case R_ARM_V4BX:
if (!s1->got) if (!s1->got)
build_got(s1); build_got(s1);
sym_index = ELFW(R_SYM)(rel->r_info); sym_index = ELFW(R_SYM)(rel->r_info);
@ -1071,7 +1083,11 @@ ST_FUNC void build_got_entries(TCCState *s1)
|| s1->output_type == TCC_OUTPUT_MEMORY)) { || s1->output_type == TCC_OUTPUT_MEMORY)) {
unsigned long ofs; unsigned long ofs;
/* look at the symbol got offset. If none, then add one */ /* look at the symbol got offset. If none, then add one */
if (type == R_ARM_GOT32) if (type == R_ARM_GOT32 || type == R_ARM_MOVT_ABS ||
type == R_ARM_MOVW_ABS_NC ||
type == R_ARM_THM_MOVT_ABS ||
type == R_ARM_THM_MOVW_ABS_NC || type == R_ARM_ABS32 ||
type == R_ARM_REL32)
reloc_type = R_ARM_GLOB_DAT; reloc_type = R_ARM_GLOB_DAT;
else else
reloc_type = R_ARM_JUMP_SLOT; reloc_type = R_ARM_JUMP_SLOT;
@ -1082,7 +1098,8 @@ ST_FUNC void build_got_entries(TCCState *s1)
(char *) symtab_section->link->data + sym->st_name, (char *) symtab_section->link->data + sym->st_name,
type, sym->st_shndx, ofs); type, sym->st_shndx, ofs);
#endif #endif
if (type != R_ARM_GOT32) { if (type == R_ARM_PC24 || type == R_ARM_CALL ||
type == R_ARM_JUMP24 || type == R_ARM_PLT32) {
addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
+ rel->r_offset); + rel->r_offset);
/* x must be signed! */ /* x must be signed! */
@ -1177,11 +1194,15 @@ ST_FUNC void build_got_entries(TCCState *s1)
} }
break; break;
#elif defined(TCC_TARGET_X86_64) #elif defined(TCC_TARGET_X86_64)
case R_X86_64_32:
case R_X86_64_32S:
case R_X86_64_64:
case R_X86_64_PC32:
case R_X86_64_GOT32: case R_X86_64_GOT32:
case R_X86_64_GOTTPOFF: case R_X86_64_GOTTPOFF:
case R_X86_64_GOTPCREL: case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX: 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_PLT32:
sym_index = ELFW(R_SYM)(rel->r_info); sym_index = ELFW(R_SYM)(rel->r_info);
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
@ -1202,16 +1223,20 @@ ST_FUNC void build_got_entries(TCCState *s1)
type == R_X86_64_PLT32) { type == R_X86_64_PLT32) {
unsigned long ofs; unsigned long ofs;
/* look at the symbol got offset. If none, then add one */ /* look at the symbol got offset. If none, then add one */
if (type == R_X86_64_PLT32) if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
reloc_type = R_X86_64_JUMP_SLOT; type == R_X86_64_GOTPCRELX ||
else type == R_X86_64_REX_GOTPCRELX ||
type == R_X86_64_32 || type == R_X86_64_32S ||
type == R_X86_64_64)
reloc_type = R_X86_64_GLOB_DAT; reloc_type = R_X86_64_GLOB_DAT;
else
reloc_type = R_X86_64_JUMP_SLOT;
ofs = put_got_entry(s1, reloc_type, sym->st_size, ofs = put_got_entry(s1, reloc_type, sym->st_size,
sym->st_info, sym_index); sym->st_info, sym_index);
if (type == R_X86_64_PLT32) if (type == R_X86_64_PLT32)
/* We store the place of the generated PLT slot /* We store the place of the generated PLT slot
in our addend. */ in our addend. */
rel->r_addend += ofs; rel->r_addend += ofs;
} }
break; break;
#else #else