From 523b55d82d455951659868d68eb54c4f5dbfb5a4 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Thu, 17 Nov 2016 22:54:06 +0000 Subject: [PATCH] Only create GOT or GOT entry when needed Currently we always build a GOT when we recognize a relocation in build_got_entries even if the relocation does not require one. In the same spirit, when the relocation does require one we always create a GOT entry even if not entry is necessary. This patch restricts the creation of a GOT and a GOT entry to relocations that needs it, ie: - do not create a GOT if relocation is not related to GOT and symbol is not UNDEF - do not create a GOT entry if relocation only relates to beginning of GOT --- tccelf.c | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/tccelf.c b/tccelf.c index e0eaea5..63e8111 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1032,6 +1032,8 @@ ST_FUNC void build_got_entries(TCCState *s1) continue; for_each_elem(s, 0, rel, ElfW_Rel) { type = ELFW(R_TYPE)(rel->r_info); + sym_index = ELFW(R_SYM)(rel->r_info); + sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; switch(type) { #if defined(TCC_TARGET_I386) case R_386_PC16: @@ -1041,15 +1043,17 @@ ST_FUNC void build_got_entries(TCCState *s1) case R_386_GOTOFF: case R_386_GOTPC: case R_386_PLT32: + if (sym->st_shndx != SHN_UNDEF && type != R_386_GOT32 && + type != R_386_GOT32X && type != R_386_GOTOFF && + type != R_386_GOTPC && type != R_386_PLT32) + break; + if (!s1->got) build_got(s1); - if (type == R_386_GOT32 || type == R_386_GOT32X || - type == R_386_PLT32) { - sym_index = ELFW(R_SYM)(rel->r_info); - sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; + + if (type != R_386_GOTOFF && type != R_386_GOTPC) { /* look at the symbol got offset. If none, then add one */ - if (type == R_386_GOT32 || type == R_386_GOT32X || - type == R_386_16 || type == R_386_32) + if (type == R_386_GOT32 || type == R_386_GOT32X) reloc_type = R_386_GLOB_DAT; else reloc_type = R_386_JMP_SLOT; @@ -1073,11 +1077,13 @@ ST_FUNC void build_got_entries(TCCState *s1) case R_ARM_GOTOFF: case R_ARM_GOT32: case R_ARM_V4BX: + if (sym->st_shndx != SHN_UNDEF && type != R_ARM_GOT32 && + type != R_ARM_GOTOFF && type != R_ARM_GOTPC && + type != R_ARM_PLT32) + break; if (!s1->got) build_got(s1); - sym_index = ELFW(R_SYM)(rel->r_info); - sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC && (sym->st_shndx == SHN_UNDEF || s1->output_type == TCC_OUTPUT_MEMORY)) { @@ -1206,22 +1212,21 @@ ST_FUNC void build_got_entries(TCCState *s1) case R_X86_64_PLT32: sym_index = ELFW(R_SYM)(rel->r_info); sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - if (type == R_X86_64_PLT32 && - ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT) - { - rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32); - break; - } + if ((type == R_X86_64_32 || type == R_X86_64_32S || + type == R_X86_64_64 || type == R_X86_64_PC32) && + sym->st_shndx != SHN_UNDEF) + break; - if (!s1->got) { - build_got(s1); - sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; + if (type == R_X86_64_PLT32 && + ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT) { + rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32); + break; } - if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL || - type == R_X86_64_GOTPCRELX || - type == R_X86_64_REX_GOTPCRELX || - type == R_X86_64_PLT32) { - unsigned long ofs; + + if (!s1->got) + build_got(s1); + if (type != R_X86_64_GOTTPOFF) { + unsigned long ofs; /* look at the symbol got offset. If none, then add one */ if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL || type == R_X86_64_GOTPCRELX ||