so it isn't quadratic in number of symbols. It's still quadratic in number of lib/version combinations (at library load time the sym versions are internalized), but that's much less a problem as in practice only glibc uses sym versioning.
Unified · Split
| @@ -43,32 +43,19 @@ ST_DATA Section *symtab_section; · 42 unmodified lines | ||
| 43 | 43 | ST_DATA Section *stab_section, *stabstr_section; |
| 44 | 44 | |
| 45 | 45 | /* elf version information */ |
| 46 | −ST_DATA int nb_version_sym; | |
| 47 | −struct sym_info_struct { | |
| 48 | − char *name; | |
| 49 | − ElfW(Sym) esym; | |
| 50 | −}; | |
| 51 | −ST_DATA struct def_need_struct { | |
| 52 | − char *lib; | |
| 53 | − char *version; | |
| 54 | − unsigned int nb_sym_info; | |
| 55 | − struct sym_info_struct *sym_info; | |
| 56 | −} *version_sym; | |
| 57 | −ST_DATA int nb_need; | |
| 58 | −ST_DATA int dt_verneednum; | |
| 59 | −ST_DATA struct need_struct { | |
| 60 | − int offset; | |
| 61 | − char *lib; | |
| 62 | − int n_aux; | |
| 63 | − struct aux_struct { | |
| 64 | − int offset; | |
| 46 | +struct sym_version { | |
| 47 | + char *lib; | |
| 65 | 48 | char *version; |
| 66 | − int other; | |
| 67 | − } *aux; | |
| 68 | −} *need; | |
| 69 | −ST_DATA ElfW(Half) next_version = 1; | |
| 70 | −ST_DATA Section *versym_section; | |
| 71 | −ST_DATA Section *verneed_section; | |
| 49 | + int out_index; | |
| 50 | + int prev_same_lib; | |
| 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; | |
| 72 | 59 | |
| 73 | 60 | /* XXX: avoid static variable */ |
| 74 | 61 | static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */ |
| @@ -139,6 +126,18 @@ ST_FUNC void tccelf_delete(TCCState *s1) · 64 unmodified lines | ||
| 139 | 126 | { |
| 140 | 127 | int i; |
| 141 | 128 | |
| 129 | + /* free symbol versions */ | |
| 130 | + for (i = 0; i < nb_sym_versions; i++) { | |
| 131 | + tcc_free(sym_versions[i].version); | |
| 132 | + tcc_free(sym_versions[i].lib); | |
| 133 | + } | |
| 134 | + tcc_free(sym_versions); | |
| 135 | + sym_versions = NULL; | |
| 136 | + nb_sym_versions = 0; | |
| 137 | + tcc_free(sym_to_version); | |
| 138 | + sym_to_version = NULL; | |
| 139 | + nb_sym_to_version = 0; | |
| 140 | + | |
| 142 | 141 | /* free all sections */ |
| 143 | 142 | for(i = 1; i < s1->nb_sections; i++) |
| 144 | 143 | free_section(s1->sections[i]); |
| @@ -557,219 +556,72 @@ ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name) · 412 unmodified lines | ||
| 557 | 556 | } |
| 558 | 557 | #endif |
| 559 | 558 | |
| 560 | −ST_FUNC void | |
| 561 | −save_def_need_index (int *n_def_need, struct def_need_struct **def_need, | |
| 562 | − unsigned int n, const char *lib, const char *version) | |
| 563 | −{ | |
| 564 | − /* add index in table */ | |
| 565 | − if (*n_def_need < n + 1) { | |
| 566 | − *def_need = (struct def_need_struct *) | |
| 567 | − tcc_realloc (*def_need, | |
| 568 | − (n + 1) * sizeof (struct def_need_struct)); | |
| 569 | − while (*n_def_need < n + 1) { | |
| 570 | − (*def_need)[*n_def_need].lib = NULL; | |
| 571 | − (*def_need)[*n_def_need].version = NULL; | |
| 572 | − (*def_need)[*n_def_need].nb_sym_info = 0; | |
| 573 | − (*def_need)[*n_def_need].sym_info = NULL; | |
| 574 | − (*n_def_need)++; | |
| 575 | − } | |
| 576 | − } | |
| 577 | − if ((*def_need)[n].lib == NULL) { | |
| 578 | − (*def_need)[n].lib = tcc_strdup (lib); | |
| 579 | − (*def_need)[n].version = tcc_strdup (version); | |
| 580 | − } | |
| 581 | −} | |
| 582 | − | |
| 583 | −ST_FUNC void | |
| 584 | −free_def_need (int n_def_need, struct def_need_struct *def_need) | |
| 585 | −{ | |
| 586 | − int i; | |
| 587 | − | |
| 588 | − for (i = 0; i < n_def_need; i++) { | |
| 589 | − tcc_free (def_need[i].lib); | |
| 590 | − tcc_free (def_need[i].version); | |
| 591 | − } | |
| 592 | − tcc_free (def_need); | |
| 593 | −} | |
| 594 | − | |
| 595 | −ST_FUNC void | |
| 596 | −add_version_sym (Section *s, int sym_index, int n_def_need, | |
| 597 | − struct def_need_struct *def_need, const char *name, unsigned int n) | |
| 598 | −{ | |
| 599 | − int i, j; | |
| 600 | − ElfW(Sym) *esym; | |
| 601 | − | |
| 602 | − /* check if present */ | |
| 603 | − esym = &((ElfW(Sym) *)s->data)[sym_index]; | |
| 604 | − for (i = 0; i < nb_version_sym; i++) { | |
| 605 | − for (j = 0; j < version_sym[i].nb_sym_info; j++) { | |
| 606 | − if (strcmp (version_sym[i].sym_info[j].name, name) == 0) { | |
| 607 | − if (memcmp (&version_sym[i].sym_info[j].esym, esym, sizeof (ElfW(Sym))) == 0) { | |
| 608 | − return; | |
| 609 | − } | |
| 610 | − version_sym[i].nb_sym_info--; | |
| 611 | − tcc_free (version_sym[i].sym_info[j].name); | |
| 612 | − for (; j < version_sym[i].nb_sym_info; j++) { | |
| 613 | − version_sym[i].sym_info[j] = version_sym[i].sym_info[j + 1]; | |
| 614 | − } | |
| 615 | − } | |
| 616 | − } | |
| 617 | − } | |
| 618 | − /* add new value */ | |
| 619 | − for (i = 0; i < nb_version_sym; i++) { | |
| 620 | − if (strcmp (def_need[n].lib, | |
| 621 | − version_sym[i].lib) == 0 && | |
| 622 | − strcmp (def_need[n].version, | |
| 623 | − version_sym[i].version) == 0) { | |
| 624 | − break; | |
| 625 | − } | |
| 626 | − } | |
| 627 | − if (i == nb_version_sym) { | |
| 628 | − version_sym = (struct def_need_struct *) | |
| 629 | − tcc_realloc (version_sym, | |
| 630 | − (nb_version_sym + 1) * sizeof (struct def_need_struct)); | |
| 631 | − version_sym[nb_version_sym].lib = tcc_strdup (def_need[n].lib); | |
| 632 | − version_sym[nb_version_sym].version = tcc_strdup (def_need[n].version); | |
| 633 | − version_sym[nb_version_sym].nb_sym_info = 0; | |
| 634 | − version_sym[nb_version_sym].sym_info = NULL; | |
| 635 | − nb_version_sym++; | |
| 636 | − } | |
| 637 | − version_sym[i].sym_info = (struct sym_info_struct *) | |
| 638 | − tcc_realloc (version_sym[i].sym_info, | |
| 639 | − (version_sym[i].nb_sym_info + 1) * sizeof (struct sym_info_struct)); | |
| 640 | − version_sym[i].sym_info[version_sym[i].nb_sym_info].name = tcc_strdup (name); | |
| 641 | − version_sym[i].sym_info[version_sym[i].nb_sym_info].esym = *esym; | |
| 642 | − version_sym[i].nb_sym_info++; | |
| 643 | −} | |
| 644 | − | |
| 645 | −static void | |
| 646 | −add_need_sym (Section *s, const char *soname, const char *version, const char *name, int sym_index) | |
| 647 | −{ | |
| 648 | − int i; | |
| 649 | − unsigned long size; | |
| 650 | − void *ptr; | |
| 651 | − int ver_index = 0; | |
| 652 | − struct need_struct *verlib = NULL; | |
| 653 | − ElfW(Half) vers; | |
| 654 | − | |
| 655 | − if (soname) { | |
| 656 | − for (i = 0; i < nb_need; i++) { | |
| 657 | − if (strcmp (soname, need[i].lib) == 0) { | |
| 658 | − verlib = &need[i]; | |
| 659 | − break; | |
| 660 | − } | |
| 661 | − } | |
| 662 | − if (verlib == NULL) { | |
| 663 | − need = (struct need_struct *) | |
| 664 | − tcc_realloc (need, (nb_need + 1) * sizeof (struct need_struct)); | |
| 665 | − need[nb_need].offset = put_elf_str(s->link, soname); | |
| 666 | − need[nb_need].lib = tcc_strdup (soname); | |
| 667 | − need[nb_need].n_aux = 0; | |
| 668 | − need[nb_need].aux = NULL; | |
| 669 | − verlib = &need[nb_need]; | |
| 670 | − nb_need++; | |
| 671 | − } | |
| 672 | − for (i = 0; i < verlib->n_aux; i++) { | |
| 673 | − if (strcmp (version, verlib->aux[i].version) == 0) { | |
| 674 | − ver_index = verlib->aux[i].other; | |
| 675 | − } | |
| 676 | − } | |
| 677 | − if (ver_index == 0) { | |
| 678 | − verlib->aux = (struct aux_struct *) | |
| 679 | − tcc_realloc (verlib->aux, (verlib->n_aux + 1) * sizeof (struct aux_struct)); | |
| 680 | − verlib->aux[verlib->n_aux].offset = put_elf_str(s->link, version); | |
| 681 | − verlib->aux[verlib->n_aux].version = tcc_strdup (version); | |
| 682 | − ver_index = verlib->aux[verlib->n_aux].other = ++next_version; | |
| 683 | − verlib->n_aux++; | |
| 684 | − } | |
| 685 | − } | |
| 686 | − /* update versym section */ | |
| 687 | − size = versym_section->data_offset / sizeof (vers); | |
| 688 | − for (i = size; i < (sym_index + 1); i++) { | |
| 689 | − ptr = section_ptr_add (versym_section, sizeof (vers)); | |
| 690 | − vers = 0; | |
| 691 | − memcpy (ptr, &vers, sizeof (vers)); | |
| 692 | − } | |
| 693 | − ptr = versym_section->data + sym_index * sizeof (vers); | |
| 694 | − vers = ver_index; | |
| 695 | − memcpy (ptr, &vers, sizeof (vers)); | |
| 696 | −} | |
| 697 | − | |
| 698 | 559 | static void |
| 699 | 560 | version_add (TCCState *s) |
| 700 | 561 | { |
| 701 | − int i, j, found; | |
| 562 | + int i; | |
| 702 | 563 | ElfW(Sym) *sym; |
| 703 | − ElfW(Verneed) verneed; | |
| 704 | − ElfW(Vernaux) aux; | |
| 564 | + ElfW(Verneed) *vn = NULL; | |
| 705 | 565 | Section *symtab; |
| 706 | − int sym_index, end_sym; | |
| 566 | + int sym_index, end_sym, nb_versions = 2, nb_entries = 0; | |
| 567 | + ElfW(Half) *versym; | |
| 707 | 568 | const char *name; |
| 708 | − void *ptr; | |
| 709 | 569 | |
| 710 | 570 | /* add needed symbols */ |
| 711 | 571 | symtab = s->dynsym; |
| 712 | 572 | end_sym = symtab->data_offset / sizeof (ElfSym); |
| 573 | + versym = section_ptr_add(versym_section, end_sym * sizeof(ElfW(Half))); | |
| 713 | 574 | for (sym_index = 0; sym_index < end_sym; ++sym_index) { |
| 575 | + int dllindex, verndx; | |
| 714 | 576 | sym = &((ElfW(Sym) *)symtab->data)[sym_index]; |
| 715 | 577 | name = (char *) symtab->link->data + sym->st_name; |
| 716 | − found = 0; | |
| 717 | − for (i = 0; !found && i < nb_version_sym; i++) { | |
| 718 | − for (j = 0; !found && j < version_sym[i].nb_sym_info; j++) { | |
| 719 | − if (strcmp (version_sym[i].sym_info[j].name, name) == 0) { | |
| 720 | − found = 1; | |
| 721 | − add_need_sym (symtab, version_sym[i].lib, version_sym[i].version, name, sym_index); | |
| 722 | − } | |
| 723 | − } | |
| 724 | − } | |
| 725 | − if (!found) { | |
| 726 | − add_need_sym (symtab, NULL, NULL, NULL, sym_index); | |
| 727 | − } | |
| 728 | − symtab = s->dynsym; /* symtab can be realocated by add_need_sym */ | |
| 578 | + dllindex = find_elf_sym(s->dynsymtab_section, name); | |
| 579 | + verndx = (dllindex && dllindex < nb_sym_to_version) | |
| 580 | + ? sym_to_version[dllindex] : -1; | |
| 581 | + if (verndx >= 0) { | |
| 582 | + if (!sym_versions[verndx].out_index) | |
| 583 | + sym_versions[verndx].out_index = nb_versions++; | |
| 584 | + versym[sym_index] = sym_versions[verndx].out_index; | |
| 585 | + } else | |
| 586 | + versym[sym_index] = 0; | |
| 729 | 587 | } |
| 730 | 588 | /* generate verneed section */ |
| 731 | − verneed_section->sh_info = nb_need; | |
| 732 | − for (i = 0; i < nb_need; i++) { | |
| 733 | − verneed.vn_version = 1; | |
| 734 | − verneed.vn_cnt = need[i].n_aux; | |
| 735 | − verneed.vn_file = need[i].offset; | |
| 736 | − verneed.vn_aux = sizeof (verneed); | |
| 737 | − verneed.vn_next = i == nb_need - 1 ? 0 : sizeof (verneed) + need[i].n_aux * sizeof (aux); | |
| 738 | − ptr = section_ptr_add (verneed_section, sizeof (verneed)); | |
| 739 | − memcpy (ptr, &verneed, sizeof (verneed)); | |
| 740 | − for (j = 0; j < need[i].n_aux; j++) { | |
| 741 | − aux.vna_hash = elf_hash (need[i].aux[j].version); | |
| 742 | − aux.vna_flags = 0; | |
| 743 | − aux.vna_other = need[i].aux[j].other; | |
| 744 | − aux.vna_name = need[i].aux[j].offset; | |
| 745 | − aux.vna_next = j == need[i].n_aux - 1 ? 0 : sizeof (aux); | |
| 746 | − ptr = section_ptr_add (verneed_section, sizeof (aux)); | |
| 747 | − memcpy (ptr, &aux, sizeof (aux)); | |
| 748 | − } | |
| 749 | − } | |
| 750 | − /* free all info */ | |
| 751 | − for (i = 0; i < nb_version_sym; i++) { | |
| 752 | − for (j = 0; j < version_sym[i].nb_sym_info; j++) { | |
| 753 | − tcc_free (version_sym[i].sym_info[j].name); | |
| 754 | − } | |
| 755 | − tcc_free (version_sym[i].lib); | |
| 756 | − tcc_free (version_sym[i].version); | |
| 757 | − tcc_free (version_sym[i].sym_info); | |
| 758 | − } | |
| 759 | − tcc_free (version_sym); | |
| 760 | − nb_version_sym = 0; | |
| 761 | − version_sym = NULL; | |
| 762 | − for (i = 0; i < nb_need; i++) { | |
| 763 | − tcc_free (need[i].lib); | |
| 764 | − for (j = 0; j < need[i].n_aux; j++) { | |
| 765 | − tcc_free (need[i].aux[j].version); | |
| 766 | − } | |
| 767 | − tcc_free (need[i].aux); | |
| 589 | + for (i = nb_sym_versions; i-- > 0;) { | |
| 590 | + struct sym_version *sv = &sym_versions[i]; | |
| 591 | + int n_same_libs = 0, prev; | |
| 592 | + size_t vnofs; | |
| 593 | + ElfW(Vernaux) *vna; | |
| 594 | + if (sv->out_index < 1) | |
| 595 | + continue; | |
| 596 | + vnofs = section_add(verneed_section, sizeof(*vn), 1); | |
| 597 | + vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); | |
| 598 | + vn->vn_version = 1; | |
| 599 | + vn->vn_file = put_elf_str(verneed_section->link, sv->lib); | |
| 600 | + vn->vn_aux = sizeof (*vn); | |
| 601 | + do { | |
| 602 | + prev = sv->prev_same_lib; | |
| 603 | + if (sv->out_index > 0) { | |
| 604 | + vna = section_ptr_add(verneed_section, sizeof(*vna)); | |
| 605 | + vna->vna_hash = elf_hash (sv->version); | |
| 606 | + vna->vna_flags = 0; | |
| 607 | + vna->vna_other = sv->out_index; | |
| 608 | + sv->out_index = -2; | |
| 609 | + vna->vna_name = put_elf_str(verneed_section->link, sv->version); | |
| 610 | + vna->vna_next = sizeof (*vna); | |
| 611 | + n_same_libs++; | |
| 612 | + } | |
| 613 | + sv = &sym_versions[prev]; | |
| 614 | + } while(prev >= 0); | |
| 615 | + vna->vna_next = 0; | |
| 616 | + vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); | |
| 617 | + vn->vn_cnt = n_same_libs; | |
| 618 | + vn->vn_next = sizeof(*vn) + n_same_libs * sizeof(*vna); | |
| 619 | + nb_entries++; | |
| 768 | 620 | } |
| 769 | − tcc_free (need); | |
| 770 | − dt_verneednum = nb_need; | |
| 771 | − nb_need = 0; | |
| 772 | − need = NULL; | |
| 621 | + if (vn) | |
| 622 | + vn->vn_next = 0; | |
| 623 | + verneed_section->sh_info = nb_entries; | |
| 624 | + dt_verneednum = nb_entries; | |
| 773 | 625 | } |
| 774 | 626 | |
| 775 | 627 | /* add an elf symbol : check if it is already defined and patch |
| @@ -3052,6 +2904,53 @@ ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte) · 2276 unmodified lines | ||
| 3052 | 2904 | } |
| 3053 | 2905 | |
| 3054 | 2906 | #ifndef TCC_TARGET_PE |
| 2907 | +/* Set LV[I] to the global index of sym-version (LIB,VERSION). Maybe resizes | |
| 2908 | + LV, maybe create a new entry for (LIB,VERSION). */ | |
| 2909 | +static void set_ver_to_ver(int *n, int **lv, int i, char *lib, char *version) | |
| 2910 | +{ | |
| 2911 | + while (i >= *n) { | |
| 2912 | + *lv = tcc_realloc(*lv, (*n + 1) * sizeof(**lv)); | |
| 2913 | + (*lv)[(*n)++] = -1; | |
| 2914 | + } | |
| 2915 | + if ((*lv)[i] == -1) { | |
| 2916 | + int v, prev_same_lib = -1; | |
| 2917 | + for (v = 0; v < nb_sym_versions; v++) { | |
| 2918 | + if (strcmp(sym_versions[v].lib, lib)) | |
| 2919 | + continue; | |
| 2920 | + prev_same_lib = v; | |
| 2921 | + if (!strcmp(sym_versions[v].version, version)) | |
| 2922 | + break; | |
| 2923 | + } | |
| 2924 | + if (v == nb_sym_versions) { | |
| 2925 | + sym_versions = tcc_realloc (sym_versions, | |
| 2926 | + (v + 1) * sizeof(*sym_versions)); | |
| 2927 | + sym_versions[v].lib = tcc_strdup(lib); | |
| 2928 | + sym_versions[v].version = tcc_strdup(version); | |
| 2929 | + sym_versions[v].out_index = 0; | |
| 2930 | + sym_versions[v].prev_same_lib = prev_same_lib; | |
| 2931 | + nb_sym_versions++; | |
| 2932 | + } | |
| 2933 | + (*lv)[i] = v; | |
| 2934 | + } | |
| 2935 | +} | |
| 2936 | + | |
| 2937 | +/* Associates symbol SYM_INDEX (in dynsymtab) with sym-version index | |
| 2938 | + VERNDX. */ | |
| 2939 | +static void | |
| 2940 | +set_sym_version(int sym_index, int verndx) | |
| 2941 | +{ | |
| 2942 | + if (sym_index >= nb_sym_to_version) { | |
| 2943 | + int newelems = sym_index ? sym_index * 2 : 1; | |
| 2944 | + sym_to_version = tcc_realloc(sym_to_version, | |
| 2945 | + newelems * sizeof(*sym_to_version)); | |
| 2946 | + memset(sym_to_version + nb_sym_to_version, -1, | |
| 2947 | + (newelems - nb_sym_to_version) * sizeof(*sym_to_version)); | |
| 2948 | + nb_sym_to_version = newelems; | |
| 2949 | + } | |
| 2950 | + if (sym_to_version[sym_index] < 0) | |
| 2951 | + sym_to_version[sym_index] = verndx; | |
| 2952 | +} | |
| 2953 | + | |
| 3055 | 2954 | /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL |
| 3056 | 2955 | is referenced by the user (so it should be added as DT_NEEDED in |
| 3057 | 2956 | the generated ELF file) */ |
| @@ -3066,12 +2965,11 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 8 unmodified lines | ||
| 3066 | 2965 | ElfW(Verdef) *verdef, *vdef; |
| 3067 | 2966 | ElfW(Verneed) *verneed, *vneed; |
| 3068 | 2967 | ElfW(Half) *versym, *vsym; |
| 3069 | − unsigned char *dynstr; | |
| 2968 | + char *dynstr; | |
| 3070 | 2969 | uint32_t next; |
| 3071 | 2970 | int sym_index; |
| 3072 | 2971 | char *lib, *version; |
| 3073 | − int n_def_need = 0; | |
| 3074 | − struct def_need_struct *def_need = NULL; | |
| 2972 | + int nb_local_ver = 0, *local_ver = NULL; | |
| 3075 | 2973 | const char *name, *soname; |
| 3076 | 2974 | DLLReference *dllref; |
| 3077 | 2975 | |
| @@ -3129,7 +3027,7 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 51 unmodified lines | ||
| 3129 | 3027 | |
| 3130 | 3028 | for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { |
| 3131 | 3029 | if (dt->d_tag == DT_SONAME) { |
| 3132 | − soname = (char *) dynstr + dt->d_un.d_val; | |
| 3030 | + soname = dynstr + dt->d_un.d_val; | |
| 3133 | 3031 | } |
| 3134 | 3032 | } |
| 3135 | 3033 | |
| @@ -3164,20 +3062,17 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 28 unmodified lines | ||
| 3164 | 3062 | vdef->vd_version, vdef->vd_flags, vdef->vd_ndx, |
| 3165 | 3063 | vdef->vd_hash); |
| 3166 | 3064 | #endif |
| 3167 | − for (i = 0; i < vdef->vd_cnt; i++) { | |
| 3168 | − version = (char *) dynstr + verdaux->vda_name; | |
| 3065 | + if (vdef->vd_cnt) { | |
| 3066 | + version = dynstr + verdaux->vda_name; | |
| 3169 | 3067 | |
| 3170 | − if (lib == NULL) { | |
| 3068 | + if (lib == NULL) | |
| 3171 | 3069 | lib = version; |
| 3172 | − } | |
| 3173 | − else { | |
| 3174 | − save_def_need_index (&n_def_need, &def_need, | |
| 3175 | − vdef->vd_ndx, lib, version); | |
| 3176 | − } | |
| 3070 | + else | |
| 3071 | + set_ver_to_ver(&nb_local_ver, &local_ver, vdef->vd_ndx, | |
| 3072 | + lib, version); | |
| 3177 | 3073 | #if DEBUG_VERSION |
| 3178 | 3074 | printf (" verdaux(%u): %s\n", vdef->vd_ndx, version); |
| 3179 | 3075 | #endif |
| 3180 | − verdaux = (ElfW(Verdaux) *) (((char *) verdaux) + verdaux->vda_next); | |
| 3181 | 3076 | } |
| 3182 | 3077 | next = vdef->vd_next; |
| 3183 | 3078 | vdef = (ElfW(Verdef) *) (((char *) vdef) + next); |
| @@ -3189,15 +3084,15 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 5 unmodified lines | ||
| 3189 | 3084 | ElfW(Vernaux) *vernaux = |
| 3190 | 3085 | (ElfW(Vernaux) *) (((char *) vneed) + vneed->vn_aux); |
| 3191 | 3086 | |
| 3192 | − lib = (char *) dynstr + vneed->vn_file; | |
| 3087 | + lib = dynstr + vneed->vn_file; | |
| 3193 | 3088 | #if DEBUG_VERSION |
| 3194 | 3089 | printf ("verneed: %u %s\n", vneed->vn_version, lib); |
| 3195 | 3090 | #endif |
| 3196 | 3091 | for (i = 0; i < vneed->vn_cnt; i++) { |
| 3197 | 3092 | if ((vernaux->vna_other & 0x8000) == 0) { /* hidden */ |
| 3198 | − version = (char *) dynstr + vernaux->vna_name; | |
| 3199 | − save_def_need_index (&n_def_need, &def_need, | |
| 3200 | − vernaux->vna_other, lib, version); | |
| 3093 | + version = dynstr + vernaux->vna_name; | |
| 3094 | + set_ver_to_ver(&nb_local_ver, &local_ver, vernaux->vna_other, | |
| 3095 | + lib, version); | |
| 3201 | 3096 | #if DEBUG_VERSION |
| 3202 | 3097 | printf (" vernaux(%u): %u %u %s\n", |
| 3203 | 3098 | vernaux->vna_other, vernaux->vna_hash, |
| @@ -3212,10 +3107,11 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 8 unmodified lines | ||
| 3212 | 3107 | } |
| 3213 | 3108 | |
| 3214 | 3109 | #if DEBUG_VERSION |
| 3215 | − for (i = 0; i < n_def_need; i++) { | |
| 3216 | − if (def_need[i].lib) { | |
| 3110 | + for (i = 0; i < nb_local_ver; i++) { | |
| 3111 | + if (local_ver[i] > 0) { | |
| 3217 | 3112 | printf ("%d: lib: %s, version %s\n", |
| 3218 | − i, def_need[i].lib, def_need[i].version); | |
| 3113 | + i, sym_versions[local_ver[i]].lib, | |
| 3114 | + sym_version[local_ver[i]].version); | |
| 3219 | 3115 | } |
| 3220 | 3116 | } |
| 3221 | 3117 | #endif |
| @@ -3231,13 +3127,12 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 9 unmodified lines | ||
| 3231 | 3127 | sym_bind = ELFW(ST_BIND)(sym->st_info); |
| 3232 | 3128 | if (sym_bind == STB_LOCAL) |
| 3233 | 3129 | continue; |
| 3234 | − name = (char *) dynstr + sym->st_name; | |
| 3130 | + name = dynstr + sym->st_name; | |
| 3235 | 3131 | sym_index = set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, |
| 3236 | 3132 | sym->st_info, sym->st_other, sym->st_shndx, name); |
| 3237 | − if (versym && n_def_need && (*vsym & 0x8000) == 0 && | |
| 3238 | − *vsym > 0 && *vsym < n_def_need && | |
| 3239 | − def_need[*vsym].lib) { | |
| 3240 | − add_version_sym (s1->dynsymtab_section, sym_index, n_def_need, def_need, name, *vsym); | |
| 3133 | + if (versym && (*vsym & 0x8000) == 0 && | |
| 3134 | + *vsym > 0 && *vsym < nb_local_ver) { | |
| 3135 | + set_sym_version(sym_index, local_ver[*vsym]); | |
| 3241 | 3136 | } |
| 3242 | 3137 | } |
| 3243 | 3138 | |
| @@ -3245,7 +3140,7 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 1 unmodified line | ||
| 3245 | 3140 | for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { |
| 3246 | 3141 | switch(dt->d_tag) { |
| 3247 | 3142 | case DT_NEEDED: |
| 3248 | − name = (char *) dynstr + dt->d_un.d_val; | |
| 3143 | + name = dynstr + dt->d_un.d_val; | |
| 3249 | 3144 | for(j = 0; j < s1->nb_loaded_dlls; j++) { |
| 3250 | 3145 | dllref = s1->loaded_dlls[j]; |
| 3251 | 3146 | if (!strcmp(name, dllref->name)) |
| @@ -3262,7 +3157,7 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 10 unmodified lines | ||
| 3262 | 3157 | } |
| 3263 | 3158 | ret = 0; |
| 3264 | 3159 | the_end: |
| 3265 | − free_def_need (n_def_need, def_need); | |
| 3160 | + tcc_free(local_ver); | |
| 3266 | 3161 | tcc_free(dynstr); |
| 3267 | 3162 | tcc_free(dynsym); |
| 3268 | 3163 | tcc_free(dynamic); |