History

elf: rewrite version support

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.

Michael Matz committed 6 years ago

Commit 8a93ce11 parent 25781e41 file · +144 −249Browse files

Unified · Split

tccelf.c+144−249
@@ -43,32 +43,19 @@ ST_DATA Section *symtab_section; · 42 unmodified lines
43ST_DATA Section *stab_section, *stabstr_section;43ST_DATA Section *stab_section, *stabstr_section;
44 44
45/* elf version information */45/* elf version information */
46ST_DATA int nb_version_sym;46struct sym_version {
47struct sym_info_struct {47 char *lib;
48 char *name;
49 ElfW(Sym) esym;
50};
51ST_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;
57ST_DATA int nb_need;
58ST_DATA int dt_verneednum;
59ST_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};
69ST_DATA ElfW(Half) next_version = 1;52static int nb_sym_versions;
70ST_DATA Section *versym_section;53static struct sym_version *sym_versions;
71ST_DATA Section *verneed_section;54static int nb_sym_to_version;
55static int *sym_to_version;
56static int dt_verneednum;
57static Section *versym_section;
58static Section *verneed_section;
72 59
73/* XXX: avoid static variable */60/* XXX: avoid static variable */
74static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */61static 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#endif557#endif
559 558
560ST_FUNC void
561save_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
583ST_FUNC void
584free_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
595ST_FUNC void
596add_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
645static void
646add_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
698static void559static void
699version_add (TCCState *s)560version_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 patch627/* 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_PE2906#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). */
2909static 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. */
2939static void
2940set_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 DLL2954/* 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 in2955 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#endif3064#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_VERSION3073#if DEBUG_VERSION
3178 printf (" verdaux(%u): %s\n", vdef->vd_ndx, version);3074 printf (" verdaux(%u): %s\n", vdef->vd_ndx, version);
3179#endif3075#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_VERSION3088#if DEBUG_VERSION
3194 printf ("verneed: %u %s\n", vneed->vn_version, lib);3089 printf ("verneed: %u %s\n", vneed->vn_version, lib);
3195#endif3090#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_VERSION3096#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_VERSION3109#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#endif3117#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);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t