| @@ -49,13 +49,14 @@ struct sym_version { · 48 unmodified lines |
| 49 | int out_index; | 49 | int out_index; |
| 50 | int prev_same_lib; | 50 | int prev_same_lib; |
| 51 | }; | 51 | }; |
| 52 | static int nb_sym_versions; | 52 | |
| 53 | static struct sym_version *sym_versions; | 53 | #define nb_sym_versions s1->nb_sym_versions |
| 54 | static int nb_sym_to_version; | 54 | #define sym_versions s1->sym_versions |
| 55 | static int *sym_to_version; | 55 | #define nb_sym_to_version s1->nb_sym_to_version |
| 56 | static int dt_verneednum; | 56 | #define sym_to_version s1->sym_to_version |
| 57 | static Section *versym_section; | 57 | #define dt_verneednum s1->dt_verneednum |
| 58 | static Section *verneed_section; | 58 | #define versym_section s1->versym_section |
| | 59 | #define verneed_section s1->verneed_section |
| 59 | | 60 | |
| 60 | /* XXX: avoid static variable */ | 61 | /* XXX: avoid static variable */ |
| 61 | static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */ | 62 | static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */ |
| @@ -76,9 +77,6 @@ ST_FUNC void tccelf_new(TCCState *s) · 14 unmodified lines |
| 76 | text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); | 77 | text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); |
| 77 | data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); | 78 | data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
| 78 | bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); | 79 | bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); |
| 79 | versym_section = new_section(s, ".gnu.version", SHT_GNU_versym, SHF_ALLOC); | | |
| 80 | versym_section->sh_entsize = sizeof(ElfW(Half)); | | |
| 81 | verneed_section = new_section(s, ".gnu.version_r", SHT_GNU_verneed, SHF_ALLOC); | | |
| 82 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); | 80 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); |
| 83 | common_section->sh_num = SHN_COMMON; | 81 | common_section->sh_num = SHN_COMMON; |
| 84 | | 82 | |
| @@ -126,17 +124,15 @@ ST_FUNC void tccelf_delete(TCCState *s1) · 41 unmodified lines |
| 126 | { | 124 | { |
| 127 | int i; | 125 | int i; |
| 128 | | 126 | |
| | 127 | #ifndef ELF_OBJ_ONLY |
| 129 | /* free symbol versions */ | 128 | /* free symbol versions */ |
| 130 | for (i = 0; i < nb_sym_versions; i++) { | 129 | for (i = 0; i < nb_sym_versions; i++) { |
| 131 | tcc_free(sym_versions[i].version); | 130 | tcc_free(sym_versions[i].version); |
| 132 | tcc_free(sym_versions[i].lib); | 131 | tcc_free(sym_versions[i].lib); |
| 133 | } | 132 | } |
| 134 | tcc_free(sym_versions); | 133 | tcc_free(sym_versions); |
| 135 | sym_versions = NULL; | | |
| 136 | nb_sym_versions = 0; | | |
| 137 | tcc_free(sym_to_version); | 134 | tcc_free(sym_to_version); |
| 138 | sym_to_version = NULL; | 135 | #endif |
| 139 | nb_sym_to_version = 0; | | |
| 140 | | 136 | |
| 141 | /* free all sections */ | 137 | /* free all sections */ |
| 142 | for(i = 1; i < s1->nb_sections; i++) | 138 | for(i = 1; i < s1->nb_sections; i++) |
| @@ -556,6 +552,7 @@ ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name) · 413 unmodified lines |
| 556 | } | 552 | } |
| 557 | #endif | 553 | #endif |
| 558 | | 554 | |
| | 555 | #ifndef ELF_OBJ_ONLY |
| 559 | static void | 556 | static void |
| 560 | version_add (TCCState *s) | 557 | version_add (TCCState *s) |
| 561 | { | 558 | { |
| @@ -566,6 +563,15 @@ version_add (TCCState *s) · 4 unmodified lines |
| 566 | int sym_index, end_sym, nb_versions = 2, nb_entries = 0; | 563 | int sym_index, end_sym, nb_versions = 2, nb_entries = 0; |
| 567 | ElfW(Half) *versym; | 564 | ElfW(Half) *versym; |
| 568 | const char *name; | 565 | const char *name; |
| | 566 | TCCState *s1 = s; |
| | 567 | |
| | 568 | if (0 == nb_sym_versions) |
| | 569 | return; |
| | 570 | versym_section = new_section(s1, ".gnu.version", SHT_GNU_versym, SHF_ALLOC); |
| | 571 | versym_section->sh_entsize = sizeof(ElfW(Half)); |
| | 572 | verneed_section = new_section(s1, ".gnu.version_r", SHT_GNU_verneed, SHF_ALLOC); |
| | 573 | versym_section->link = s1->dynsym; |
| | 574 | verneed_section->link = s1->dynsym->link; |
| 569 | | 575 | |
| 570 | /* add needed symbols */ | 576 | /* add needed symbols */ |
| 571 | symtab = s->dynsym; | 577 | symtab = s->dynsym; |
| @@ -590,7 +596,7 @@ version_add (TCCState *s) · 18 unmodified lines |
| 590 | struct sym_version *sv = &sym_versions[i]; | 596 | struct sym_version *sv = &sym_versions[i]; |
| 591 | int n_same_libs = 0, prev; | 597 | int n_same_libs = 0, prev; |
| 592 | size_t vnofs; | 598 | size_t vnofs; |
| 593 | ElfW(Vernaux) *vna = vna; | 599 | ElfW(Vernaux) *vna = 0; |
| 594 | if (sv->out_index < 1) | 600 | if (sv->out_index < 1) |
| 595 | continue; | 601 | continue; |
| 596 | vnofs = section_add(verneed_section, sizeof(*vn), 1); | 602 | vnofs = section_add(verneed_section, sizeof(*vn), 1); |
| @@ -623,6 +629,7 @@ version_add (TCCState *s) · 26 unmodified lines |
| 623 | verneed_section->sh_info = nb_entries; | 629 | verneed_section->sh_info = nb_entries; |
| 624 | dt_verneednum = nb_entries; | 630 | dt_verneednum = nb_entries; |
| 625 | } | 631 | } |
| | 632 | #endif |
| 626 | | 633 | |
| 627 | /* add an elf symbol : check if it is already defined and patch | 634 | /* add an elf symbol : check if it is already defined and patch |
| 628 | it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ | 635 | it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ |
| @@ -970,7 +977,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 341 unmodified lines |
| 970 | unsigned char *ptr; | 977 | unsigned char *ptr; |
| 971 | addr_t tgt, addr; | 978 | addr_t tgt, addr; |
| 972 | | 979 | |
| 973 | relocate_init(sr); | 980 | qrel = (ElfW_Rel *)sr->data; |
| 974 | | 981 | |
| 975 | for_each_elem(sr, 0, rel, ElfW_Rel) { | 982 | for_each_elem(sr, 0, rel, ElfW_Rel) { |
| 976 | ptr = s->data + rel->r_offset; | 983 | ptr = s->data + rel->r_offset; |
| @@ -989,6 +996,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 12 unmodified lines |
| 989 | sr->link = s1->dynsym; | 996 | sr->link = s1->dynsym; |
| 990 | } | 997 | } |
| 991 | | 998 | |
| | 999 | #ifndef ELF_OBJ_ONLY |
| 992 | /* relocate relocation table in 'sr' */ | 1000 | /* relocate relocation table in 'sr' */ |
| 993 | static void relocate_rel(TCCState *s1, Section *sr) | 1001 | static void relocate_rel(TCCState *s1, Section *sr) |
| 994 | { | 1002 | { |
| @@ -1255,6 +1263,7 @@ static void put_dt(Section *dynamic, int dt, addr_t val) · 260 unmodified lines |
| 1255 | dyn->d_tag = dt; | 1263 | dyn->d_tag = dt; |
| 1256 | dyn->d_un.d_val = val; | 1264 | dyn->d_un.d_val = val; |
| 1257 | } | 1265 | } |
| | 1266 | #endif |
| 1258 | | 1267 | |
| 1259 | static void add_init_array_defines(TCCState *s1, const char *section_name) | 1268 | static void add_init_array_defines(TCCState *s1, const char *section_name) |
| 1260 | { | 1269 | { |
| @@ -1459,6 +1468,7 @@ static void tcc_output_binary(TCCState *s1, FILE *f, · 198 unmodified lines |
| 1459 | } | 1468 | } |
| 1460 | } | 1469 | } |
| 1461 | | 1470 | |
| | 1471 | #ifndef ELF_OBJ_ONLY |
| 1462 | ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) | 1472 | ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) |
| 1463 | { | 1473 | { |
| 1464 | int sym_index = ELFW(R_SYM) (rel->r_info); | 1474 | int sym_index = ELFW(R_SYM) (rel->r_info); |
| @@ -1661,6 +1671,7 @@ static void export_global_syms(TCCState *s1) · 196 unmodified lines |
| 1661 | } | 1671 | } |
| 1662 | } | 1672 | } |
| 1663 | } | 1673 | } |
| | 1674 | #endif |
| 1664 | | 1675 | |
| 1665 | /* Allocate strings for section names and decide if an unallocated section | 1676 | /* Allocate strings for section names and decide if an unallocated section |
| 1666 | should be output. | 1677 | should be output. |
| @@ -1676,6 +1687,7 @@ static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec) · 9 unmodified lines |
| 1676 | s = s1->sections[i]; | 1687 | s = s1->sections[i]; |
| 1677 | /* when generating a DLL, we include relocations but we may | 1688 | /* when generating a DLL, we include relocations but we may |
| 1678 | patch them */ | 1689 | patch them */ |
| | 1690 | #ifndef ELF_OBJ_ONLY |
| 1679 | if (file_type == TCC_OUTPUT_DLL && | 1691 | if (file_type == TCC_OUTPUT_DLL && |
| 1680 | s->sh_type == SHT_RELX && | 1692 | s->sh_type == SHT_RELX && |
| 1681 | !(s->sh_flags & SHF_ALLOC) && | 1693 | !(s->sh_flags & SHF_ALLOC) && |
| @@ -1683,7 +1695,9 @@ static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec) · 1 unmodified line |
| 1683 | prepare_dynamic_rel(s1, s)) { | 1695 | prepare_dynamic_rel(s1, s)) { |
| 1684 | if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR) | 1696 | if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR) |
| 1685 | textrel = 1; | 1697 | textrel = 1; |
| 1686 | } else if ((s1->do_debug && s->sh_type != SHT_RELX) || | 1698 | } else |
| | 1699 | #endif |
| | 1700 | if ((s1->do_debug && s->sh_type != SHT_RELX) || |
| 1687 | file_type == TCC_OUTPUT_OBJ || | 1701 | file_type == TCC_OUTPUT_OBJ || |
| 1688 | (s->sh_flags & SHF_ALLOC) || | 1702 | (s->sh_flags & SHF_ALLOC) || |
| 1689 | i == (s1->nb_sections - 1)) { | 1703 | i == (s1->nb_sections - 1)) { |
| @@ -1890,6 +1904,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 200 unmodified lines |
| 1890 | return file_offset; | 1904 | return file_offset; |
| 1891 | } | 1905 | } |
| 1892 | | 1906 | |
| | 1907 | #ifndef ELF_OBJ_ONLY |
| 1893 | static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, | 1908 | static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, |
| 1894 | Section *dynamic) | 1909 | Section *dynamic) |
| 1895 | { | 1910 | { |
| @@ -1964,9 +1979,11 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) · 68 unmodified lines |
| 1964 | put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel)); | 1979 | put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel)); |
| 1965 | #endif | 1980 | #endif |
| 1966 | #endif | 1981 | #endif |
| 1967 | put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr); | 1982 | if (versym_section) { |
| 1968 | put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum); | 1983 | put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr); |
| 1969 | put_dt(dynamic, DT_VERSYM, versym_section->sh_addr); | 1984 | put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum); |
| | 1985 | put_dt(dynamic, DT_VERSYM, versym_section->sh_addr); |
| | 1986 | } |
| 1970 | s = find_section_create (s1, ".preinit_array", 0); | 1987 | s = find_section_create (s1, ".preinit_array", 0); |
| 1971 | if (s && s->data_offset) { | 1988 | if (s && s->data_offset) { |
| 1972 | put_dt(dynamic, DT_PREINIT_ARRAY, s->sh_addr); | 1989 | put_dt(dynamic, DT_PREINIT_ARRAY, s->sh_addr); |
| @@ -2026,6 +2043,7 @@ static int final_sections_reloc(TCCState *s1) · 53 unmodified lines |
| 2026 | } | 2043 | } |
| 2027 | return 0; | 2044 | return 0; |
| 2028 | } | 2045 | } |
| | 2046 | #endif |
| 2029 | | 2047 | |
| 2030 | /* Create an ELF file on disk. | 2048 | /* Create an ELF file on disk. |
| 2031 | This function handle ELF specific layout requirements */ | 2049 | This function handle ELF specific layout requirements */ |
| @@ -2183,6 +2201,7 @@ static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum, · 151 unmodified lines |
| 2183 | return 0; | 2201 | return 0; |
| 2184 | } | 2202 | } |
| 2185 | | 2203 | |
| | 2204 | #ifndef ELF_OBJ_ONLY |
| 2186 | /* Sort section headers by assigned sh_addr, remove sections | 2205 | /* Sort section headers by assigned sh_addr, remove sections |
| 2187 | that we aren't going to output. */ | 2206 | that we aren't going to output. */ |
| 2188 | static void tidy_section_headers(TCCState *s1, int *sec_order) | 2207 | static void tidy_section_headers(TCCState *s1, int *sec_order) |
| @@ -2228,17 +2247,16 @@ static void tidy_section_headers(TCCState *s1, int *sec_order) · 39 unmodified lines |
| 2228 | s1->nb_sections = nnew; | 2247 | s1->nb_sections = nnew; |
| 2229 | tcc_free(backmap); | 2248 | tcc_free(backmap); |
| 2230 | } | 2249 | } |
| | 2250 | #endif |
| 2231 | | 2251 | |
| 2232 | /* Output an elf, coff or binary file */ | 2252 | /* Output an elf, coff or binary file */ |
| 2233 | /* XXX: suppress unneeded sections */ | 2253 | /* XXX: suppress unneeded sections */ |
| 2234 | static int elf_output_file(TCCState *s1, const char *filename) | 2254 | static int elf_output_file(TCCState *s1, const char *filename) |
| 2235 | { | 2255 | { |
| 2236 | int i, ret, phnum, shnum, file_type, file_offset, *sec_order; | 2256 | int ret, phnum, shnum, file_type, file_offset, *sec_order; |
| 2237 | struct dyn_inf dyninf = {0}; | 2257 | struct dyn_inf dyninf = {0}; |
| 2238 | ElfW(Phdr) *phdr; | 2258 | ElfW(Phdr) *phdr; |
| 2239 | ElfW(Sym) *sym; | | |
| 2240 | Section *strsec, *interp, *dynamic, *dynstr; | 2259 | Section *strsec, *interp, *dynamic, *dynstr; |
| 2241 | int textrel; | | |
| 2242 | | 2260 | |
| 2243 | file_type = s1->output_type; | 2261 | file_type = s1->output_type; |
| 2244 | s1->nb_errors = 0; | 2262 | s1->nb_errors = 0; |
| @@ -2246,8 +2264,8 @@ static int elf_output_file(TCCState *s1, const char *filename) · 1 unmodified line |
| 2246 | phdr = NULL; | 2264 | phdr = NULL; |
| 2247 | sec_order = NULL; | 2265 | sec_order = NULL; |
| 2248 | interp = dynamic = dynstr = NULL; /* avoid warning */ | 2266 | interp = dynamic = dynstr = NULL; /* avoid warning */ |
| 2249 | textrel = 0; | | |
| 2250 | | 2267 | |
| | 2268 | #ifndef ELF_OBJ_ONLY |
| 2251 | if (file_type != TCC_OUTPUT_OBJ) { | 2269 | if (file_type != TCC_OUTPUT_OBJ) { |
| 2252 | /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ | 2270 | /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ |
| 2253 | tcc_add_runtime(s1); | 2271 | tcc_add_runtime(s1); |
| @@ -2272,9 +2290,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 18 unmodified lines |
| 2272 | ".dynstr", | 2290 | ".dynstr", |
| 2273 | ".hash", SHF_ALLOC); | 2291 | ".hash", SHF_ALLOC); |
| 2274 | dynstr = s1->dynsym->link; | 2292 | dynstr = s1->dynsym->link; |
| 2275 | versym_section->link = s1->dynsym; | | |
| 2276 | verneed_section->link = dynstr; | | |
| 2277 | | | |
| 2278 | /* add dynamic section */ | 2293 | /* add dynamic section */ |
| 2279 | dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, | 2294 | dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, |
| 2280 | SHF_ALLOC | SHF_WRITE); | 2295 | SHF_ALLOC | SHF_WRITE); |
| @@ -2296,15 +2311,18 @@ static int elf_output_file(TCCState *s1, const char *filename) · 15 unmodified lines |
| 2296 | build_got_entries(s1); | 2311 | build_got_entries(s1); |
| 2297 | version_add (s1); | 2312 | version_add (s1); |
| 2298 | } | 2313 | } |
| | 2314 | #endif |
| 2299 | | 2315 | |
| 2300 | /* we add a section for symbols */ | 2316 | /* we add a section for symbols */ |
| 2301 | strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0); | 2317 | strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0); |
| 2302 | put_elf_str(strsec, ""); | 2318 | put_elf_str(strsec, ""); |
| 2303 | | 2319 | |
| 2304 | /* Allocate strings for section names */ | 2320 | /* Allocate strings for section names */ |
| 2305 | textrel = alloc_sec_names(s1, file_type, strsec); | 2321 | ret = alloc_sec_names(s1, file_type, strsec); |
| 2306 | | 2322 | |
| | 2323 | #ifndef ELF_OBJ_ONLY |
| 2307 | if (dynamic) { | 2324 | if (dynamic) { |
| | 2325 | int i; |
| 2308 | /* add a list of needed dlls */ | 2326 | /* add a list of needed dlls */ |
| 2309 | for(i = 0; i < s1->nb_loaded_dlls; i++) { | 2327 | for(i = 0; i < s1->nb_loaded_dlls; i++) { |
| 2310 | DLLReference *dllref = s1->loaded_dlls[i]; | 2328 | DLLReference *dllref = s1->loaded_dlls[i]; |
| @@ -2321,7 +2339,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 10 unmodified lines |
| 2321 | put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); | 2339 | put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); |
| 2322 | /* XXX: currently, since we do not handle PIC code, we | 2340 | /* XXX: currently, since we do not handle PIC code, we |
| 2323 | must relocate the readonly segments */ | 2341 | must relocate the readonly segments */ |
| 2324 | if (textrel) | 2342 | if (ret) |
| 2325 | put_dt(dynamic, DT_TEXTREL, 0); | 2343 | put_dt(dynamic, DT_TEXTREL, 0); |
| 2326 | } | 2344 | } |
| 2327 | | 2345 | |
| @@ -2336,6 +2354,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 8 unmodified lines |
| 2336 | dynamic->sh_size = dynamic->data_offset; | 2354 | dynamic->sh_size = dynamic->data_offset; |
| 2337 | dynstr->sh_size = dynstr->data_offset; | 2355 | dynstr->sh_size = dynstr->data_offset; |
| 2338 | } | 2356 | } |
| | 2357 | #endif |
| 2339 | | 2358 | |
| 2340 | /* compute number of program headers */ | 2359 | /* compute number of program headers */ |
| 2341 | if (file_type == TCC_OUTPUT_OBJ) | 2360 | if (file_type == TCC_OUTPUT_OBJ) |
| @@ -2361,11 +2380,13 @@ static int elf_output_file(TCCState *s1, const char *filename) · 19 unmodified lines |
| 2361 | file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf, | 2380 | file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf, |
| 2362 | sec_order); | 2381 | sec_order); |
| 2363 | | 2382 | |
| | 2383 | #ifndef ELF_OBJ_ONLY |
| 2364 | /* Fill remaining program header and finalize relocation related to dynamic | 2384 | /* Fill remaining program header and finalize relocation related to dynamic |
| 2365 | linking. */ | 2385 | linking. */ |
| 2366 | if (file_type != TCC_OUTPUT_OBJ) { | 2386 | if (file_type != TCC_OUTPUT_OBJ) { |
| 2367 | fill_unloadable_phdr(phdr, phnum, interp, dynamic); | 2387 | fill_unloadable_phdr(phdr, phnum, interp, dynamic); |
| 2368 | if (dynamic) { | 2388 | if (dynamic) { |
| | 2389 | ElfW(Sym) *sym; |
| 2369 | dynamic->data_offset = dyninf.data_offset; | 2390 | dynamic->data_offset = dyninf.data_offset; |
| 2370 | fill_dynamic(s1, &dyninf); | 2391 | fill_dynamic(s1, &dyninf); |
| 2371 | | 2392 | |
| @@ -2397,10 +2418,12 @@ static int elf_output_file(TCCState *s1, const char *filename) · 25 unmodified lines |
| 2397 | else if (s1->got) | 2418 | else if (s1->got) |
| 2398 | fill_local_got_entries(s1); | 2419 | fill_local_got_entries(s1); |
| 2399 | } | 2420 | } |
| | 2421 | #endif |
| 2400 | | 2422 | |
| 2401 | /* Create the ELF file with name 'filename' */ | 2423 | /* Create the ELF file with name 'filename' */ |
| 2402 | ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); | 2424 | ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); |
| 2403 | s1->nb_sections = shnum; | 2425 | s1->nb_sections = shnum; |
| | 2426 | goto the_end; |
| 2404 | the_end: | 2427 | the_end: |
| 2405 | tcc_free(sec_order); | 2428 | tcc_free(sec_order); |
| 2406 | tcc_free(phdr); | 2429 | tcc_free(phdr); |
| @@ -2885,10 +2908,10 @@ ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte) · 478 unmodified lines |
| 2885 | return 0; | 2908 | return 0; |
| 2886 | } | 2909 | } |
| 2887 | | 2910 | |
| 2888 | #ifndef TCC_TARGET_PE | 2911 | #ifndef ELF_OBJ_ONLY |
| 2889 | /* Set LV[I] to the global index of sym-version (LIB,VERSION). Maybe resizes | 2912 | /* Set LV[I] to the global index of sym-version (LIB,VERSION). Maybe resizes |
| 2890 | LV, maybe create a new entry for (LIB,VERSION). */ | 2913 | LV, maybe create a new entry for (LIB,VERSION). */ |
| 2891 | static void set_ver_to_ver(int *n, int **lv, int i, char *lib, char *version) | 2914 | static void set_ver_to_ver(TCCState *s1, int *n, int **lv, int i, char *lib, char *version) |
| 2892 | { | 2915 | { |
| 2893 | while (i >= *n) { | 2916 | while (i >= *n) { |
| 2894 | *lv = tcc_realloc(*lv, (*n + 1) * sizeof(**lv)); | 2917 | *lv = tcc_realloc(*lv, (*n + 1) * sizeof(**lv)); |
| @@ -2919,7 +2942,7 @@ static void set_ver_to_ver(int *n, int **lv, int i, char *lib, char *version) · 24 unmodified lines |
| 2919 | /* Associates symbol SYM_INDEX (in dynsymtab) with sym-version index | 2942 | /* Associates symbol SYM_INDEX (in dynsymtab) with sym-version index |
| 2920 | VERNDX. */ | 2943 | VERNDX. */ |
| 2921 | static void | 2944 | static void |
| 2922 | set_sym_version(int sym_index, int verndx) | 2945 | set_sym_version(TCCState *s1, int sym_index, int verndx) |
| 2923 | { | 2946 | { |
| 2924 | if (sym_index >= nb_sym_to_version) { | 2947 | if (sym_index >= nb_sym_to_version) { |
| 2925 | int newelems = sym_index ? sym_index * 2 : 1; | 2948 | int newelems = sym_index ? sym_index * 2 : 1; |
| @@ -2933,6 +2956,90 @@ set_sym_version(int sym_index, int verndx) · 7 unmodified lines |
| 2933 | sym_to_version[sym_index] = verndx; | 2956 | sym_to_version[sym_index] = verndx; |
| 2934 | } | 2957 | } |
| 2935 | | 2958 | |
| | 2959 | struct versym_info { |
| | 2960 | int nb_versyms; |
| | 2961 | ElfW(Verdef) *verdef; |
| | 2962 | ElfW(Verneed) *verneed; |
| | 2963 | ElfW(Half) *versym; |
| | 2964 | int nb_local_ver, *local_ver; |
| | 2965 | }; |
| | 2966 | |
| | 2967 | |
| | 2968 | static void store_version(TCCState *s1, struct versym_info *v, char *dynstr) |
| | 2969 | { |
| | 2970 | char *lib, *version; |
| | 2971 | uint32_t next; |
| | 2972 | int i; |
| | 2973 | |
| | 2974 | #define DEBUG_VERSION 0 |
| | 2975 | |
| | 2976 | if (v->versym && v->verdef) { |
| | 2977 | ElfW(Verdef) *vdef = v->verdef; |
| | 2978 | lib = NULL; |
| | 2979 | do { |
| | 2980 | ElfW(Verdaux) *verdaux = |
| | 2981 | (ElfW(Verdaux) *) (((char *) vdef) + vdef->vd_aux); |
| | 2982 | |
| | 2983 | #if DEBUG_VERSION |
| | 2984 | printf ("verdef: version:%u flags:%u index:%u, hash:%u\n", |
| | 2985 | vdef->vd_version, vdef->vd_flags, vdef->vd_ndx, |
| | 2986 | vdef->vd_hash); |
| | 2987 | #endif |
| | 2988 | if (vdef->vd_cnt) { |
| | 2989 | version = dynstr + verdaux->vda_name; |
| | 2990 | |
| | 2991 | if (lib == NULL) |
| | 2992 | lib = version; |
| | 2993 | else |
| | 2994 | set_ver_to_ver(s1, &v->nb_local_ver, &v->local_ver, vdef->vd_ndx, |
| | 2995 | lib, version); |
| | 2996 | #if DEBUG_VERSION |
| | 2997 | printf (" verdaux(%u): %s\n", vdef->vd_ndx, version); |
| | 2998 | #endif |
| | 2999 | } |
| | 3000 | next = vdef->vd_next; |
| | 3001 | vdef = (ElfW(Verdef) *) (((char *) vdef) + next); |
| | 3002 | } while (next); |
| | 3003 | } |
| | 3004 | if (v->versym && v->verneed) { |
| | 3005 | ElfW(Verneed) *vneed = v->verneed; |
| | 3006 | do { |
| | 3007 | ElfW(Vernaux) *vernaux = |
| | 3008 | (ElfW(Vernaux) *) (((char *) vneed) + vneed->vn_aux); |
| | 3009 | |
| | 3010 | lib = dynstr + vneed->vn_file; |
| | 3011 | #if DEBUG_VERSION |
| | 3012 | printf ("verneed: %u %s\n", vneed->vn_version, lib); |
| | 3013 | #endif |
| | 3014 | for (i = 0; i < vneed->vn_cnt; i++) { |
| | 3015 | if ((vernaux->vna_other & 0x8000) == 0) { /* hidden */ |
| | 3016 | version = dynstr + vernaux->vna_name; |
| | 3017 | set_ver_to_ver(s1, &v->nb_local_ver, &v->local_ver, vernaux->vna_other, |
| | 3018 | lib, version); |
| | 3019 | #if DEBUG_VERSION |
| | 3020 | printf (" vernaux(%u): %u %u %s\n", |
| | 3021 | vernaux->vna_other, vernaux->vna_hash, |
| | 3022 | vernaux->vna_flags, version); |
| | 3023 | #endif |
| | 3024 | } |
| | 3025 | vernaux = (ElfW(Vernaux) *) (((char *) vernaux) + vernaux->vna_next); |
| | 3026 | } |
| | 3027 | next = vneed->vn_next; |
| | 3028 | vneed = (ElfW(Verneed) *) (((char *) vneed) + next); |
| | 3029 | } while (next); |
| | 3030 | } |
| | 3031 | |
| | 3032 | #if DEBUG_VERSION |
| | 3033 | for (i = 0; i < v->nb_local_ver; i++) { |
| | 3034 | if (v->local_ver[i] > 0) { |
| | 3035 | printf ("%d: lib: %s, version %s\n", |
| | 3036 | i, sym_versions[v->local_ver[i]].lib, |
| | 3037 | sym_versions[v->local_ver[i]].version); |
| | 3038 | } |
| | 3039 | } |
| | 3040 | #endif |
| | 3041 | } |
| | 3042 | |
| 2936 | /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL | 3043 | /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL |
| 2937 | is referenced by the user (so it should be added as DT_NEEDED in | 3044 | is referenced by the user (so it should be added as DT_NEEDED in |
| 2938 | the generated ELF file) */ | 3045 | the generated ELF file) */ |
| @@ -2943,17 +3050,12 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 4 unmodified lines |
| 2943 | int i, j, nb_syms, nb_dts, sym_bind, ret; | 3050 | int i, j, nb_syms, nb_dts, sym_bind, ret; |
| 2944 | ElfW(Sym) *sym, *dynsym; | 3051 | ElfW(Sym) *sym, *dynsym; |
| 2945 | ElfW(Dyn) *dt, *dynamic; | 3052 | ElfW(Dyn) *dt, *dynamic; |
| 2946 | int nb_versyms; | 3053 | |
| 2947 | ElfW(Verdef) *verdef, *vdef; | | |
| 2948 | ElfW(Verneed) *verneed, *vneed; | | |
| 2949 | ElfW(Half) *versym, *vsym; | | |
| 2950 | char *dynstr; | 3054 | char *dynstr; |
| 2951 | uint32_t next; | | |
| 2952 | int sym_index; | 3055 | int sym_index; |
| 2953 | char *lib, *version; | | |
| 2954 | int nb_local_ver = 0, *local_ver = NULL; | | |
| 2955 | const char *name, *soname; | 3056 | const char *name, *soname; |
| 2956 | DLLReference *dllref; | 3057 | DLLReference *dllref; |
| | 3058 | struct versym_info v; |
| 2957 | | 3059 | |
| 2958 | full_read(fd, &ehdr, sizeof(ehdr)); | 3060 | full_read(fd, &ehdr, sizeof(ehdr)); |
| 2959 | | 3061 | |
| @@ -2973,10 +3075,8 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 13 unmodified lines |
| 2973 | dynamic = NULL; | 3075 | dynamic = NULL; |
| 2974 | dynsym = NULL; /* avoid warning */ | 3076 | dynsym = NULL; /* avoid warning */ |
| 2975 | dynstr = NULL; /* avoid warning */ | 3077 | dynstr = NULL; /* avoid warning */ |
| 2976 | nb_versyms = 0; | 3078 | memset(&v, 0, sizeof v); |
| 2977 | verdef = NULL; | 3079 | |
| 2978 | verneed = NULL; | | |
| 2979 | versym = NULL; | | |
| 2980 | for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) { | 3080 | for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) { |
| 2981 | switch(sh->sh_type) { | 3081 | switch(sh->sh_type) { |
| 2982 | case SHT_DYNAMIC: | 3082 | case SHT_DYNAMIC: |
| @@ -2990,14 +3090,14 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 7 unmodified lines |
| 2990 | dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size); | 3090 | dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size); |
| 2991 | break; | 3091 | break; |
| 2992 | case SHT_GNU_verdef: | 3092 | case SHT_GNU_verdef: |
| 2993 | verdef = load_data(fd, sh->sh_offset, sh->sh_size); | 3093 | v.verdef = load_data(fd, sh->sh_offset, sh->sh_size); |
| 2994 | break; | 3094 | break; |
| 2995 | case SHT_GNU_verneed: | 3095 | case SHT_GNU_verneed: |
| 2996 | verneed = load_data(fd, sh->sh_offset, sh->sh_size); | 3096 | v.verneed = load_data(fd, sh->sh_offset, sh->sh_size); |
| 2997 | break; | 3097 | break; |
| 2998 | case SHT_GNU_versym: | 3098 | case SHT_GNU_versym: |
| 2999 | nb_versyms = sh->sh_size / sizeof(ElfW(Half)); | 3099 | v.nb_versyms = sh->sh_size / sizeof(ElfW(Half)); |
| 3000 | versym = load_data(fd, sh->sh_offset, sh->sh_size); | 3100 | v.versym = load_data(fd, sh->sh_offset, sh->sh_size); |
| 3001 | break; | 3101 | break; |
| 3002 | default: | 3102 | default: |
| 3003 | break; | 3103 | break; |
| @@ -3025,78 +3125,10 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 21 unmodified lines |
| 3025 | } | 3125 | } |
| 3026 | } | 3126 | } |
| 3027 | | 3127 | |
| 3028 | if (nb_versyms != nb_syms) { | 3128 | if (v.nb_versyms != nb_syms) |
| 3029 | tcc_free (versym); | 3129 | tcc_free (v.versym), v.versym = NULL; |
| 3030 | versym = NULL; | 3130 | else |
| 3031 | } | 3131 | store_version(s1, &v, dynstr); |
| 3032 | | | |
| 3033 | #define DEBUG_VERSION 0 | | |
| 3034 | | | |
| 3035 | if (versym && verdef) { | | |
| 3036 | lib = NULL; | | |
| 3037 | vdef = verdef; | | |
| 3038 | do { | | |
| 3039 | ElfW(Verdaux) *verdaux = | | |
| 3040 | (ElfW(Verdaux) *) (((char *) vdef) + vdef->vd_aux); | | |
| 3041 | | | |
| 3042 | #if DEBUG_VERSION | | |
| 3043 | printf ("verdef: version:%u flags:%u index:%u, hash:%u\n", | | |
| 3044 | vdef->vd_version, vdef->vd_flags, vdef->vd_ndx, | | |
| 3045 | vdef->vd_hash); | | |
| 3046 | #endif | | |
| 3047 | if (vdef->vd_cnt) { | | |
| 3048 | version = dynstr + verdaux->vda_name; | | |
| 3049 | | | |
| 3050 | if (lib == NULL) | | |
| 3051 | lib = version; | | |
| 3052 | else | | |
| 3053 | set_ver_to_ver(&nb_local_ver, &local_ver, vdef->vd_ndx, | | |
| 3054 | lib, version); | | |
| 3055 | #if DEBUG_VERSION | | |
| 3056 | printf (" verdaux(%u): %s\n", vdef->vd_ndx, version); | | |
| 3057 | #endif | | |
| 3058 | } | | |
| 3059 | next = vdef->vd_next; | | |
| 3060 | vdef = (ElfW(Verdef) *) (((char *) vdef) + next); | | |
| 3061 | } while (next); | | |
| 3062 | } | | |
| 3063 | if (versym && verneed) { | | |
| 3064 | vneed = verneed; | | |
| 3065 | do { | | |
| 3066 | ElfW(Vernaux) *vernaux = | | |
| 3067 | (ElfW(Vernaux) *) (((char *) vneed) + vneed->vn_aux); | | |
| 3068 | | | |
| 3069 | lib = dynstr + vneed->vn_file; | | |
| 3070 | #if DEBUG_VERSION | | |
| 3071 | printf ("verneed: %u %s\n", vneed->vn_version, lib); | | |
| 3072 | #endif | | |
| 3073 | for (i = 0; i < vneed->vn_cnt; i++) { | | |
| 3074 | if ((vernaux->vna_other & 0x8000) == 0) { /* hidden */ | | |
| 3075 | version = dynstr + vernaux->vna_name; | | |
| 3076 | set_ver_to_ver(&nb_local_ver, &local_ver, vernaux->vna_other, | | |
| 3077 | lib, version); | | |
| 3078 | #if DEBUG_VERSION | | |
| 3079 | printf (" vernaux(%u): %u %u %s\n", | | |
| 3080 | vernaux->vna_other, vernaux->vna_hash, | | |
| 3081 | vernaux->vna_flags, version); | | |
| 3082 | #endif | | |
| 3083 | } | | |
| 3084 | vernaux = (ElfW(Vernaux) *) (((char *) vernaux) + vernaux->vna_next); | | |
| 3085 | } | | |
| 3086 | next = vneed->vn_next; | | |
| 3087 | vneed = (ElfW(Verneed) *) (((char *) vneed) + next); | | |
| 3088 | } while (next); | | |
| 3089 | } | | |
| 3090 | | | |
| 3091 | #if DEBUG_VERSION | | |
| 3092 | for (i = 0; i < nb_local_ver; i++) { | | |
| 3093 | if (local_ver[i] > 0) { | | |
| 3094 | printf ("%d: lib: %s, version %s\n", | | |
| 3095 | i, sym_versions[local_ver[i]].lib, | | |
| 3096 | sym_version[local_ver[i]].version); | | |
| 3097 | } | | |
| 3098 | } | | |
| 3099 | #endif | | |
| 3100 | | 3132 | |
| 3101 | /* add the dll and its level */ | 3133 | /* add the dll and its level */ |
| 3102 | dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname)); | 3134 | dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname)); |
| @@ -3105,17 +3137,18 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 2 unmodified lines |
| 3105 | dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); | 3137 | dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); |
| 3106 | | 3138 | |
| 3107 | /* add dynamic symbols in dynsym_section */ | 3139 | /* add dynamic symbols in dynsym_section */ |
| 3108 | for(i = 1, sym = dynsym + 1, vsym = versym + 1; i < nb_syms; i++, sym++, vsym++) { | 3140 | for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) { |
| 3109 | sym_bind = ELFW(ST_BIND)(sym->st_info); | 3141 | sym_bind = ELFW(ST_BIND)(sym->st_info); |
| 3110 | if (sym_bind == STB_LOCAL) | 3142 | if (sym_bind == STB_LOCAL) |
| 3111 | continue; | 3143 | continue; |
| 3112 | name = dynstr + sym->st_name; | 3144 | name = dynstr + sym->st_name; |
| 3113 | sym_index = set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, | 3145 | sym_index = set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, |
| 3114 | sym->st_info, sym->st_other, sym->st_shndx, name); | 3146 | sym->st_info, sym->st_other, sym->st_shndx, name); |
| 3115 | if (versym && (*vsym & 0x8000) == 0 && | 3147 | if (v.versym) { |
| 3116 | *vsym > 0 && *vsym < nb_local_ver) { | 3148 | ElfW(Half) vsym = v.versym[i]; |
| 3117 | set_sym_version(sym_index, local_ver[*vsym]); | 3149 | if ((vsym & 0x8000) == 0 && vsym > 0 && vsym < v.nb_local_ver) |
| 3118 | } | 3150 | set_sym_version(s1, sym_index, v.local_ver[vsym]); |
| | 3151 | } |
| 3119 | } | 3152 | } |
| 3120 | | 3153 | |
| 3121 | /* load all referenced DLLs */ | 3154 | /* load all referenced DLLs */ |
| @@ -3139,14 +3172,14 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 17 unmodified lines |
| 3139 | } | 3172 | } |
| 3140 | ret = 0; | 3173 | ret = 0; |
| 3141 | the_end: | 3174 | the_end: |
| 3142 | tcc_free(local_ver); | | |
| 3143 | tcc_free(dynstr); | 3175 | tcc_free(dynstr); |
| 3144 | tcc_free(dynsym); | 3176 | tcc_free(dynsym); |
| 3145 | tcc_free(dynamic); | 3177 | tcc_free(dynamic); |
| 3146 | tcc_free(verdef); | | |
| 3147 | tcc_free(verneed); | | |
| 3148 | tcc_free(versym); | | |
| 3149 | tcc_free(shdr); | 3178 | tcc_free(shdr); |
| | 3179 | tcc_free(v.local_ver); |
| | 3180 | tcc_free(v.verdef); |
| | 3181 | tcc_free(v.verneed); |
| | 3182 | tcc_free(v.versym); |
| 3150 | return ret; | 3183 | return ret; |
| 3151 | } | 3184 | } |
| 3152 | | 3185 | |
| @@ -3406,4 +3439,4 @@ ST_FUNC int tcc_load_ldscript(TCCState *s1) · 253 unmodified lines |
| 3406 | } | 3439 | } |
| 3407 | return 0; | 3440 | return 0; |
| 3408 | } | 3441 | } |
| 3409 | #endif /* !TCC_TARGET_PE */ | 3442 | #endif /* !ELF_OBJ_ONLY */ |