History

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 4c82b003420fabbb95e077866784badc1a49189b 5 insertions(+), 5 deletions(-)

grischka committed 4 years ago

Commit 7d6979d1 parent c81519e3 files · +35 −46Browse files

Unified · Split

3 files
  1. tcc.h +1 −1
  2. tccelf.c +33 −44
  3. tccrun.c +1 −1
tcc.h+1−1
@@ -1567,7 +1567,7 @@ enum gotplt_entry { · 1566 unmodified lines
15671567 #if !defined TCC_TARGET_MACHO || defined TCC_IS_NATIVE
15681568 ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
15691569 ST_FUNC void relocate_plt(TCCState *s1);
1570−ST_FUNC void build_got_entries(TCCState *s1); /* in tccelf.c */
1570+ST_FUNC void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */
15711571 #define NEED_BUILD_GOT
15721572
15731573 #endif
tccelf.c+33−44
@@ -1039,15 +1039,15 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) · 1038 unmodified lines
10391039 #endif
10401040
10411041 #ifdef NEED_BUILD_GOT
1042−static void build_got(TCCState *s1)
1042+static int build_got(TCCState *s1)
10431043 {
10441044 /* if no got, then create it */
10451045 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10461046 s1->got->sh_entsize = 4;
1047− set_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1048− 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
10491047 /* keep space for _DYNAMIC pointer and two dummy got entries */
10501048 section_ptr_add(s1->got, 3 * PTR_SIZE);
1049+ return set_elf_sym(symtab_section, 0, 0, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1050+ 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
10511051 }
10521052
10531053 /* 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, · 98 unmodified lines
11521152 /* build GOT and PLT entries */
11531153 /* Two passes because R_JMP_SLOT should become first. Some targets
11541154 (arm, arm64) do not allow mixing R_JMP_SLOT and R_GLOB_DAT. */
1155−ST_FUNC void build_got_entries(TCCState *s1)
1155+ST_FUNC void build_got_entries(TCCState *s1, int got_sym)
11561156 {
11571157 Section *s;
11581158 ElfW_Rel *rel;
@@ -1160,7 +1160,6 @@ ST_FUNC void build_got_entries(TCCState *s1) · 1 unmodified line
11601160 int i, type, gotplt_entry, reloc_type, sym_index;
11611161 struct sym_attr *attr;
11621162 int pass = 0;
1163−
11641163 redo:
11651164 for(i = 1; i < s1->nb_sections; i++) {
11661165 s = s1->sections[i];
@@ -1252,7 +1251,7 @@ redo: · 85 unmodified lines
12521251 }
12531252
12541253 if (!s1->got)
1255− build_got(s1);
1254+ got_sym = build_got(s1);
12561255
12571256 if (gotplt_entry == BUILD_GOT_ONLY)
12581257 continue;
@@ -1265,11 +1264,11 @@ redo: · 6 unmodified lines
12651264 }
12661265 if (++pass < 2)
12671266 goto redo;
1268−
12691267 /* .rel.plt refers to .got actually */
12701268 if (s1->plt && s1->plt->reloc)
12711269 s1->plt->reloc->sh_info = s1->got->sh_num;
1272−
1270+ if (got_sym) /* set size */
1271+ ((ElfW(Sym)*)symtab_section->data)[got_sym].st_size = s1->got->data_offset;
12731272 }
12741273 #endif /* def NEED_BUILD_GOT */
12751274
@@ -1681,8 +1680,7 @@ static void fill_local_got_entries(TCCState *s1) · 405 unmodified lines
16811680 }
16821681
16831682 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1684− in shared libraries and export non local defined symbols to shared libraries
1685− if -rdynamic switch was given on command line */
1683+ in shared libraries */
16861684 static void bind_exe_dynsyms(TCCState *s1)
16871685 {
16881686 const char *name;
@@ -1755,11 +1753,6 @@ static void bind_exe_dynsyms(TCCState *s1) · 66 unmodified lines
17551753 tcc_error_noabort("undefined symbol '%s'", name);
17561754 }
17571755 }
1758− } else if (s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1759− /* if -rdynamic option, then export all non local symbols */
1760− name = (char *) symtab_section->link->data + sym->st_name;
1761− set_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info,
1762− 0, sym->st_shndx, name);
17631756 }
17641757 }
17651758 }
@@ -1768,25 +1761,28 @@ static void bind_exe_dynsyms(TCCState *s1) · 2 unmodified lines
17681761 are referenced by shared libraries. The reason is that the dynamic loader
17691762 search symbol first in executable and then in libraries. Therefore a
17701763 reference to a symbol already defined by a library can still be resolved by
1771− a symbol in the executable. */
1764+ a symbol in the executable. With -rdynamic, export all defined symbols */
17721765 static void bind_libs_dynsyms(TCCState *s1)
17731766 {
17741767 const char *name;
1775− int sym_index;
1768+ int dynsym_index;
17761769 ElfW(Sym) *sym, *esym;
17771770
1778− for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
1779− name = (char *) s1->dynsymtab_section->link->data + esym->st_name;
1780− sym_index = find_elf_sym(symtab_section, name);
1781− sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1782− if (sym_index && sym->st_shndx != SHN_UNDEF
1771+ for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1772+ name = (char *)symtab_section->link->data + sym->st_name;
1773+ dynsym_index = find_elf_sym(s1->dynsymtab_section, name);
1774+ if (sym->st_shndx != SHN_UNDEF
17831775 && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1784− set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1785− sym->st_info, 0, sym->st_shndx, name);
1786− } else if (esym->st_shndx == SHN_UNDEF) {
1787− /* weak symbols can stay undefined */
1788− if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
1789− tcc_warning("undefined dynamic symbol '%s'", name);
1776+ if (dynsym_index || s1->rdynamic)
1777+ set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1778+ sym->st_info, 0, sym->st_shndx, name);
1779+ } else if (dynsym_index) {
1780+ esym = (ElfW(Sym) *)s1->dynsymtab_section->data + dynsym_index;
1781+ if (esym->st_shndx == SHN_UNDEF) {
1782+ /* weak symbols can stay undefined */
1783+ if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
1784+ tcc_warning("undefined dynamic symbol '%s'", name);
1785+ }
17901786 }
17911787 }
17921788 }
@@ -1800,11 +1796,10 @@ static void export_global_syms(TCCState *s1) · 7 unmodified lines
18001796 int dynindex, index;
18011797 const char *name;
18021798 ElfW(Sym) *sym;
1803−
18041799 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
18051800 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
18061801 name = (char *) symtab_section->link->data + sym->st_name;
1807− dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1802+ dynindex = set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
18081803 sym->st_info, 0, sym->st_shndx, name);
18091804 index = sym - (ElfW(Sym) *) symtab_section->data;
18101805 get_sym_attr(s1, index, 1)->dyn_index = dynindex;
@@ -2532,13 +2527,7 @@ static Section *create_bsd_note_section(TCCState *s1, · 721 unmodified lines
25322527 }
25332528 #endif
25342529
2535−static void elf_patch_global_offset_size(TCCState *s1, Section *s)
2536−{
2537− int sym_index;
2538−
2539− if (s && (sym_index = find_elf_sym(s, "_GLOBAL_OFFSET_TABLE_")))
2540− ((ElfW(Sym) *)s->data)[sym_index].st_size = s1->got->data_offset;
2541−}
2530+static void alloc_sec_names(TCCState *s1, int is_obj);
25422531
25432532 /* Output an elf, coff or binary file */
25442533 /* XXX: suppress unneeded sections */
@@ -2550,7 +2539,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 5 unmodified lines
25502539 ElfW(Phdr) *phdr;
25512540 Section *interp, *dynamic, *dynstr, *note;
25522541 struct ro_inf *roinf_use = NULL;
2553− int textrel;
2542+ int textrel, got_sym;
25542543
25552544 file_type = s1->output_type;
25562545 s1->nb_errors = 0;
@@ -2603,22 +2592,22 @@ static int elf_output_file(TCCState *s1, const char *filename) · 46 unmodified lines
26032592 dynamic->link = dynstr;
26042593 dynamic->sh_entsize = sizeof(ElfW(Dyn));
26052594
2606− if (!s1->got)
2607− build_got(s1);
2608−
2595+ got_sym = build_got(s1);
26092596 if (file_type == TCC_OUTPUT_EXE) {
26102597 bind_exe_dynsyms(s1);
26112598 if (s1->nb_errors)
26122599 goto the_end;
2600+ }
2601+ build_got_entries(s1, got_sym);
2602+ if (file_type == TCC_OUTPUT_EXE) {
26132603 bind_libs_dynsyms(s1);
26142604 } else {
26152605 /* shared library case: simply export all global symbols */
26162606 export_global_syms(s1);
26172607 }
2608+ } else {
2609+ build_got_entries(s1, 0);
26182610 }
2619− build_got_entries(s1);
2620− elf_patch_global_offset_size(s1, symtab_section);
2621− elf_patch_global_offset_size(s1, s1->dynsym);
26222611 version_add (s1);
26232612 }
26242613
tccrun.c+1−1
@@ -261,7 +261,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) · 260 unmodified lines
261261 #else
262262 tcc_add_runtime(s1);
263263 resolve_common_syms(s1);
264− build_got_entries(s1);
264+ build_got_entries(s1, 0);
265265 #endif
266266 if (s1->nb_errors)
267267 return -1;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t