aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Preud'homme <robotux@celest.fr>2016-11-17 22:54:06 +0000
committerThomas Preud'homme <robotux@celest.fr>2016-12-03 17:26:51 +0000
commit523b55d82d455951659868d68eb54c4f5dbfb5a4 (patch)
tree5b73752ab76c0365f763a354920a78bd3ec27b07
parent6cd23d1d8cb904e7168893e67b7ffbc718b3237d (diff)
downloadtinycc-523b55d82d455951659868d68eb54c4f5dbfb5a4.tar.gz
tinycc-523b55d82d455951659868d68eb54c4f5dbfb5a4.tar.bz2
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
-rw-r--r--tccelf.c49
1 files 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 ||