| @@ -1039,15 +1039,15 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) · 1038 unmodified lines |
| 1039 | 1039 | #endif |
| 1040 | 1040 | |
| 1041 | 1041 | #ifdef NEED_BUILD_GOT |
| 1042 | | −static void build_got(TCCState *s1) |
| 1042 | +static int build_got(TCCState *s1) |
| 1043 | 1043 | { |
| 1044 | 1044 | /* if no got, then create it */ |
| 1045 | 1045 | s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
| 1046 | 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 | 1047 | /* keep space for _DYNAMIC pointer and two dummy got entries */ |
| 1050 | 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 | 1053 | /* 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 | 1152 | /* build GOT and PLT entries */ |
| 1153 | 1153 | /* Two passes because R_JMP_SLOT should become first. Some targets |
| 1154 | 1154 | (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) |
| 1156 | 1156 | { |
| 1157 | 1157 | Section *s; |
| 1158 | 1158 | ElfW_Rel *rel; |
| @@ -1160,7 +1160,6 @@ ST_FUNC void build_got_entries(TCCState *s1) · 1 unmodified line |
| 1160 | 1160 | int i, type, gotplt_entry, reloc_type, sym_index; |
| 1161 | 1161 | struct sym_attr *attr; |
| 1162 | 1162 | int pass = 0; |
| 1163 | | − |
| 1164 | 1163 | redo: |
| 1165 | 1164 | for(i = 1; i < s1->nb_sections; i++) { |
| 1166 | 1165 | s = s1->sections[i]; |
| @@ -1252,7 +1251,7 @@ redo: · 85 unmodified lines |
| 1252 | 1251 | } |
| 1253 | 1252 | |
| 1254 | 1253 | if (!s1->got) |
| 1255 | | − build_got(s1); |
| 1254 | + got_sym = build_got(s1); |
| 1256 | 1255 | |
| 1257 | 1256 | if (gotplt_entry == BUILD_GOT_ONLY) |
| 1258 | 1257 | continue; |
| @@ -1265,11 +1264,11 @@ redo: · 6 unmodified lines |
| 1265 | 1264 | } |
| 1266 | 1265 | if (++pass < 2) |
| 1267 | 1266 | goto redo; |
| 1268 | | − |
| 1269 | 1267 | /* .rel.plt refers to .got actually */ |
| 1270 | 1268 | if (s1->plt && s1->plt->reloc) |
| 1271 | 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 | 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 | 1682 | /* 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 */ |
| 1686 | 1684 | static void bind_exe_dynsyms(TCCState *s1) |
| 1687 | 1685 | { |
| 1688 | 1686 | const char *name; |
| @@ -1755,11 +1753,6 @@ static void bind_exe_dynsyms(TCCState *s1) · 66 unmodified lines |
| 1755 | 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 | 1761 | are referenced by shared libraries. The reason is that the dynamic loader |
| 1769 | 1762 | search symbol first in executable and then in libraries. Therefore a |
| 1770 | 1763 | 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 */ |
| 1772 | 1765 | static void bind_libs_dynsyms(TCCState *s1) |
| 1773 | 1766 | { |
| 1774 | 1767 | const char *name; |
| 1775 | | − int sym_index; |
| 1768 | + int dynsym_index; |
| 1776 | 1769 | ElfW(Sym) *sym, *esym; |
| 1777 | 1770 | |
| 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 |
| 1783 | 1775 | && 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 | + } |
| 1790 | 1786 | } |
| 1791 | 1787 | } |
| 1792 | 1788 | } |
| @@ -1800,11 +1796,10 @@ static void export_global_syms(TCCState *s1) · 7 unmodified lines |
| 1800 | 1796 | int dynindex, index; |
| 1801 | 1797 | const char *name; |
| 1802 | 1798 | ElfW(Sym) *sym; |
| 1803 | | − |
| 1804 | 1799 | for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { |
| 1805 | 1800 | if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { |
| 1806 | 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 | 1803 | sym->st_info, 0, sym->st_shndx, name); |
| 1809 | 1804 | index = sym - (ElfW(Sym) *) symtab_section->data; |
| 1810 | 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 | 2528 | #endif |
| 2534 | 2529 | |
| 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); |
| 2542 | 2531 | |
| 2543 | 2532 | /* Output an elf, coff or binary file */ |
| 2544 | 2533 | /* XXX: suppress unneeded sections */ |
| @@ -2550,7 +2539,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 5 unmodified lines |
| 2550 | 2539 | ElfW(Phdr) *phdr; |
| 2551 | 2540 | Section *interp, *dynamic, *dynstr, *note; |
| 2552 | 2541 | struct ro_inf *roinf_use = NULL; |
| 2553 | | − int textrel; |
| 2542 | + int textrel, got_sym; |
| 2554 | 2543 | |
| 2555 | 2544 | file_type = s1->output_type; |
| 2556 | 2545 | s1->nb_errors = 0; |
| @@ -2603,22 +2592,22 @@ static int elf_output_file(TCCState *s1, const char *filename) · 46 unmodified lines |
| 2603 | 2592 | dynamic->link = dynstr; |
| 2604 | 2593 | dynamic->sh_entsize = sizeof(ElfW(Dyn)); |
| 2605 | 2594 | |
| 2606 | | − if (!s1->got) |
| 2607 | | − build_got(s1); |
| 2608 | | − |
| 2595 | + got_sym = build_got(s1); |
| 2609 | 2596 | if (file_type == TCC_OUTPUT_EXE) { |
| 2610 | 2597 | bind_exe_dynsyms(s1); |
| 2611 | 2598 | if (s1->nb_errors) |
| 2612 | 2599 | goto the_end; |
| 2600 | + } |
| 2601 | + build_got_entries(s1, got_sym); |
| 2602 | + if (file_type == TCC_OUTPUT_EXE) { |
| 2613 | 2603 | bind_libs_dynsyms(s1); |
| 2614 | 2604 | } else { |
| 2615 | 2605 | /* shared library case: simply export all global symbols */ |
| 2616 | 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 | 2611 | version_add (s1); |
| 2623 | 2612 | } |
| 2624 | 2613 | |