| @@ -1039,15 +1039,15 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) · 1038 unmodified lines |
| 1039 | #endif | 1039 | #endif |
| 1040 | | 1040 | |
| 1041 | #ifdef NEED_BUILD_GOT | 1041 | #ifdef NEED_BUILD_GOT |
| 1042 | static void build_got(TCCState *s1) | 1042 | static 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 symbol | 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 | /* build GOT and PLT entries */ | 1152 | /* build GOT and PLT entries */ |
| 1153 | /* Two passes because R_JMP_SLOT should become first. Some targets | 1153 | /* 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. */ |
| 1155 | ST_FUNC void build_got_entries(TCCState *s1) | 1155 | ST_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 | | | |
| 1164 | redo: | 1163 | redo: |
| 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 symbols | 1682 | /* Bind symbols of executable: resolve undefined symbols from exported symbols |
| 1684 | in shared libraries and export non local defined symbols to shared libraries | 1683 | in shared libraries */ |
| 1685 | if -rdynamic switch was given on command line */ | | |
| 1686 | static void bind_exe_dynsyms(TCCState *s1) | 1684 | static 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 loader | 1761 | are referenced by shared libraries. The reason is that the dynamic loader |
| 1769 | search symbol first in executable and then in libraries. Therefore a | 1762 | 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 by | 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 | static void bind_libs_dynsyms(TCCState *s1) | 1765 | static 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 | #endif | 2528 | #endif |
| 2534 | | 2529 | |
| 2535 | static void elf_patch_global_offset_size(TCCState *s1, Section *s) | 2530 | static 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 | |