mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-06 06:40:07 +08:00
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
This commit is contained in:
parent
6cd23d1d8c
commit
523b55d82d
49
tccelf.c
49
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 ||
|
||||
|
Loading…
Reference in New Issue
Block a user