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 | ST_DATA Section *stab_section, *stabstr_section; | 43 | ST_DATA Section *stab_section, *stabstr_section; |
| 44 | 44 | ||
| 45 | /* elf version information */ | 45 | /* elf version information */ |
| 46 | ST_DATA int nb_version_sym; | 46 | struct sym_version { |
| 47 | struct sym_info_struct { | 47 | char *lib; |
| 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; | ||
| 65 | char *version; | 48 | char *version; |
| 66 | int other; | 49 | int out_index; |
| 67 | } *aux; | 50 | int prev_same_lib; |
| 68 | } *need; | 51 | }; |
| 69 | ST_DATA ElfW(Half) next_version = 1; | 52 | static int nb_sym_versions; |
| 70 | ST_DATA Section *versym_section; | 53 | static struct sym_version *sym_versions; |
| 71 | ST_DATA Section *verneed_section; | 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 | /* XXX: avoid static variable */ | 60 | /* XXX: avoid static variable */ |
| 74 | static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */ | 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 | int i; | 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 | /* free all sections */ | 141 | /* free all sections */ |
| 143 | for(i = 1; i < s1->nb_sections; i++) | 142 | for(i = 1; i < s1->nb_sections; i++) |
| 144 | free_section(s1->sections[i]); | 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 | #endif | 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 | static void | 559 | static void |
| 699 | version_add (TCCState *s) | 560 | version_add (TCCState *s) |
| 700 | { | 561 | { |
| 701 | int i, j, found; | 562 | int i; |
| 702 | ElfW(Sym) *sym; | 563 | ElfW(Sym) *sym; |
| 703 | ElfW(Verneed) verneed; | 564 | ElfW(Verneed) *vn = NULL; |
| 704 | ElfW(Vernaux) aux; | ||
| 705 | Section *symtab; | 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 | const char *name; | 568 | const char *name; |
| 708 | void *ptr; | ||
| 709 | 569 | ||
| 710 | /* add needed symbols */ | 570 | /* add needed symbols */ |
| 711 | symtab = s->dynsym; | 571 | symtab = s->dynsym; |
| 712 | end_sym = symtab->data_offset / sizeof (ElfSym); | 572 | end_sym = symtab->data_offset / sizeof (ElfSym); |
| 573 | versym = section_ptr_add(versym_section, end_sym * sizeof(ElfW(Half))); | ||
| 713 | for (sym_index = 0; sym_index < end_sym; ++sym_index) { | 574 | for (sym_index = 0; sym_index < end_sym; ++sym_index) { |
| 575 | int dllindex, verndx; | ||
| 714 | sym = &((ElfW(Sym) *)symtab->data)[sym_index]; | 576 | sym = &((ElfW(Sym) *)symtab->data)[sym_index]; |
| 715 | name = (char *) symtab->link->data + sym->st_name; | 577 | name = (char *) symtab->link->data + sym->st_name; |
| 716 | found = 0; | 578 | dllindex = find_elf_sym(s->dynsymtab_section, name); |
| 717 | for (i = 0; !found && i < nb_version_sym; i++) { | 579 | verndx = (dllindex && dllindex < nb_sym_to_version) |
| 718 | for (j = 0; !found && j < version_sym[i].nb_sym_info; j++) { | 580 | ? sym_to_version[dllindex] : -1; |
| 719 | if (strcmp (version_sym[i].sym_info[j].name, name) == 0) { | 581 | if (verndx >= 0) { |
| 720 | found = 1; | 582 | if (!sym_versions[verndx].out_index) |
| 721 | add_need_sym (symtab, version_sym[i].lib, version_sym[i].version, name, sym_index); | 583 | sym_versions[verndx].out_index = nb_versions++; |
| 722 | } | 584 | versym[sym_index] = sym_versions[verndx].out_index; |
| 723 | } | 585 | } else |
| 724 | } | 586 | versym[sym_index] = 0; |
| 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 */ | ||
| 729 | } | 587 | } |
| 730 | /* generate verneed section */ | 588 | /* generate verneed section */ |
| 731 | verneed_section->sh_info = nb_need; | 589 | for (i = nb_sym_versions; i-- > 0;) { |
| 732 | for (i = 0; i < nb_need; i++) { | 590 | struct sym_version *sv = &sym_versions[i]; |
| 733 | verneed.vn_version = 1; | 591 | int n_same_libs = 0, prev; |
| 734 | verneed.vn_cnt = need[i].n_aux; | 592 | size_t vnofs; |
| 735 | verneed.vn_file = need[i].offset; | 593 | ElfW(Vernaux) *vna; |
| 736 | verneed.vn_aux = sizeof (verneed); | 594 | if (sv->out_index < 1) |
| 737 | verneed.vn_next = i == nb_need - 1 ? 0 : sizeof (verneed) + need[i].n_aux * sizeof (aux); | 595 | continue; |
| 738 | ptr = section_ptr_add (verneed_section, sizeof (verneed)); | 596 | vnofs = section_add(verneed_section, sizeof(*vn), 1); |
| 739 | memcpy (ptr, &verneed, sizeof (verneed)); | 597 | vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); |
| 740 | for (j = 0; j < need[i].n_aux; j++) { | 598 | vn->vn_version = 1; |
| 741 | aux.vna_hash = elf_hash (need[i].aux[j].version); | 599 | vn->vn_file = put_elf_str(verneed_section->link, sv->lib); |
| 742 | aux.vna_flags = 0; | 600 | vn->vn_aux = sizeof (*vn); |
| 743 | aux.vna_other = need[i].aux[j].other; | 601 | do { |
| 744 | aux.vna_name = need[i].aux[j].offset; | 602 | prev = sv->prev_same_lib; |
| 745 | aux.vna_next = j == need[i].n_aux - 1 ? 0 : sizeof (aux); | 603 | if (sv->out_index > 0) { |
| 746 | ptr = section_ptr_add (verneed_section, sizeof (aux)); | 604 | vna = section_ptr_add(verneed_section, sizeof(*vna)); |
| 747 | memcpy (ptr, &aux, sizeof (aux)); | 605 | vna->vna_hash = elf_hash (sv->version); |
| 748 | } | 606 | vna->vna_flags = 0; |
| 749 | } | 607 | vna->vna_other = sv->out_index; |
| 750 | /* free all info */ | 608 | sv->out_index = -2; |
| 751 | for (i = 0; i < nb_version_sym; i++) { | 609 | vna->vna_name = put_elf_str(verneed_section->link, sv->version); |
| 752 | for (j = 0; j < version_sym[i].nb_sym_info; j++) { | 610 | vna->vna_next = sizeof (*vna); |
| 753 | tcc_free (version_sym[i].sym_info[j].name); | 611 | n_same_libs++; |
| 754 | } | 612 | } |
| 755 | tcc_free (version_sym[i].lib); | 613 | sv = &sym_versions[prev]; |
| 756 | tcc_free (version_sym[i].version); | 614 | } while(prev >= 0); |
| 757 | tcc_free (version_sym[i].sym_info); | 615 | vna->vna_next = 0; |
| 758 | } | 616 | vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); |
| 759 | tcc_free (version_sym); | 617 | vn->vn_cnt = n_same_libs; |
| 760 | nb_version_sym = 0; | 618 | vn->vn_next = sizeof(*vn) + n_same_libs * sizeof(*vna); |
| 761 | version_sym = NULL; | 619 | nb_entries++; |
| 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); | ||
| 768 | } | 620 | } |
| 769 | tcc_free (need); | 621 | if (vn) |
| 770 | dt_verneednum = nb_need; | 622 | vn->vn_next = 0; |
| 771 | nb_need = 0; | 623 | verneed_section->sh_info = nb_entries; |
| 772 | need = NULL; | 624 | dt_verneednum = nb_entries; |
| 773 | } | 625 | } |
| 774 | 626 | ||
| 775 | /* add an elf symbol : check if it is already defined and patch | 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 | #ifndef TCC_TARGET_PE | 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 | /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL | 2954 | /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL |
| 3056 | is referenced by the user (so it should be added as DT_NEEDED in | 2955 | is referenced by the user (so it should be added as DT_NEEDED in |
| 3057 | the generated ELF file) */ | 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 | ElfW(Verdef) *verdef, *vdef; | 2965 | ElfW(Verdef) *verdef, *vdef; |
| 3067 | ElfW(Verneed) *verneed, *vneed; | 2966 | ElfW(Verneed) *verneed, *vneed; |
| 3068 | ElfW(Half) *versym, *vsym; | 2967 | ElfW(Half) *versym, *vsym; |
| 3069 | unsigned char *dynstr; | 2968 | char *dynstr; |
| 3070 | uint32_t next; | 2969 | uint32_t next; |
| 3071 | int sym_index; | 2970 | int sym_index; |
| 3072 | char *lib, *version; | 2971 | char *lib, *version; |
| 3073 | int n_def_need = 0; | 2972 | int nb_local_ver = 0, *local_ver = NULL; |
| 3074 | struct def_need_struct *def_need = NULL; | ||
| 3075 | const char *name, *soname; | 2973 | const char *name, *soname; |
| 3076 | DLLReference *dllref; | 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 | for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { | 3028 | for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { |
| 3131 | if (dt->d_tag == DT_SONAME) { | 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 | vdef->vd_version, vdef->vd_flags, vdef->vd_ndx, | 3062 | vdef->vd_version, vdef->vd_flags, vdef->vd_ndx, |
| 3165 | vdef->vd_hash); | 3063 | vdef->vd_hash); |
| 3166 | #endif | 3064 | #endif |
| 3167 | for (i = 0; i < vdef->vd_cnt; i++) { | 3065 | if (vdef->vd_cnt) { |
| 3168 | version = (char *) dynstr + verdaux->vda_name; | 3066 | version = dynstr + verdaux->vda_name; |
| 3169 | 3067 | ||
| 3170 | if (lib == NULL) { | 3068 | if (lib == NULL) |
| 3171 | lib = version; | 3069 | lib = version; |
| 3172 | } | 3070 | else |
| 3173 | else { | 3071 | set_ver_to_ver(&nb_local_ver, &local_ver, vdef->vd_ndx, |
| 3174 | save_def_need_index (&n_def_need, &def_need, | 3072 | lib, version); |
| 3175 | vdef->vd_ndx, lib, version); | ||
| 3176 | } | ||
| 3177 | #if DEBUG_VERSION | 3073 | #if DEBUG_VERSION |
| 3178 | printf (" verdaux(%u): %s\n", vdef->vd_ndx, version); | 3074 | printf (" verdaux(%u): %s\n", vdef->vd_ndx, version); |
| 3179 | #endif | 3075 | #endif |
| 3180 | verdaux = (ElfW(Verdaux) *) (((char *) verdaux) + verdaux->vda_next); | ||
| 3181 | } | 3076 | } |
| 3182 | next = vdef->vd_next; | 3077 | next = vdef->vd_next; |
| 3183 | vdef = (ElfW(Verdef) *) (((char *) vdef) + next); | 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 | ElfW(Vernaux) *vernaux = | 3084 | ElfW(Vernaux) *vernaux = |
| 3190 | (ElfW(Vernaux) *) (((char *) vneed) + vneed->vn_aux); | 3085 | (ElfW(Vernaux) *) (((char *) vneed) + vneed->vn_aux); |
| 3191 | 3086 | ||
| 3192 | lib = (char *) dynstr + vneed->vn_file; | 3087 | lib = dynstr + vneed->vn_file; |
| 3193 | #if DEBUG_VERSION | 3088 | #if DEBUG_VERSION |
| 3194 | printf ("verneed: %u %s\n", vneed->vn_version, lib); | 3089 | printf ("verneed: %u %s\n", vneed->vn_version, lib); |
| 3195 | #endif | 3090 | #endif |
| 3196 | for (i = 0; i < vneed->vn_cnt; i++) { | 3091 | for (i = 0; i < vneed->vn_cnt; i++) { |
| 3197 | if ((vernaux->vna_other & 0x8000) == 0) { /* hidden */ | 3092 | if ((vernaux->vna_other & 0x8000) == 0) { /* hidden */ |
| 3198 | version = (char *) dynstr + vernaux->vna_name; | 3093 | version = dynstr + vernaux->vna_name; |
| 3199 | save_def_need_index (&n_def_need, &def_need, | 3094 | set_ver_to_ver(&nb_local_ver, &local_ver, vernaux->vna_other, |
| 3200 | vernaux->vna_other, lib, version); | 3095 | lib, version); |
| 3201 | #if DEBUG_VERSION | 3096 | #if DEBUG_VERSION |
| 3202 | printf (" vernaux(%u): %u %u %s\n", | 3097 | printf (" vernaux(%u): %u %u %s\n", |
| 3203 | vernaux->vna_other, vernaux->vna_hash, | 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 | #if DEBUG_VERSION | 3109 | #if DEBUG_VERSION |
| 3215 | for (i = 0; i < n_def_need; i++) { | 3110 | for (i = 0; i < nb_local_ver; i++) { |
| 3216 | if (def_need[i].lib) { | 3111 | if (local_ver[i] > 0) { |
| 3217 | printf ("%d: lib: %s, version %s\n", | 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 | #endif | 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 | sym_bind = ELFW(ST_BIND)(sym->st_info); | 3127 | sym_bind = ELFW(ST_BIND)(sym->st_info); |
| 3232 | if (sym_bind == STB_LOCAL) | 3128 | if (sym_bind == STB_LOCAL) |
| 3233 | continue; | 3129 | continue; |
| 3234 | name = (char *) dynstr + sym->st_name; | 3130 | name = dynstr + sym->st_name; |
| 3235 | sym_index = set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, | 3131 | sym_index = set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, |
| 3236 | sym->st_info, sym->st_other, sym->st_shndx, name); | 3132 | sym->st_info, sym->st_other, sym->st_shndx, name); |
| 3237 | if (versym && n_def_need && (*vsym & 0x8000) == 0 && | 3133 | if (versym && (*vsym & 0x8000) == 0 && |
| 3238 | *vsym > 0 && *vsym < n_def_need && | 3134 | *vsym > 0 && *vsym < nb_local_ver) { |
| 3239 | def_need[*vsym].lib) { | 3135 | set_sym_version(sym_index, local_ver[*vsym]); |
| 3240 | add_version_sym (s1->dynsymtab_section, sym_index, n_def_need, def_need, name, *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 | for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { | 3140 | for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { |
| 3246 | switch(dt->d_tag) { | 3141 | switch(dt->d_tag) { |
| 3247 | case DT_NEEDED: | 3142 | case DT_NEEDED: |
| 3248 | name = (char *) dynstr + dt->d_un.d_val; | 3143 | name = dynstr + dt->d_un.d_val; |
| 3249 | for(j = 0; j < s1->nb_loaded_dlls; j++) { | 3144 | for(j = 0; j < s1->nb_loaded_dlls; j++) { |
| 3250 | dllref = s1->loaded_dlls[j]; | 3145 | dllref = s1->loaded_dlls[j]; |
| 3251 | if (!strcmp(name, dllref->name)) | 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 | ret = 0; | 3158 | ret = 0; |
| 3264 | the_end: | 3159 | the_end: |
| 3265 | free_def_need (n_def_need, def_need); | 3160 | tcc_free(local_ver); |
| 3266 | tcc_free(dynstr); | 3161 | tcc_free(dynstr); |
| 3267 | tcc_free(dynsym); | 3162 | tcc_free(dynsym); |
| 3268 | tcc_free(dynamic); | 3163 | tcc_free(dynamic); |