Unified · Split
| @@ -42,6 +42,34 @@ ST_DATA Section *symtab_section; · 41 unmodified lines | ||
| 42 | 42 | /* debug sections */ |
| 43 | 43 | ST_DATA Section *stab_section, *stabstr_section; |
| 44 | 44 | |
| 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; | |
| 65 | + 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; | |
| 72 | + | |
| 45 | 73 | /* XXX: avoid static variable */ |
| 46 | 74 | static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */ |
| 47 | 75 | |
| @@ -61,6 +89,10 @@ ST_FUNC void tccelf_new(TCCState *s) · 13 unmodified lines | ||
| 61 | 89 | text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); |
| 62 | 90 | data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
| 63 | 91 | bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); |
| 92 | + versym_section = new_section(s, ".gnu.version", SHT_GNU_versym, SHF_ALLOC); | |
| 93 | + versym_section->sh_entsize = sizeof(ElfW(Half)); | |
| 94 | + verneed_section = new_section(s, ".gnu.version_r", SHT_GNU_verneed, SHF_ALLOC); | |
| 95 | + verneed_section->sh_info = 2; | |
| 64 | 96 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); |
| 65 | 97 | common_section->sh_num = SHN_COMMON; |
| 66 | 98 | |
| @@ -198,13 +230,18 @@ ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh · 131 unmodified lines | ||
| 198 | 230 | sec->sh_type = sh_type; |
| 199 | 231 | sec->sh_flags = sh_flags; |
| 200 | 232 | switch(sh_type) { |
| 233 | + case SHT_GNU_versym: | |
| 234 | + sec->sh_addralign = 2; | |
| 235 | + break; | |
| 201 | 236 | case SHT_HASH: |
| 202 | 237 | case SHT_REL: |
| 203 | 238 | case SHT_RELA: |
| 204 | 239 | case SHT_DYNSYM: |
| 205 | 240 | case SHT_SYMTAB: |
| 206 | 241 | case SHT_DYNAMIC: |
| 207 | − sec->sh_addralign = 4; | |
| 242 | + case SHT_GNU_verneed: | |
| 243 | + case SHT_GNU_verdef: | |
| 244 | + sec->sh_addralign = PTR_SIZE; | |
| 208 | 245 | break; |
| 209 | 246 | case SHT_STRTAB: |
| 210 | 247 | sec->sh_addralign = 1; |
| @@ -516,6 +553,220 @@ ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name) · 305 unmodified lines | ||
| 516 | 553 | } |
| 517 | 554 | #endif |
| 518 | 555 | |
| 556 | +ST_FUNC void | |
| 557 | +save_def_need_index (int *n_def_need, struct def_need_struct **def_need, | |
| 558 | + unsigned int n, const char *lib, const char *version) | |
| 559 | +{ | |
| 560 | + /* add index in table */ | |
| 561 | + if (*n_def_need < n + 1) { | |
| 562 | + *def_need = (struct def_need_struct *) | |
| 563 | + tcc_realloc (*def_need, | |
| 564 | + (n + 1) * sizeof (struct def_need_struct)); | |
| 565 | + while (*n_def_need < n + 1) { | |
| 566 | + (*def_need)[*n_def_need].lib = NULL; | |
| 567 | + (*def_need)[*n_def_need].version = NULL; | |
| 568 | + (*def_need)[*n_def_need].nb_sym_info = 0; | |
| 569 | + (*def_need)[*n_def_need].sym_info = NULL; | |
| 570 | + (*n_def_need)++; | |
| 571 | + } | |
| 572 | + } | |
| 573 | + if ((*def_need)[n].lib == NULL) { | |
| 574 | + (*def_need)[n].lib = tcc_strdup (lib); | |
| 575 | + (*def_need)[n].version = tcc_strdup (version); | |
| 576 | + } | |
| 577 | +} | |
| 578 | + | |
| 579 | +ST_FUNC void | |
| 580 | +free_def_need (int n_def_need, struct def_need_struct *def_need) | |
| 581 | +{ | |
| 582 | + int i; | |
| 583 | + | |
| 584 | + for (i = 0; i < n_def_need; i++) { | |
| 585 | + tcc_free (def_need[i].lib); | |
| 586 | + tcc_free (def_need[i].version); | |
| 587 | + } | |
| 588 | + tcc_free (def_need); | |
| 589 | +} | |
| 590 | + | |
| 591 | +ST_FUNC void | |
| 592 | +add_version_sym (Section *s, int sym_index, int n_def_need, | |
| 593 | + struct def_need_struct *def_need, const char *name, unsigned int n) | |
| 594 | +{ | |
| 595 | + int i, j; | |
| 596 | + ElfW(Sym) *esym; | |
| 597 | + | |
| 598 | + /* check if present */ | |
| 599 | + esym = &((ElfW(Sym) *)s->data)[sym_index]; | |
| 600 | + for (i = 0; i < nb_version_sym; i++) { | |
| 601 | + for (j = 0; j < version_sym[i].nb_sym_info; j++) { | |
| 602 | + if (strcmp (version_sym[i].sym_info[j].name, name) == 0) { | |
| 603 | + if (memcmp (&version_sym[i].sym_info[j].esym, esym, sizeof (ElfW(Sym))) == 0) { | |
| 604 | + return; | |
| 605 | + } | |
| 606 | + version_sym[i].nb_sym_info--; | |
| 607 | + tcc_free (version_sym[i].sym_info[j].name); | |
| 608 | + for (; j < version_sym[i].nb_sym_info; j++) { | |
| 609 | + version_sym[i].sym_info[j] = version_sym[i].sym_info[j + 1]; | |
| 610 | + } | |
| 611 | + } | |
| 612 | + } | |
| 613 | + } | |
| 614 | + /* add new value */ | |
| 615 | + for (i = 0; i < nb_version_sym; i++) { | |
| 616 | + if (strcmp (def_need[n].lib, | |
| 617 | + version_sym[i].lib) == 0 && | |
| 618 | + strcmp (def_need[n].version, | |
| 619 | + version_sym[i].version) == 0) { | |
| 620 | + break; | |
| 621 | + } | |
| 622 | + } | |
| 623 | + if (i == nb_version_sym) { | |
| 624 | + version_sym = (struct def_need_struct *) | |
| 625 | + tcc_realloc (version_sym, | |
| 626 | + (nb_version_sym + 1) * sizeof (struct def_need_struct)); | |
| 627 | + version_sym[nb_version_sym].lib = tcc_strdup (def_need[n].lib); | |
| 628 | + version_sym[nb_version_sym].version = tcc_strdup (def_need[n].version); | |
| 629 | + version_sym[nb_version_sym].nb_sym_info = 0; | |
| 630 | + version_sym[nb_version_sym].sym_info = NULL; | |
| 631 | + nb_version_sym++; | |
| 632 | + } | |
| 633 | + version_sym[i].sym_info = (struct sym_info_struct *) | |
| 634 | + tcc_realloc (version_sym[i].sym_info, | |
| 635 | + (version_sym[i].nb_sym_info + 1) * sizeof (struct sym_info_struct)); | |
| 636 | + version_sym[i].sym_info[version_sym[i].nb_sym_info].name = tcc_strdup (name); | |
| 637 | + version_sym[i].sym_info[version_sym[i].nb_sym_info].esym = *esym; | |
| 638 | + version_sym[i].nb_sym_info++; | |
| 639 | +} | |
| 640 | + | |
| 641 | +static void | |
| 642 | +add_need_sym (Section *s, const char *soname, const char *version, const char *name, int sym_index) | |
| 643 | +{ | |
| 644 | + int i; | |
| 645 | + unsigned long size; | |
| 646 | + void *ptr; | |
| 647 | + int ver_index = 0; | |
| 648 | + struct need_struct *verlib = NULL; | |
| 649 | + ElfW(Half) vers; | |
| 650 | + | |
| 651 | + if (soname) { | |
| 652 | + for (i = 0; i < nb_need; i++) { | |
| 653 | + if (strcmp (soname, need[i].lib) == 0) { | |
| 654 | + verlib = &need[i]; | |
| 655 | + break; | |
| 656 | + } | |
| 657 | + } | |
| 658 | + if (verlib == NULL) { | |
| 659 | + need = (struct need_struct *) | |
| 660 | + tcc_realloc (need, (nb_need + 1) * sizeof (struct need_struct)); | |
| 661 | + need[nb_need].offset = put_elf_str(s->link, soname); | |
| 662 | + need[nb_need].lib = tcc_strdup (soname); | |
| 663 | + need[nb_need].n_aux = 0; | |
| 664 | + need[nb_need].aux = NULL; | |
| 665 | + verlib = &need[nb_need]; | |
| 666 | + nb_need++; | |
| 667 | + } | |
| 668 | + for (i = 0; i < verlib->n_aux; i++) { | |
| 669 | + if (strcmp (version, verlib->aux[i].version) == 0) { | |
| 670 | + ver_index = verlib->aux[i].other; | |
| 671 | + } | |
| 672 | + } | |
| 673 | + if (ver_index == 0) { | |
| 674 | + verlib->aux = (struct aux_struct *) | |
| 675 | + tcc_realloc (verlib->aux, (verlib->n_aux + 1) * sizeof (struct aux_struct)); | |
| 676 | + verlib->aux[verlib->n_aux].offset = put_elf_str(s->link, version); | |
| 677 | + verlib->aux[verlib->n_aux].version = tcc_strdup (version); | |
| 678 | + ver_index = verlib->aux[verlib->n_aux].other = ++next_version; | |
| 679 | + verlib->n_aux++; | |
| 680 | + } | |
| 681 | + } | |
| 682 | + /* update versym section */ | |
| 683 | + size = versym_section->data_offset / sizeof (vers); | |
| 684 | + for (i = size; i < (sym_index + 1); i++) { | |
| 685 | + ptr = section_ptr_add (versym_section, sizeof (vers)); | |
| 686 | + vers = 0; | |
| 687 | + memcpy (ptr, &vers, sizeof (vers)); | |
| 688 | + } | |
| 689 | + ptr = versym_section->data + sym_index * sizeof (vers); | |
| 690 | + vers = ver_index; | |
| 691 | + memcpy (ptr, &vers, sizeof (vers)); | |
| 692 | +} | |
| 693 | + | |
| 694 | +static void | |
| 695 | +version_add (TCCState *s) | |
| 696 | +{ | |
| 697 | + int i, j, found; | |
| 698 | + ElfW(Sym) *sym; | |
| 699 | + ElfW(Verneed) verneed; | |
| 700 | + ElfW(Vernaux) aux; | |
| 701 | + Section *symtab; | |
| 702 | + int sym_index, end_sym; | |
| 703 | + const char *name; | |
| 704 | + void *ptr; | |
| 705 | + | |
| 706 | + /* add needed symbols */ | |
| 707 | + symtab = s->dynsym; | |
| 708 | + end_sym = symtab->data_offset / sizeof (ElfSym); | |
| 709 | + for (sym_index = 0; sym_index < end_sym; ++sym_index) { | |
| 710 | + sym = &((ElfW(Sym) *)symtab->data)[sym_index]; | |
| 711 | + name = (char *) symtab->link->data + sym->st_name; | |
| 712 | + found = 0; | |
| 713 | + for (i = 0; !found && i < nb_version_sym; i++) { | |
| 714 | + for (j = 0; !found && j < version_sym[i].nb_sym_info; j++) { | |
| 715 | + if (strcmp (version_sym[i].sym_info[j].name, name) == 0) { | |
| 716 | + found = 1; | |
| 717 | + add_need_sym (symtab, version_sym[i].lib, version_sym[i].version, name, sym_index); | |
| 718 | + } | |
| 719 | + } | |
| 720 | + } | |
| 721 | + if (!found) { | |
| 722 | + add_need_sym (symtab, NULL, NULL, NULL, sym_index); | |
| 723 | + } | |
| 724 | + symtab = s->dynsym; /* symtab can be realocated by add_need_sym */ | |
| 725 | + } | |
| 726 | + /* generate verneed section */ | |
| 727 | + for (i = 0; i < nb_need; i++) { | |
| 728 | + verneed.vn_version = 1; | |
| 729 | + verneed.vn_cnt = need[i].n_aux; | |
| 730 | + verneed.vn_file = need[i].offset; | |
| 731 | + verneed.vn_aux = sizeof (verneed); | |
| 732 | + verneed.vn_next = i == nb_need - 1 ? 0 : sizeof (verneed) + need[i].n_aux * sizeof (aux); | |
| 733 | + ptr = section_ptr_add (verneed_section, sizeof (verneed)); | |
| 734 | + memcpy (ptr, &verneed, sizeof (verneed)); | |
| 735 | + for (j = 0; j < need[i].n_aux; j++) { | |
| 736 | + aux.vna_hash = elf_hash (need[i].aux[j].version); | |
| 737 | + aux.vna_flags = 0; | |
| 738 | + aux.vna_other = need[i].aux[j].other; | |
| 739 | + aux.vna_name = need[i].aux[j].offset; | |
| 740 | + aux.vna_next = j == need[i].n_aux - 1 ? 0 : sizeof (aux); | |
| 741 | + ptr = section_ptr_add (verneed_section, sizeof (aux)); | |
| 742 | + memcpy (ptr, &aux, sizeof (aux)); | |
| 743 | + } | |
| 744 | + } | |
| 745 | + /* free all info */ | |
| 746 | + for (i = 0; i < nb_version_sym; i++) { | |
| 747 | + for (j = 0; j < version_sym[i].nb_sym_info; j++) { | |
| 748 | + tcc_free (version_sym[i].sym_info[j].name); | |
| 749 | + } | |
| 750 | + tcc_free (version_sym[i].lib); | |
| 751 | + tcc_free (version_sym[i].version); | |
| 752 | + tcc_free (version_sym[i].sym_info); | |
| 753 | + } | |
| 754 | + tcc_free (version_sym); | |
| 755 | + nb_version_sym = 0; | |
| 756 | + version_sym = NULL; | |
| 757 | + for (i = 0; i < nb_need; i++) { | |
| 758 | + tcc_free (need[i].lib); | |
| 759 | + for (j = 0; j < need[i].n_aux; j++) { | |
| 760 | + tcc_free (need[i].aux[j].version); | |
| 761 | + } | |
| 762 | + tcc_free (need[i].aux); | |
| 763 | + } | |
| 764 | + tcc_free (need); | |
| 765 | + dt_verneednum = nb_need; | |
| 766 | + nb_need = 0; | |
| 767 | + need = NULL; | |
| 768 | +} | |
| 769 | + | |
| 519 | 770 | /* add an elf symbol : check if it is already defined and patch |
| 520 | 771 | it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ |
| 521 | 772 | ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, |
| @@ -1855,6 +2106,9 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) · 1333 unmodified lines | ||
| 1855 | 2106 | put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel)); |
| 1856 | 2107 | #endif |
| 1857 | 2108 | #endif |
| 2109 | + put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr); | |
| 2110 | + put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum); | |
| 2111 | + put_dt(dynamic, DT_VERSYM, versym_section->sh_addr); | |
| 1858 | 2112 | if (s1->do_debug) |
| 1859 | 2113 | put_dt(dynamic, DT_DEBUG, 0); |
| 1860 | 2114 | put_dt(dynamic, DT_NULL, 0); |
| @@ -2137,6 +2391,8 @@ static int elf_output_file(TCCState *s1, const char *filename) · 276 unmodified lines | ||
| 2137 | 2391 | ".dynstr", |
| 2138 | 2392 | ".hash", SHF_ALLOC); |
| 2139 | 2393 | dynstr = s1->dynsym->link; |
| 2394 | + versym_section->link = s1->dynsym; | |
| 2395 | + verneed_section->link = dynstr; | |
| 2140 | 2396 | |
| 2141 | 2397 | /* add dynamic section */ |
| 2142 | 2398 | dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, |
| @@ -2157,6 +2413,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 14 unmodified lines | ||
| 2157 | 2413 | } |
| 2158 | 2414 | } |
| 2159 | 2415 | build_got_entries(s1); |
| 2416 | + version_add (s1); | |
| 2160 | 2417 | } |
| 2161 | 2418 | |
| 2162 | 2419 | /* we add a section for symbols */ |
| @@ -2752,7 +3009,16 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 589 unmodified lines | ||
| 2752 | 3009 | int i, j, nb_syms, nb_dts, sym_bind, ret; |
| 2753 | 3010 | ElfW(Sym) *sym, *dynsym; |
| 2754 | 3011 | ElfW(Dyn) *dt, *dynamic; |
| 3012 | + int nb_versyms; | |
| 3013 | + ElfW(Verdef) *verdef, *vdef; | |
| 3014 | + ElfW(Verneed) *verneed, *vneed; | |
| 3015 | + ElfW(Half) *versym, *vsym; | |
| 2755 | 3016 | unsigned char *dynstr; |
| 3017 | + uint32_t next; | |
| 3018 | + int sym_index; | |
| 3019 | + char *lib, *version; | |
| 3020 | + int n_def_need = 0; | |
| 3021 | + struct def_need_struct *def_need = NULL; | |
| 2756 | 3022 | const char *name, *soname; |
| 2757 | 3023 | DLLReference *dllref; |
| 2758 | 3024 | |
| @@ -2774,6 +3040,10 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 15 unmodified lines | ||
| 2774 | 3040 | dynamic = NULL; |
| 2775 | 3041 | dynsym = NULL; /* avoid warning */ |
| 2776 | 3042 | dynstr = NULL; /* avoid warning */ |
| 3043 | + nb_versyms = 0; | |
| 3044 | + verdef = NULL; | |
| 3045 | + verneed = NULL; | |
| 3046 | + versym = NULL; | |
| 2777 | 3047 | for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) { |
| 2778 | 3048 | switch(sh->sh_type) { |
| 2779 | 3049 | case SHT_DYNAMIC: |
| @@ -2786,6 +3056,16 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 6 unmodified lines | ||
| 2786 | 3056 | sh1 = &shdr[sh->sh_link]; |
| 2787 | 3057 | dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size); |
| 2788 | 3058 | break; |
| 3059 | + case SHT_GNU_verdef: | |
| 3060 | + verdef = load_data(fd, sh->sh_offset, sh->sh_size); | |
| 3061 | + break; | |
| 3062 | + case SHT_GNU_verneed: | |
| 3063 | + verneed = load_data(fd, sh->sh_offset, sh->sh_size); | |
| 3064 | + break; | |
| 3065 | + case SHT_GNU_versym: | |
| 3066 | + nb_versyms = sh->sh_size / sizeof(ElfW(Half)); | |
| 3067 | + versym = load_data(fd, sh->sh_offset, sh->sh_size); | |
| 3068 | + break; | |
| 2789 | 3069 | default: |
| 2790 | 3070 | break; |
| 2791 | 3071 | } |
| @@ -2812,6 +3092,81 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 20 unmodified lines | ||
| 2812 | 3092 | } |
| 2813 | 3093 | } |
| 2814 | 3094 | |
| 3095 | + if (nb_versyms != nb_syms) { | |
| 3096 | + tcc_free (versym); | |
| 3097 | + versym = NULL; | |
| 3098 | + } | |
| 3099 | + | |
| 3100 | +#define DEBUG_VERSION 0 | |
| 3101 | + | |
| 3102 | + if (versym && verdef) { | |
| 3103 | + lib = NULL; | |
| 3104 | + vdef = verdef; | |
| 3105 | + do { | |
| 3106 | + ElfW(Verdaux) *verdaux = | |
| 3107 | + (ElfW(Verdaux) *) (((char *) vdef) + vdef->vd_aux); | |
| 3108 | + | |
| 3109 | +#if DEBUG_VERSION | |
| 3110 | + printf ("verdef: version:%u flags:%u index:%u, hash:%u\n", | |
| 3111 | + vdef->vd_version, vdef->vd_flags, vdef->vd_ndx, | |
| 3112 | + vdef->vd_hash); | |
| 3113 | +#endif | |
| 3114 | + for (i = 0; i < vdef->vd_cnt; i++) { | |
| 3115 | + version = (char *) dynstr + verdaux->vda_name; | |
| 3116 | + | |
| 3117 | + if (lib == NULL) { | |
| 3118 | + lib = version; | |
| 3119 | + } | |
| 3120 | + else { | |
| 3121 | + save_def_need_index (&n_def_need, &def_need, | |
| 3122 | + vdef->vd_ndx, lib, version); | |
| 3123 | + } | |
| 3124 | +#if DEBUG_VERSION | |
| 3125 | + printf (" verdaux(%u): %s\n", vdef->vd_ndx, version); | |
| 3126 | +#endif | |
| 3127 | + verdaux = (ElfW(Verdaux) *) (((char *) verdaux) + verdaux->vda_next); | |
| 3128 | + } | |
| 3129 | + next = vdef->vd_next; | |
| 3130 | + vdef = (ElfW(Verdef) *) (((char *) vdef) + next); | |
| 3131 | + } while (next); | |
| 3132 | + } | |
| 3133 | + if (versym && verneed) { | |
| 3134 | + vneed = verneed; | |
| 3135 | + do { | |
| 3136 | + ElfW(Vernaux) *vernaux = | |
| 3137 | + (ElfW(Vernaux) *) (((char *) vneed) + vneed->vn_aux); | |
| 3138 | + | |
| 3139 | + lib = (char *) dynstr + vneed->vn_file; | |
| 3140 | +#if DEBUG_VERSION | |
| 3141 | + printf ("verneed: %u %s\n", vneed->vn_version, lib); | |
| 3142 | +#endif | |
| 3143 | + for (i = 0; i < vneed->vn_cnt; i++) { | |
| 3144 | + if ((vernaux->vna_other & 0x8000) == 0) { /* hidden */ | |
| 3145 | + version = (char *) dynstr + vernaux->vna_name; | |
| 3146 | + save_def_need_index (&n_def_need, &def_need, | |
| 3147 | + vernaux->vna_other, lib, version); | |
| 3148 | +#if DEBUG_VERSION | |
| 3149 | + printf (" vernaux(%u): %u %u %s\n", | |
| 3150 | + vernaux->vna_other, vernaux->vna_hash, | |
| 3151 | + vernaux->vna_flags, version); | |
| 3152 | +#endif | |
| 3153 | + } | |
| 3154 | + vernaux = (ElfW(Vernaux) *) (((char *) vernaux) + vernaux->vna_next); | |
| 3155 | + } | |
| 3156 | + next = vneed->vn_next; | |
| 3157 | + vneed = (ElfW(Verneed) *) (((char *) vneed) + next); | |
| 3158 | + } while (next); | |
| 3159 | + } | |
| 3160 | + | |
| 3161 | +#if DEBUG_VERSION | |
| 3162 | + for (i = 0; i < n_def_need; i++) { | |
| 3163 | + if (def_need[i].lib) { | |
| 3164 | + printf ("%d: lib: %s, version %s\n", | |
| 3165 | + i, def_need[i].lib, def_need[i].version); | |
| 3166 | + } | |
| 3167 | + } | |
| 3168 | +#endif | |
| 3169 | + | |
| 2815 | 3170 | /* add the dll and its level */ |
| 2816 | 3171 | dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname)); |
| 2817 | 3172 | dllref->level = level; |
| @@ -2819,13 +3174,18 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 1 unmodified line | ||
| 2819 | 3174 | dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); |
| 2820 | 3175 | |
| 2821 | 3176 | /* add dynamic symbols in dynsym_section */ |
| 2822 | − for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) { | |
| 3177 | + for(i = 1, sym = dynsym + 1, vsym = versym + 1; i < nb_syms; i++, sym++, vsym++) { | |
| 2823 | 3178 | sym_bind = ELFW(ST_BIND)(sym->st_info); |
| 2824 | 3179 | if (sym_bind == STB_LOCAL) |
| 2825 | 3180 | continue; |
| 2826 | 3181 | name = (char *) dynstr + sym->st_name; |
| 2827 | − set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, | |
| 2828 | − sym->st_info, sym->st_other, sym->st_shndx, name); | |
| 3182 | + sym_index = set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, | |
| 3183 | + sym->st_info, sym->st_other, sym->st_shndx, name); | |
| 3184 | + if (versym && n_def_need && (*vsym & 0x8000) == 0 && | |
| 3185 | + *vsym > 0 && *vsym < n_def_need && | |
| 3186 | + def_need[*vsym].lib) { | |
| 3187 | + add_version_sym (s1->dynsymtab_section, sym_index, n_def_need, def_need, name, *vsym); | |
| 3188 | + } | |
| 2829 | 3189 | } |
| 2830 | 3190 | |
| 2831 | 3191 | /* load all referenced DLLs */ |
| @@ -2849,9 +3209,13 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 17 unmodified lines | ||
| 2849 | 3209 | } |
| 2850 | 3210 | ret = 0; |
| 2851 | 3211 | the_end: |
| 3212 | + free_def_need (n_def_need, def_need); | |
| 2852 | 3213 | tcc_free(dynstr); |
| 2853 | 3214 | tcc_free(dynsym); |
| 2854 | 3215 | tcc_free(dynamic); |
| 3216 | + tcc_free(verdef); | |
| 3217 | + tcc_free(verneed); | |
| 3218 | + tcc_free(versym); | |
| 2855 | 3219 | tcc_free(shdr); |
| 2856 | 3220 | return ret; |
| 2857 | 3221 | } |