| @@ -49,13 +49,14 @@ struct sym_version { · 48 unmodified lines |
| 49 | 49 | int out_index; |
| 50 | 50 | int prev_same_lib; |
| 51 | 51 | }; |
| 52 | | −static int nb_sym_versions; |
| 53 | | −static struct sym_version *sym_versions; |
| 54 | | −static int nb_sym_to_version; |
| 55 | | −static int *sym_to_version; |
| 56 | | −static int dt_verneednum; |
| 57 | | −static Section *versym_section; |
| 58 | | −static Section *verneed_section; |
| 52 | + |
| 53 | +#define nb_sym_versions s1->nb_sym_versions |
| 54 | +#define sym_versions s1->sym_versions |
| 55 | +#define nb_sym_to_version s1->nb_sym_to_version |
| 56 | +#define sym_to_version s1->sym_to_version |
| 57 | +#define dt_verneednum s1->dt_verneednum |
| 58 | +#define versym_section s1->versym_section |
| 59 | +#define verneed_section s1->verneed_section |
| 59 | 60 | |
| 60 | 61 | /* XXX: avoid static variable */ |
| 61 | 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 | 77 | text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); |
| 77 | 78 | data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
| 78 | 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 | 80 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); |
| 83 | 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 | 125 | int i; |
| 128 | 126 | |
| 127 | +#ifndef ELF_OBJ_ONLY |
| 129 | 128 | /* free symbol versions */ |
| 130 | 129 | for (i = 0; i < nb_sym_versions; i++) { |
| 131 | 130 | tcc_free(sym_versions[i].version); |
| 132 | 131 | tcc_free(sym_versions[i].lib); |
| 133 | 132 | } |
| 134 | 133 | tcc_free(sym_versions); |
| 135 | | − sym_versions = NULL; |
| 136 | | − nb_sym_versions = 0; |
| 137 | 134 | tcc_free(sym_to_version); |
| 138 | | − sym_to_version = NULL; |
| 139 | | − nb_sym_to_version = 0; |
| 135 | +#endif |
| 140 | 136 | |
| 141 | 137 | /* free all sections */ |
| 142 | 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 | 553 | #endif |
| 558 | 554 | |
| 555 | +#ifndef ELF_OBJ_ONLY |
| 559 | 556 | static void |
| 560 | 557 | version_add (TCCState *s) |
| 561 | 558 | { |
| @@ -566,6 +563,15 @@ version_add (TCCState *s) · 4 unmodified lines |
| 566 | 563 | int sym_index, end_sym, nb_versions = 2, nb_entries = 0; |
| 567 | 564 | ElfW(Half) *versym; |
| 568 | 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 | 576 | /* add needed symbols */ |
| 571 | 577 | symtab = s->dynsym; |
| @@ -590,7 +596,7 @@ version_add (TCCState *s) · 18 unmodified lines |
| 590 | 596 | struct sym_version *sv = &sym_versions[i]; |
| 591 | 597 | int n_same_libs = 0, prev; |
| 592 | 598 | size_t vnofs; |
| 593 | | − ElfW(Vernaux) *vna = vna; |
| 599 | + ElfW(Vernaux) *vna = 0; |
| 594 | 600 | if (sv->out_index < 1) |
| 595 | 601 | continue; |
| 596 | 602 | vnofs = section_add(verneed_section, sizeof(*vn), 1); |
| @@ -623,6 +629,7 @@ version_add (TCCState *s) · 26 unmodified lines |
| 623 | 629 | verneed_section->sh_info = nb_entries; |
| 624 | 630 | dt_verneednum = nb_entries; |
| 625 | 631 | } |
| 632 | +#endif |
| 626 | 633 | |
| 627 | 634 | /* add an elf symbol : check if it is already defined and patch |
| 628 | 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 | 977 | unsigned char *ptr; |
| 971 | 978 | addr_t tgt, addr; |
| 972 | 979 | |
| 973 | | − relocate_init(sr); |
| 980 | + qrel = (ElfW_Rel *)sr->data; |
| 974 | 981 | |
| 975 | 982 | for_each_elem(sr, 0, rel, ElfW_Rel) { |
| 976 | 983 | ptr = s->data + rel->r_offset; |
| @@ -989,6 +996,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 12 unmodified lines |
| 989 | 996 | sr->link = s1->dynsym; |
| 990 | 997 | } |
| 991 | 998 | |
| 999 | +#ifndef ELF_OBJ_ONLY |
| 992 | 1000 | /* relocate relocation table in 'sr' */ |
| 993 | 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 | 1263 | dyn->d_tag = dt; |
| 1256 | 1264 | dyn->d_un.d_val = val; |
| 1257 | 1265 | } |
| 1266 | +#endif |
| 1258 | 1267 | |
| 1259 | 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 | 1472 | ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) |
| 1463 | 1473 | { |
| 1464 | 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 | 1676 | /* Allocate strings for section names and decide if an unallocated section |
| 1666 | 1677 | should be output. |
| @@ -1676,6 +1687,7 @@ static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec) · 9 unmodified lines |
| 1676 | 1687 | s = s1->sections[i]; |
| 1677 | 1688 | /* when generating a DLL, we include relocations but we may |
| 1678 | 1689 | patch them */ |
| 1690 | +#ifndef ELF_OBJ_ONLY |
| 1679 | 1691 | if (file_type == TCC_OUTPUT_DLL && |
| 1680 | 1692 | s->sh_type == SHT_RELX && |
| 1681 | 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 | 1695 | prepare_dynamic_rel(s1, s)) { |
| 1684 | 1696 | if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR) |
| 1685 | 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 | 1701 | file_type == TCC_OUTPUT_OBJ || |
| 1688 | 1702 | (s->sh_flags & SHF_ALLOC) || |
| 1689 | 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 | 1904 | return file_offset; |
| 1891 | 1905 | } |
| 1892 | 1906 | |
| 1907 | +#ifndef ELF_OBJ_ONLY |
| 1893 | 1908 | static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, |
| 1894 | 1909 | Section *dynamic) |
| 1895 | 1910 | { |
| @@ -1964,9 +1979,11 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) · 68 unmodified lines |
| 1964 | 1979 | put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel)); |
| 1965 | 1980 | #endif |
| 1966 | 1981 | #endif |
| 1967 | | − put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr); |
| 1968 | | − put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum); |
| 1969 | | − put_dt(dynamic, DT_VERSYM, versym_section->sh_addr); |
| 1982 | + if (versym_section) { |
| 1983 | + put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr); |
| 1984 | + put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum); |
| 1985 | + put_dt(dynamic, DT_VERSYM, versym_section->sh_addr); |
| 1986 | + } |
| 1970 | 1987 | s = find_section_create (s1, ".preinit_array", 0); |
| 1971 | 1988 | if (s && s->data_offset) { |
| 1972 | 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 | 2044 | return 0; |
| 2028 | 2045 | } |
| 2046 | +#endif |
| 2029 | 2047 | |
| 2030 | 2048 | /* Create an ELF file on disk. |
| 2031 | 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 | 2201 | return 0; |
| 2184 | 2202 | } |
| 2185 | 2203 | |
| 2204 | +#ifndef ELF_OBJ_ONLY |
| 2186 | 2205 | /* Sort section headers by assigned sh_addr, remove sections |
| 2187 | 2206 | that we aren't going to output. */ |
| 2188 | 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 | 2247 | s1->nb_sections = nnew; |
| 2229 | 2248 | tcc_free(backmap); |
| 2230 | 2249 | } |
| 2250 | +#endif |
| 2231 | 2251 | |
| 2232 | 2252 | /* Output an elf, coff or binary file */ |
| 2233 | 2253 | /* XXX: suppress unneeded sections */ |
| 2234 | 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 | 2257 | struct dyn_inf dyninf = {0}; |
| 2238 | 2258 | ElfW(Phdr) *phdr; |
| 2239 | | − ElfW(Sym) *sym; |
| 2240 | 2259 | Section *strsec, *interp, *dynamic, *dynstr; |
| 2241 | | − int textrel; |
| 2242 | 2260 | |
| 2243 | 2261 | file_type = s1->output_type; |
| 2244 | 2262 | s1->nb_errors = 0; |
| @@ -2246,8 +2264,8 @@ static int elf_output_file(TCCState *s1, const char *filename) · 1 unmodified line |
| 2246 | 2264 | phdr = NULL; |
| 2247 | 2265 | sec_order = NULL; |
| 2248 | 2266 | interp = dynamic = dynstr = NULL; /* avoid warning */ |
| 2249 | | − textrel = 0; |
| 2250 | 2267 | |
| 2268 | +#ifndef ELF_OBJ_ONLY |
| 2251 | 2269 | if (file_type != TCC_OUTPUT_OBJ) { |
| 2252 | 2270 | /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ |
| 2253 | 2271 | tcc_add_runtime(s1); |
| @@ -2272,9 +2290,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 18 unmodified lines |
| 2272 | 2290 | ".dynstr", |
| 2273 | 2291 | ".hash", SHF_ALLOC); |
| 2274 | 2292 | dynstr = s1->dynsym->link; |
| 2275 | | − versym_section->link = s1->dynsym; |
| 2276 | | − verneed_section->link = dynstr; |
| 2277 | | − |
| 2278 | 2293 | /* add dynamic section */ |
| 2279 | 2294 | dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, |
| 2280 | 2295 | SHF_ALLOC | SHF_WRITE); |
| @@ -2296,15 +2311,18 @@ static int elf_output_file(TCCState *s1, const char *filename) · 15 unmodified lines |
| 2296 | 2311 | build_got_entries(s1); |
| 2297 | 2312 | version_add (s1); |
| 2298 | 2313 | } |
| 2314 | +#endif |
| 2299 | 2315 | |
| 2300 | 2316 | /* we add a section for symbols */ |
| 2301 | 2317 | strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0); |
| 2302 | 2318 | put_elf_str(strsec, ""); |
| 2303 | 2319 | |
| 2304 | 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 | 2324 | if (dynamic) { |
| 2325 | + int i; |
| 2308 | 2326 | /* add a list of needed dlls */ |
| 2309 | 2327 | for(i = 0; i < s1->nb_loaded_dlls; i++) { |
| 2310 | 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 | 2339 | put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); |
| 2322 | 2340 | /* XXX: currently, since we do not handle PIC code, we |
| 2323 | 2341 | must relocate the readonly segments */ |
| 2324 | | − if (textrel) |
| 2342 | + if (ret) |
| 2325 | 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 | 2354 | dynamic->sh_size = dynamic->data_offset; |
| 2337 | 2355 | dynstr->sh_size = dynstr->data_offset; |
| 2338 | 2356 | } |
| 2357 | +#endif |
| 2339 | 2358 | |
| 2340 | 2359 | /* compute number of program headers */ |
| 2341 | 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 | 2380 | file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf, |
| 2362 | 2381 | sec_order); |
| 2363 | 2382 | |
| 2383 | +#ifndef ELF_OBJ_ONLY |
| 2364 | 2384 | /* Fill remaining program header and finalize relocation related to dynamic |
| 2365 | 2385 | linking. */ |
| 2366 | 2386 | if (file_type != TCC_OUTPUT_OBJ) { |
| 2367 | 2387 | fill_unloadable_phdr(phdr, phnum, interp, dynamic); |
| 2368 | 2388 | if (dynamic) { |
| 2389 | + ElfW(Sym) *sym; |
| 2369 | 2390 | dynamic->data_offset = dyninf.data_offset; |
| 2370 | 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 | 2418 | else if (s1->got) |
| 2398 | 2419 | fill_local_got_entries(s1); |
| 2399 | 2420 | } |
| 2421 | +#endif |
| 2400 | 2422 | |
| 2401 | 2423 | /* Create the ELF file with name 'filename' */ |
| 2402 | 2424 | ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); |
| 2403 | 2425 | s1->nb_sections = shnum; |
| 2426 | + goto the_end; |
| 2404 | 2427 | the_end: |
| 2405 | 2428 | tcc_free(sec_order); |
| 2406 | 2429 | tcc_free(phdr); |
| @@ -2885,10 +2908,10 @@ ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte) · 478 unmodified lines |
| 2885 | 2908 | return 0; |
| 2886 | 2909 | } |
| 2887 | 2910 | |
| 2888 | | −#ifndef TCC_TARGET_PE |
| 2911 | +#ifndef ELF_OBJ_ONLY |
| 2889 | 2912 | /* Set LV[I] to the global index of sym-version (LIB,VERSION). Maybe resizes |
| 2890 | 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 | 2916 | while (i >= *n) { |
| 2894 | 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 | 2942 | /* Associates symbol SYM_INDEX (in dynsymtab) with sym-version index |
| 2920 | 2943 | VERNDX. */ |
| 2921 | 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 | 2947 | if (sym_index >= nb_sym_to_version) { |
| 2925 | 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 | 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 | 3043 | /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL |
| 2937 | 3044 | is referenced by the user (so it should be added as DT_NEEDED in |
| 2938 | 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 | 3050 | int i, j, nb_syms, nb_dts, sym_bind, ret; |
| 2944 | 3051 | ElfW(Sym) *sym, *dynsym; |
| 2945 | 3052 | ElfW(Dyn) *dt, *dynamic; |
| 2946 | | − int nb_versyms; |
| 2947 | | − ElfW(Verdef) *verdef, *vdef; |
| 2948 | | − ElfW(Verneed) *verneed, *vneed; |
| 2949 | | − ElfW(Half) *versym, *vsym; |
| 3053 | + |
| 2950 | 3054 | char *dynstr; |
| 2951 | | − uint32_t next; |
| 2952 | 3055 | int sym_index; |
| 2953 | | − char *lib, *version; |
| 2954 | | − int nb_local_ver = 0, *local_ver = NULL; |
| 2955 | 3056 | const char *name, *soname; |
| 2956 | 3057 | DLLReference *dllref; |
| 3058 | + struct versym_info v; |
| 2957 | 3059 | |
| 2958 | 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 | 3075 | dynamic = NULL; |
| 2974 | 3076 | dynsym = NULL; /* avoid warning */ |
| 2975 | 3077 | dynstr = NULL; /* avoid warning */ |
| 2976 | | − nb_versyms = 0; |
| 2977 | | − verdef = NULL; |
| 2978 | | − verneed = NULL; |
| 2979 | | − versym = NULL; |
| 3078 | + memset(&v, 0, sizeof v); |
| 3079 | + |
| 2980 | 3080 | for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) { |
| 2981 | 3081 | switch(sh->sh_type) { |
| 2982 | 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 | 3090 | dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size); |
| 2991 | 3091 | break; |
| 2992 | 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 | 3094 | break; |
| 2995 | 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 | 3097 | break; |
| 2998 | 3098 | case SHT_GNU_versym: |
| 2999 | | − nb_versyms = sh->sh_size / sizeof(ElfW(Half)); |
| 3000 | | − versym = load_data(fd, sh->sh_offset, sh->sh_size); |
| 3099 | + v.nb_versyms = sh->sh_size / sizeof(ElfW(Half)); |
| 3100 | + v.versym = load_data(fd, sh->sh_offset, sh->sh_size); |
| 3001 | 3101 | break; |
| 3002 | 3102 | default: |
| 3003 | 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) { |
| 3029 | | − tcc_free (versym); |
| 3030 | | − versym = NULL; |
| 3031 | | − } |
| 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 |
| 3128 | + if (v.nb_versyms != nb_syms) |
| 3129 | + tcc_free (v.versym), v.versym = NULL; |
| 3130 | + else |
| 3131 | + store_version(s1, &v, dynstr); |
| 3100 | 3132 | |
| 3101 | 3133 | /* add the dll and its level */ |
| 3102 | 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 | 3137 | dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); |
| 3106 | 3138 | |
| 3107 | 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 | 3141 | sym_bind = ELFW(ST_BIND)(sym->st_info); |
| 3110 | 3142 | if (sym_bind == STB_LOCAL) |
| 3111 | 3143 | continue; |
| 3112 | 3144 | name = dynstr + sym->st_name; |
| 3113 | 3145 | sym_index = set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, |
| 3114 | 3146 | sym->st_info, sym->st_other, sym->st_shndx, name); |
| 3115 | | − if (versym && (*vsym & 0x8000) == 0 && |
| 3116 | | − *vsym > 0 && *vsym < nb_local_ver) { |
| 3117 | | − set_sym_version(sym_index, local_ver[*vsym]); |
| 3118 | | − } |
| 3147 | + if (v.versym) { |
| 3148 | + ElfW(Half) vsym = v.versym[i]; |
| 3149 | + if ((vsym & 0x8000) == 0 && vsym > 0 && vsym < v.nb_local_ver) |
| 3150 | + set_sym_version(s1, sym_index, v.local_ver[vsym]); |
| 3151 | + } |
| 3119 | 3152 | } |
| 3120 | 3153 | |
| 3121 | 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 | 3173 | ret = 0; |
| 3141 | 3174 | the_end: |
| 3142 | | − tcc_free(local_ver); |
| 3143 | 3175 | tcc_free(dynstr); |
| 3144 | 3176 | tcc_free(dynsym); |
| 3145 | 3177 | tcc_free(dynamic); |
| 3146 | | − tcc_free(verdef); |
| 3147 | | − tcc_free(verneed); |
| 3148 | | − tcc_free(versym); |
| 3149 | 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 | 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 | 3440 | return 0; |
| 3408 | 3441 | } |
| 3409 | | −#endif /* !TCC_TARGET_PE */ |
| 3442 | +#endif /* !ELF_OBJ_ONLY */ |