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
1567#if !defined TCC_TARGET_MACHO || defined TCC_IS_NATIVE1567#if !defined TCC_TARGET_MACHO || defined TCC_IS_NATIVE
1568ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);1568ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
1569ST_FUNC void relocate_plt(TCCState *s1);1569ST_FUNC void relocate_plt(TCCState *s1);
1570ST_FUNC void build_got_entries(TCCState *s1); /* in tccelf.c */1570ST_FUNC void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */
1571#define NEED_BUILD_GOT1571#define NEED_BUILD_GOT
1572 1572
1573#endif1573#endif
tccelf.c+33−44
@@ -1039,15 +1039,15 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) · 1038 unmodified lines
1039#endif1039#endif
1040 1040
1041#ifdef NEED_BUILD_GOT1041#ifdef NEED_BUILD_GOT
1042static void build_got(TCCState *s1)1042static int build_got(TCCState *s1)
1043{1043{
1044 /* if no got, then create it */1044 /* if no got, then create it */
1045 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);1045 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
1046 s1->got->sh_entsize = 4;1046 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_");
1049 /* keep space for _DYNAMIC pointer and two dummy got entries */1047 /* keep space for _DYNAMIC pointer and two dummy got entries */
1050 section_ptr_add(s1->got, 3 * PTR_SIZE);1048 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_");
1051}1051}
1052 1052
1053/* Create a GOT and (for function call) a PLT entry corresponding to a symbol1053/* 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
1152/* build GOT and PLT entries */1152/* build GOT and PLT entries */
1153/* Two passes because R_JMP_SLOT should become first. Some targets1153/* Two passes because R_JMP_SLOT should become first. Some targets
1154 (arm, arm64) do not allow mixing R_JMP_SLOT and R_GLOB_DAT. */1154 (arm, arm64) do not allow mixing R_JMP_SLOT and R_GLOB_DAT. */
1155ST_FUNC void build_got_entries(TCCState *s1)1155ST_FUNC void build_got_entries(TCCState *s1, int got_sym)
1156{1156{
1157 Section *s;1157 Section *s;
1158 ElfW_Rel *rel;1158 ElfW_Rel *rel;
@@ -1160,7 +1160,6 @@ ST_FUNC void build_got_entries(TCCState *s1) · 1 unmodified line
1160 int i, type, gotplt_entry, reloc_type, sym_index;1160 int i, type, gotplt_entry, reloc_type, sym_index;
1161 struct sym_attr *attr;1161 struct sym_attr *attr;
1162 int pass = 0;1162 int pass = 0;
1163
1164redo:1163redo:
1165 for(i = 1; i < s1->nb_sections; i++) {1164 for(i = 1; i < s1->nb_sections; i++) {
1166 s = s1->sections[i];1165 s = s1->sections[i];
@@ -1252,7 +1251,7 @@ redo: · 85 unmodified lines
1252 }1251 }
1253 1252
1254 if (!s1->got)1253 if (!s1->got)
1255 build_got(s1);1254 got_sym = build_got(s1);
1256 1255
1257 if (gotplt_entry == BUILD_GOT_ONLY)1256 if (gotplt_entry == BUILD_GOT_ONLY)
1258 continue;1257 continue;
@@ -1265,11 +1264,11 @@ redo: · 6 unmodified lines
1265 }1264 }
1266 if (++pass < 2)1265 if (++pass < 2)
1267 goto redo;1266 goto redo;
1268
1269 /* .rel.plt refers to .got actually */1267 /* .rel.plt refers to .got actually */
1270 if (s1->plt && s1->plt->reloc)1268 if (s1->plt && s1->plt->reloc)
1271 s1->plt->reloc->sh_info = s1->got->sh_num;1269 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;
1273}1272}
1274#endif /* def NEED_BUILD_GOT */1273#endif /* def NEED_BUILD_GOT */
1275 1274
@@ -1681,8 +1680,7 @@ static void fill_local_got_entries(TCCState *s1) · 405 unmodified lines
1681}1680}
1682 1681
1683/* Bind symbols of executable: resolve undefined symbols from exported symbols1682/* Bind symbols of executable: resolve undefined symbols from exported symbols
1684 in shared libraries and export non local defined symbols to shared libraries1683 in shared libraries */
1685 if -rdynamic switch was given on command line */
1686static void bind_exe_dynsyms(TCCState *s1)1684static void bind_exe_dynsyms(TCCState *s1)
1687{1685{
1688 const char *name;1686 const char *name;
@@ -1755,11 +1753,6 @@ static void bind_exe_dynsyms(TCCState *s1) · 66 unmodified lines
1755 tcc_error_noabort("undefined symbol '%s'", name);1753 tcc_error_noabort("undefined symbol '%s'", name);
1756 }1754 }
1757 }1755 }
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);
1763 }1756 }
1764 }1757 }
1765}1758}
@@ -1768,25 +1761,28 @@ static void bind_exe_dynsyms(TCCState *s1) · 2 unmodified lines
1768 are referenced by shared libraries. The reason is that the dynamic loader1761 are referenced by shared libraries. The reason is that the dynamic loader
1769 search symbol first in executable and then in libraries. Therefore a1762 search symbol first in executable and then in libraries. Therefore a
1770 reference to a symbol already defined by a library can still be resolved by1763 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 */
1772static void bind_libs_dynsyms(TCCState *s1)1765static void bind_libs_dynsyms(TCCState *s1)
1773{1766{
1774 const char *name;1767 const char *name;
1775 int sym_index;1768 int dynsym_index;
1776 ElfW(Sym) *sym, *esym;1769 ElfW(Sym) *sym, *esym;
1777 1770
1778 for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {1771 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1779 name = (char *) s1->dynsymtab_section->link->data + esym->st_name;1772 name = (char *)symtab_section->link->data + sym->st_name;
1780 sym_index = find_elf_sym(symtab_section, name);1773 dynsym_index = find_elf_sym(s1->dynsymtab_section, name);
1781 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];1774 if (sym->st_shndx != SHN_UNDEF
1782 if (sym_index && sym->st_shndx != SHN_UNDEF
1783 && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {1775 && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1784 set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,1776 if (dynsym_index || s1->rdynamic)
1785 sym->st_info, 0, sym->st_shndx, name);1777 set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1786 } else if (esym->st_shndx == SHN_UNDEF) {1778 sym->st_info, 0, sym->st_shndx, name);
1787 /* weak symbols can stay undefined */1779 } else if (dynsym_index) {
1788 if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)1780 esym = (ElfW(Sym) *)s1->dynsymtab_section->data + dynsym_index;
1789 tcc_warning("undefined dynamic symbol '%s'", name);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 }
1790 }1786 }
1791 }1787 }
1792}1788}
@@ -1800,11 +1796,10 @@ static void export_global_syms(TCCState *s1) · 7 unmodified lines
1800 int dynindex, index;1796 int dynindex, index;
1801 const char *name;1797 const char *name;
1802 ElfW(Sym) *sym;1798 ElfW(Sym) *sym;
1803
1804 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {1799 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1805 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {1800 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1806 name = (char *) symtab_section->link->data + sym->st_name;1801 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,
1808 sym->st_info, 0, sym->st_shndx, name);1803 sym->st_info, 0, sym->st_shndx, name);
1809 index = sym - (ElfW(Sym) *) symtab_section->data;1804 index = sym - (ElfW(Sym) *) symtab_section->data;
1810 get_sym_attr(s1, index, 1)->dyn_index = dynindex;1805 get_sym_attr(s1, index, 1)->dyn_index = dynindex;
@@ -2532,13 +2527,7 @@ static Section *create_bsd_note_section(TCCState *s1, · 721 unmodified lines
2532}2527}
2533#endif2528#endif
2534 2529
2535static void elf_patch_global_offset_size(TCCState *s1, Section *s)2530static void alloc_sec_names(TCCState *s1, int is_obj);
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}
2542 2531
2543/* Output an elf, coff or binary file */2532/* Output an elf, coff or binary file */
2544/* XXX: suppress unneeded sections */2533/* XXX: suppress unneeded sections */
@@ -2550,7 +2539,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 5 unmodified lines
2550 ElfW(Phdr) *phdr;2539 ElfW(Phdr) *phdr;
2551 Section *interp, *dynamic, *dynstr, *note;2540 Section *interp, *dynamic, *dynstr, *note;
2552 struct ro_inf *roinf_use = NULL;2541 struct ro_inf *roinf_use = NULL;
2553 int textrel;2542 int textrel, got_sym;
2554 2543
2555 file_type = s1->output_type;2544 file_type = s1->output_type;
2556 s1->nb_errors = 0;2545 s1->nb_errors = 0;
@@ -2603,22 +2592,22 @@ static int elf_output_file(TCCState *s1, const char *filename) · 46 unmodified lines
2603 dynamic->link = dynstr;2592 dynamic->link = dynstr;
2604 dynamic->sh_entsize = sizeof(ElfW(Dyn));2593 dynamic->sh_entsize = sizeof(ElfW(Dyn));
2605 2594
2606 if (!s1->got)2595 got_sym = build_got(s1);
2607 build_got(s1);
2608
2609 if (file_type == TCC_OUTPUT_EXE) {2596 if (file_type == TCC_OUTPUT_EXE) {
2610 bind_exe_dynsyms(s1);2597 bind_exe_dynsyms(s1);
2611 if (s1->nb_errors)2598 if (s1->nb_errors)
2612 goto the_end;2599 goto the_end;
2600 }
2601 build_got_entries(s1, got_sym);
2602 if (file_type == TCC_OUTPUT_EXE) {
2613 bind_libs_dynsyms(s1);2603 bind_libs_dynsyms(s1);
2614 } else {2604 } else {
2615 /* shared library case: simply export all global symbols */2605 /* shared library case: simply export all global symbols */
2616 export_global_syms(s1);2606 export_global_syms(s1);
2617 }2607 }
2608 } else {
2609 build_got_entries(s1, 0);
2618 }2610 }
2619 build_got_entries(s1);
2620 elf_patch_global_offset_size(s1, symtab_section);
2621 elf_patch_global_offset_size(s1, s1->dynsym);
2622 version_add (s1);2611 version_add (s1);
2623 }2612 }
2624 2613
tccrun.c+1−1
@@ -261,7 +261,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) · 260 unmodified lines
261#else261#else
262 tcc_add_runtime(s1);262 tcc_add_runtime(s1);
263 resolve_common_syms(s1);263 resolve_common_syms(s1);
264 build_got_entries(s1);264 build_got_entries(s1, 0);
265#endif265#endif
266 if (s1->nb_errors)266 if (s1->nb_errors)
267 return -1;267 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