tccelf: avoid lookup of _GLOBAL_OFFSET_TABLE_

Instead, return its symbol index from build_got_entries()
Also, copy dynamic symbols later when size of _GLOBAL_OFFSET_TABLE_
was already set and handle -rdynamic there too.
See commit 4c82b00342

5 insertions(+), 5 deletions(-)
This commit is contained in:
grischka 2022-05-28 20:59:25 +02:00
parent c81519e1c4
commit 7d6979d452
3 changed files with 35 additions and 46 deletions

2
tcc.h
View file

@ -1567,7 +1567,7 @@ enum gotplt_entry {
#if !defined TCC_TARGET_MACHO || defined TCC_IS_NATIVE
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
ST_FUNC void relocate_plt(TCCState *s1);
ST_FUNC void build_got_entries(TCCState *s1); /* in tccelf.c */
ST_FUNC void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */
#define NEED_BUILD_GOT
#endif

View file

@ -1039,15 +1039,15 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
#endif
#ifdef NEED_BUILD_GOT
static void build_got(TCCState *s1)
static int build_got(TCCState *s1)
{
/* if no got, then create it */
s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
s1->got->sh_entsize = 4;
set_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
/* keep space for _DYNAMIC pointer and two dummy got entries */
section_ptr_add(s1->got, 3 * PTR_SIZE);
return set_elf_sym(symtab_section, 0, 0, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
}
/* Create a GOT and (for function call) a PLT entry corresponding to a symbol
@ -1152,7 +1152,7 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type,
/* build GOT and PLT entries */
/* Two passes because R_JMP_SLOT should become first. Some targets
(arm, arm64) do not allow mixing R_JMP_SLOT and R_GLOB_DAT. */
ST_FUNC void build_got_entries(TCCState *s1)
ST_FUNC void build_got_entries(TCCState *s1, int got_sym)
{
Section *s;
ElfW_Rel *rel;
@ -1160,7 +1160,6 @@ ST_FUNC void build_got_entries(TCCState *s1)
int i, type, gotplt_entry, reloc_type, sym_index;
struct sym_attr *attr;
int pass = 0;
redo:
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
@ -1252,7 +1251,7 @@ redo:
}
if (!s1->got)
build_got(s1);
got_sym = build_got(s1);
if (gotplt_entry == BUILD_GOT_ONLY)
continue;
@ -1265,11 +1264,11 @@ redo:
}
if (++pass < 2)
goto redo;
/* .rel.plt refers to .got actually */
if (s1->plt && s1->plt->reloc)
s1->plt->reloc->sh_info = s1->got->sh_num;
if (got_sym) /* set size */
((ElfW(Sym)*)symtab_section->data)[got_sym].st_size = s1->got->data_offset;
}
#endif /* def NEED_BUILD_GOT */
@ -1681,8 +1680,7 @@ static void fill_local_got_entries(TCCState *s1)
}
/* Bind symbols of executable: resolve undefined symbols from exported symbols
in shared libraries and export non local defined symbols to shared libraries
if -rdynamic switch was given on command line */
in shared libraries */
static void bind_exe_dynsyms(TCCState *s1)
{
const char *name;
@ -1755,11 +1753,6 @@ static void bind_exe_dynsyms(TCCState *s1)
tcc_error_noabort("undefined symbol '%s'", name);
}
}
} else if (s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
/* if -rdynamic option, then export all non local symbols */
name = (char *) symtab_section->link->data + sym->st_name;
set_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info,
0, sym->st_shndx, name);
}
}
}
@ -1768,28 +1761,31 @@ static void bind_exe_dynsyms(TCCState *s1)
are referenced by shared libraries. The reason is that the dynamic loader
search symbol first in executable and then in libraries. Therefore a
reference to a symbol already defined by a library can still be resolved by
a symbol in the executable. */
a symbol in the executable. With -rdynamic, export all defined symbols */
static void bind_libs_dynsyms(TCCState *s1)
{
const char *name;
int sym_index;
int dynsym_index;
ElfW(Sym) *sym, *esym;
for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
name = (char *) s1->dynsymtab_section->link->data + esym->st_name;
sym_index = find_elf_sym(symtab_section, name);
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
if (sym_index && sym->st_shndx != SHN_UNDEF
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
name = (char *)symtab_section->link->data + sym->st_name;
dynsym_index = find_elf_sym(s1->dynsymtab_section, name);
if (sym->st_shndx != SHN_UNDEF
&& ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
if (dynsym_index || s1->rdynamic)
set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
sym->st_info, 0, sym->st_shndx, name);
} else if (esym->st_shndx == SHN_UNDEF) {
} else if (dynsym_index) {
esym = (ElfW(Sym) *)s1->dynsymtab_section->data + dynsym_index;
if (esym->st_shndx == SHN_UNDEF) {
/* weak symbols can stay undefined */
if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
tcc_warning("undefined dynamic symbol '%s'", name);
}
}
}
}
/* Export all non local symbols. This is used by shared libraries so that the
non local symbols they define can resolve a reference in another shared
@ -1800,11 +1796,10 @@ static void export_global_syms(TCCState *s1)
int dynindex, index;
const char *name;
ElfW(Sym) *sym;
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
name = (char *) symtab_section->link->data + sym->st_name;
dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
dynindex = set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
sym->st_info, 0, sym->st_shndx, name);
index = sym - (ElfW(Sym) *) symtab_section->data;
get_sym_attr(s1, index, 1)->dyn_index = dynindex;
@ -2532,13 +2527,7 @@ static Section *create_bsd_note_section(TCCState *s1,
}
#endif
static void elf_patch_global_offset_size(TCCState *s1, Section *s)
{
int sym_index;
if (s && (sym_index = find_elf_sym(s, "_GLOBAL_OFFSET_TABLE_")))
((ElfW(Sym) *)s->data)[sym_index].st_size = s1->got->data_offset;
}
static void alloc_sec_names(TCCState *s1, int is_obj);
/* Output an elf, coff or binary file */
/* XXX: suppress unneeded sections */
@ -2550,7 +2539,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
ElfW(Phdr) *phdr;
Section *interp, *dynamic, *dynstr, *note;
struct ro_inf *roinf_use = NULL;
int textrel;
int textrel, got_sym;
file_type = s1->output_type;
s1->nb_errors = 0;
@ -2603,22 +2592,22 @@ static int elf_output_file(TCCState *s1, const char *filename)
dynamic->link = dynstr;
dynamic->sh_entsize = sizeof(ElfW(Dyn));
if (!s1->got)
build_got(s1);
got_sym = build_got(s1);
if (file_type == TCC_OUTPUT_EXE) {
bind_exe_dynsyms(s1);
if (s1->nb_errors)
goto the_end;
}
build_got_entries(s1, got_sym);
if (file_type == TCC_OUTPUT_EXE) {
bind_libs_dynsyms(s1);
} else {
/* shared library case: simply export all global symbols */
export_global_syms(s1);
}
} else {
build_got_entries(s1, 0);
}
build_got_entries(s1);
elf_patch_global_offset_size(s1, symtab_section);
elf_patch_global_offset_size(s1, s1->dynsym);
version_add (s1);
}

View file

@ -261,7 +261,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
#else
tcc_add_runtime(s1);
resolve_common_syms(s1);
build_got_entries(s1);
build_got_entries(s1, 0);
#endif
if (s1->nb_errors)
return -1;