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
master
Thomas Preud'homme 2016-11-17 22:54:06 +00:00
parent 6cd23d1d8c
commit 523b55d82d
1 changed files with 27 additions and 22 deletions

View File

@ -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 ||