Unified · Split
| @@ -42,6 +42,34 @@ ST_DATA Section *symtab_section; · 41 unmodified lines | |||
| 42 | /* debug sections */ | 42 | /* debug sections */ |
| 43 | ST_DATA Section *stab_section, *stabstr_section; | 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 | /* XXX: avoid static variable */ | 73 | /* XXX: avoid static variable */ |
| 46 | static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */ | 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 | text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); | 89 | text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); |
| 62 | data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); | 90 | data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); |
| 63 | bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); | 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 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); | 96 | common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE); |
| 65 | common_section->sh_num = SHN_COMMON; | 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 | sec->sh_type = sh_type; | 230 | sec->sh_type = sh_type; |
| 199 | sec->sh_flags = sh_flags; | 231 | sec->sh_flags = sh_flags; |
| 200 | switch(sh_type) { | 232 | switch(sh_type) { |
| 233 | case SHT_GNU_versym: | ||
| 234 | sec->sh_addralign = 2; | ||
| 235 | break; | ||
| 201 | case SHT_HASH: | 236 | case SHT_HASH: |
| 202 | case SHT_REL: | 237 | case SHT_REL: |
| 203 | case SHT_RELA: | 238 | case SHT_RELA: |
| 204 | case SHT_DYNSYM: | 239 | case SHT_DYNSYM: |
| 205 | case SHT_SYMTAB: | 240 | case SHT_SYMTAB: |
| 206 | case SHT_DYNAMIC: | 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 | break; | 245 | break; |
| 209 | case SHT_STRTAB: | 246 | case SHT_STRTAB: |
| 210 | sec->sh_addralign = 1; | 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 | #endif | 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 | /* add an elf symbol : check if it is already defined and patch | 770 | /* add an elf symbol : check if it is already defined and patch |
| 520 | it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ | 771 | it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ |
| 521 | ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, | 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 | put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel)); | 2106 | put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel)); |
| 1856 | #endif | 2107 | #endif |
| 1857 | #endif | 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 | if (s1->do_debug) | 2112 | if (s1->do_debug) |
| 1859 | put_dt(dynamic, DT_DEBUG, 0); | 2113 | put_dt(dynamic, DT_DEBUG, 0); |
| 1860 | put_dt(dynamic, DT_NULL, 0); | 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 | ".dynstr", | 2391 | ".dynstr", |
| 2138 | ".hash", SHF_ALLOC); | 2392 | ".hash", SHF_ALLOC); |
| 2139 | dynstr = s1->dynsym->link; | 2393 | dynstr = s1->dynsym->link; |
| 2394 | versym_section->link = s1->dynsym; | ||
| 2395 | verneed_section->link = dynstr; | ||
| 2140 | 2396 | ||
| 2141 | /* add dynamic section */ | 2397 | /* add dynamic section */ |
| 2142 | dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, | 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 | build_got_entries(s1); | 2415 | build_got_entries(s1); |
| 2416 | version_add (s1); | ||
| 2160 | } | 2417 | } |
| 2161 | 2418 | ||
| 2162 | /* we add a section for symbols */ | 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 | int i, j, nb_syms, nb_dts, sym_bind, ret; | 3009 | int i, j, nb_syms, nb_dts, sym_bind, ret; |
| 2753 | ElfW(Sym) *sym, *dynsym; | 3010 | ElfW(Sym) *sym, *dynsym; |
| 2754 | ElfW(Dyn) *dt, *dynamic; | 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 | unsigned char *dynstr; | 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 | const char *name, *soname; | 3022 | const char *name, *soname; |
| 2757 | DLLReference *dllref; | 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 | dynamic = NULL; | 3040 | dynamic = NULL; |
| 2775 | dynsym = NULL; /* avoid warning */ | 3041 | dynsym = NULL; /* avoid warning */ |
| 2776 | dynstr = NULL; /* avoid warning */ | 3042 | dynstr = NULL; /* avoid warning */ |
| 3043 | nb_versyms = 0; | ||
| 3044 | verdef = NULL; | ||
| 3045 | verneed = NULL; | ||
| 3046 | versym = NULL; | ||
| 2777 | for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) { | 3047 | for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) { |
| 2778 | switch(sh->sh_type) { | 3048 | switch(sh->sh_type) { |
| 2779 | case SHT_DYNAMIC: | 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 | sh1 = &shdr[sh->sh_link]; | 3056 | sh1 = &shdr[sh->sh_link]; |
| 2787 | dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size); | 3057 | dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size); |
| 2788 | break; | 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 | default: | 3069 | default: |
| 2790 | break; | 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 | /* add the dll and its level */ | 3170 | /* add the dll and its level */ |
| 2816 | dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname)); | 3171 | dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname)); |
| 2817 | dllref->level = level; | 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 | dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); | 3174 | dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); |
| 2820 | 3175 | ||
| 2821 | /* add dynamic symbols in dynsym_section */ | 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 | sym_bind = ELFW(ST_BIND)(sym->st_info); | 3178 | sym_bind = ELFW(ST_BIND)(sym->st_info); |
| 2824 | if (sym_bind == STB_LOCAL) | 3179 | if (sym_bind == STB_LOCAL) |
| 2825 | continue; | 3180 | continue; |
| 2826 | name = (char *) dynstr + sym->st_name; | 3181 | name = (char *) dynstr + sym->st_name; |
| 2827 | set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, | 3182 | sym_index = set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, |
| 2828 | sym->st_info, sym->st_other, sym->st_shndx, name); | 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 | /* load all referenced DLLs */ | 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 | ret = 0; | 3210 | ret = 0; |
| 2851 | the_end: | 3211 | the_end: |
| 3212 | free_def_need (n_def_need, def_need); | ||
| 2852 | tcc_free(dynstr); | 3213 | tcc_free(dynstr); |
| 2853 | tcc_free(dynsym); | 3214 | tcc_free(dynsym); |
| 2854 | tcc_free(dynamic); | 3215 | tcc_free(dynamic); |
| 3216 | tcc_free(verdef); | ||
| 3217 | tcc_free(verneed); | ||
| 3218 | tcc_free(versym); | ||
| 2855 | tcc_free(shdr); | 3219 | tcc_free(shdr); |
| 2856 | return ret; | 3220 | return ret; |
| 2857 | } | 3221 | } |