libtcc.c: - integrate find_dllref loop into tcc_add_dllref() tccelf.c: - make sure a DT_NEEDED tag is put for versions even when the dll was not previously loaded. Related commit 4c82b003420fabbb95e077866784badc1a49189b 48 insertions(+), 77 deletions(-)
Unified · Split
| @@ -957,11 +957,29 @@ LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname) · 956 unmodified lines | |||
| 957 | return 0; | 957 | return 0; |
| 958 | } | 958 | } |
| 959 | 959 | ||
| 960 | ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname) | 960 | /* add/update a 'DLLReference', Just find if level == -1 */ |
| 961 | ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level) | ||
| 961 | { | 962 | { |
| 962 | DLLReference *ref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname)); | 963 | DLLReference *ref = NULL; |
| 964 | int i; | ||
| 965 | for (i = 0; i < s1->nb_loaded_dlls; i++) | ||
| 966 | if (0 == strcmp(s1->loaded_dlls[i]->name, dllname)) { | ||
| 967 | ref = s1->loaded_dlls[i]; | ||
| 968 | break; | ||
| 969 | } | ||
| 970 | if (level == -1) | ||
| 971 | return ref; | ||
| 972 | if (ref) { | ||
| 973 | if (level < ref->level) | ||
| 974 | ref->level = level; | ||
| 975 | ref->found = 1; | ||
| 976 | return ref; | ||
| 977 | } | ||
| 978 | ref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname)); | ||
| 963 | strcpy(ref->name, dllname); | 979 | strcpy(ref->name, dllname); |
| 964 | dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, ref); | 980 | dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, ref); |
| 981 | ref->level = level; | ||
| 982 | ref->index = s1->nb_loaded_dlls; | ||
| 965 | return ref; | 983 | return ref; |
| 966 | } | 984 | } |
| 967 | 985 | ||
| @@ -1042,7 +1060,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) · 74 unmodified lines | |||
| 1042 | soname = macho_tbd_soname(filename); | 1060 | soname = macho_tbd_soname(filename); |
| 1043 | dl = dlopen(soname, RTLD_GLOBAL | RTLD_LAZY); | 1061 | dl = dlopen(soname, RTLD_GLOBAL | RTLD_LAZY); |
| 1044 | if (dl) | 1062 | if (dl) |
| 1045 | tcc_add_dllref(s1, soname)->handle = dl, ret = 0; | 1063 | tcc_add_dllref(s1, soname, 0)->handle = dl, ret = 0; |
| 1046 | if (filename != soname) | 1064 | if (filename != soname) |
| 1047 | tcc_free((void *)soname); | 1065 | tcc_free((void *)soname); |
| 1048 | #endif | 1066 | #endif |
| @@ -1070,7 +1088,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) · 21 unmodified lines | |||
| 1070 | #ifdef TCC_IS_NATIVE | 1088 | #ifdef TCC_IS_NATIVE |
| 1071 | void* dl = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); | 1089 | void* dl = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); |
| 1072 | if (dl) | 1090 | if (dl) |
| 1073 | tcc_add_dllref(s1, filename)->handle = dl, ret = 0; | 1091 | tcc_add_dllref(s1, filename, 0)->handle = dl, ret = 0; |
| 1074 | #endif | 1092 | #endif |
| 1075 | } else | 1093 | } else |
| 1076 | ret = tcc_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0); | 1094 | ret = tcc_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0); |
| @@ -609,6 +609,7 @@ typedef struct Section { · 608 unmodified lines | |||
| 609 | typedef struct DLLReference { | 609 | typedef struct DLLReference { |
| 610 | int level; | 610 | int level; |
| 611 | void *handle; | 611 | void *handle; |
| 612 | unsigned char found, index; | ||
| 612 | char name[1]; | 613 | char name[1]; |
| 613 | } DLLReference; | 614 | } DLLReference; |
| 614 | 615 | ||
| @@ -1279,7 +1280,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind); · 664 unmodified lines | |||
| 1279 | #ifdef _WIN32 | 1280 | #ifdef _WIN32 |
| 1280 | ST_FUNC char *normalize_slashes(char *path); | 1281 | ST_FUNC char *normalize_slashes(char *path); |
| 1281 | #endif | 1282 | #endif |
| 1282 | ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname); | 1283 | ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level); |
| 1283 | ST_FUNC char *tcc_load_text(int fd); | 1284 | ST_FUNC char *tcc_load_text(int fd); |
| 1284 | 1285 | ||
| 1285 | /* tcc_parse_args return codes: */ | 1286 | /* tcc_parse_args return codes: */ |
| @@ -547,7 +547,7 @@ LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, · 546 unmodified lines | |||
| 547 | static void | 547 | static void |
| 548 | version_add (TCCState *s1) | 548 | version_add (TCCState *s1) |
| 549 | { | 549 | { |
| 550 | int i, j; | 550 | int i; |
| 551 | ElfW(Sym) *sym; | 551 | ElfW(Sym) *sym; |
| 552 | ElfW(Verneed) *vn = NULL; | 552 | ElfW(Verneed) *vn = NULL; |
| 553 | Section *symtab; | 553 | Section *symtab; |
| @@ -594,14 +594,8 @@ version_add (TCCState *s1) · 40 unmodified lines | |||
| 594 | ElfW(Vernaux) *vna = 0; | 594 | ElfW(Vernaux) *vna = 0; |
| 595 | if (sv->out_index < 1) | 595 | if (sv->out_index < 1) |
| 596 | continue; | 596 | continue; |
| 597 | /* If present in verneed it should be in DT_NEEDED */ | 597 | /* make sure that a DT_NEEDED tag is put */ |
| 598 | for (j = 0; j < s1->nb_loaded_dlls; j++) { | 598 | tcc_add_dllref(s1, sv->lib, 0); |
| 599 | DLLReference *dllref = s1->loaded_dlls[j]; | ||
| 600 | if (!strcmp(sv->lib, dllref->name)) { | ||
| 601 | dllref->level = 0; | ||
| 602 | break; | ||
| 603 | } | ||
| 604 | } | ||
| 605 | vnofs = section_add(verneed_section, sizeof(*vn), 1); | 599 | vnofs = section_add(verneed_section, sizeof(*vn), 1); |
| 606 | vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); | 600 | vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); |
| 607 | vn->vn_version = 1; | 601 | vn->vn_version = 1; |
| @@ -3425,14 +3419,13 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 2817 unmodified lines | |||
| 3425 | { | 3419 | { |
| 3426 | ElfW(Ehdr) ehdr; | 3420 | ElfW(Ehdr) ehdr; |
| 3427 | ElfW(Shdr) *shdr, *sh, *sh1; | 3421 | ElfW(Shdr) *shdr, *sh, *sh1; |
| 3428 | int i, j, nb_syms, nb_dts, sym_bind, ret; | 3422 | int i, nb_syms, nb_dts, sym_bind, ret = -1; |
| 3429 | ElfW(Sym) *sym, *dynsym; | 3423 | ElfW(Sym) *sym, *dynsym; |
| 3430 | ElfW(Dyn) *dt, *dynamic; | 3424 | ElfW(Dyn) *dt, *dynamic; |
| 3431 | 3425 | ||
| 3432 | char *dynstr; | 3426 | char *dynstr; |
| 3433 | int sym_index; | 3427 | int sym_index; |
| 3434 | const char *name, *soname; | 3428 | const char *name, *soname; |
| 3435 | DLLReference *dllref; | ||
| 3436 | struct versym_info v; | 3429 | struct versym_info v; |
| 3437 | 3430 | ||
| 3438 | full_read(fd, &ehdr, sizeof(ehdr)); | 3431 | full_read(fd, &ehdr, sizeof(ehdr)); |
| @@ -3482,37 +3475,24 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 43 unmodified lines | |||
| 3482 | } | 3475 | } |
| 3483 | } | 3476 | } |
| 3484 | 3477 | ||
| 3478 | if (!dynamic) | ||
| 3479 | goto the_end; | ||
| 3480 | |||
| 3485 | /* compute the real library name */ | 3481 | /* compute the real library name */ |
| 3486 | soname = tcc_basename(filename); | 3482 | soname = tcc_basename(filename); |
| 3487 | 3483 | for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) | |
| 3488 | for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { | 3484 | if (dt->d_tag == DT_SONAME) |
| 3489 | if (dt->d_tag == DT_SONAME) { | ||
| 3490 | soname = dynstr + dt->d_un.d_val; | 3485 | soname = dynstr + dt->d_un.d_val; |
| 3491 | } else if (dt->d_tag == DT_RPATH) { | ||
| 3492 | tcc_add_library_path(s1, dynstr + dt->d_un.d_val); | ||
| 3493 | } | ||
| 3494 | } | ||
| 3495 | 3486 | ||
| 3496 | /* if the dll is already loaded, do not load it */ | 3487 | /* if the dll is already loaded, do not load it */ |
| 3497 | for(i = 0; i < s1->nb_loaded_dlls; i++) { | 3488 | if (tcc_add_dllref(s1, soname, level)->found) |
| 3498 | dllref = s1->loaded_dlls[i]; | 3489 | goto ret_success; |
| 3499 | if (!strcmp(soname, dllref->name)) { | ||
| 3500 | /* but update level if needed */ | ||
| 3501 | if (level < dllref->level) | ||
| 3502 | dllref->level = level; | ||
| 3503 | ret = 0; | ||
| 3504 | goto the_end; | ||
| 3505 | } | ||
| 3506 | } | ||
| 3507 | 3490 | ||
| 3508 | if (v.nb_versyms != nb_syms) | 3491 | if (v.nb_versyms != nb_syms) |
| 3509 | tcc_free (v.versym), v.versym = NULL; | 3492 | tcc_free (v.versym), v.versym = NULL; |
| 3510 | else | 3493 | else |
| 3511 | store_version(s1, &v, dynstr); | 3494 | store_version(s1, &v, dynstr); |
| 3512 | 3495 | ||
| 3513 | /* add the dll and its level */ | ||
| 3514 | tcc_add_dllref(s1, soname)->level = level; | ||
| 3515 | |||
| 3516 | /* add dynamic symbols in dynsym_section */ | 3496 | /* add dynamic symbols in dynsym_section */ |
| 3517 | for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) { | 3497 | for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) { |
| 3518 | sym_bind = ELFW(ST_BIND)(sym->st_info); | 3498 | sym_bind = ELFW(ST_BIND)(sym->st_info); |
| @@ -3528,25 +3508,25 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) · 9 unmodified lines | |||
| 3528 | } | 3508 | } |
| 3529 | } | 3509 | } |
| 3530 | 3510 | ||
| 3511 | for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) | ||
| 3512 | if (dt->d_tag == DT_RPATH) | ||
| 3513 | tcc_add_library_path(s1, dynstr + dt->d_un.d_val); | ||
| 3514 | |||
| 3531 | /* load all referenced DLLs */ | 3515 | /* load all referenced DLLs */ |
| 3532 | for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { | 3516 | for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { |
| 3533 | switch(dt->d_tag) { | 3517 | switch(dt->d_tag) { |
| 3534 | case DT_NEEDED: | 3518 | case DT_NEEDED: |
| 3535 | name = dynstr + dt->d_un.d_val; | 3519 | name = dynstr + dt->d_un.d_val; |
| 3536 | for(j = 0; j < s1->nb_loaded_dlls; j++) { | 3520 | if (tcc_add_dllref(s1, name, -1)) |
| 3537 | dllref = s1->loaded_dlls[j]; | 3521 | continue; |
| 3538 | if (!strcmp(name, dllref->name)) | ||
| 3539 | goto already_loaded; | ||
| 3540 | } | ||
| 3541 | if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) { | 3522 | if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) { |
| 3542 | tcc_error_noabort("referenced dll '%s' not found", name); | 3523 | tcc_error_noabort("referenced dll '%s' not found", name); |
| 3543 | ret = -1; | ||
| 3544 | goto the_end; | 3524 | goto the_end; |
| 3545 | } | 3525 | } |
| 3546 | already_loaded: | ||
| 3547 | break; | ||
| 3548 | } | 3526 | } |
| 3549 | } | 3527 | } |
| 3528 | |||
| 3529 | ret_success: | ||
| 3550 | ret = 0; | 3530 | ret = 0; |
| 3551 | the_end: | 3531 | the_end: |
| 3552 | tcc_free(dynstr); | 3532 | tcc_free(dynstr); |
| @@ -835,25 +835,6 @@ static uint32_t macho_swap32(uint32_t x) · 834 unmodified lines | |||
| 835 | return (x >> 24) | (x << 24) | ((x >> 8) & 0xff00) | ((x & 0xff00) << 8); | 835 | return (x >> 24) | (x << 24) | ((x >> 8) & 0xff00) | ((x & 0xff00) << 8); |
| 836 | } | 836 | } |
| 837 | #define SWAP(x) (swap ? macho_swap32(x) : (x)) | 837 | #define SWAP(x) (swap ? macho_swap32(x) : (x)) |
| 838 | |||
| 839 | ST_FUNC int macho_add_dllref(TCCState* s1, int lev, const char* soname) | ||
| 840 | { | ||
| 841 | /* if the dll is already loaded, do not load it */ | ||
| 842 | DLLReference *dllref; | ||
| 843 | int i; | ||
| 844 | for(i = 0; i < s1->nb_loaded_dlls; i++) { | ||
| 845 | dllref = s1->loaded_dlls[i]; | ||
| 846 | if (!strcmp(soname, dllref->name)) { | ||
| 847 | /* but update level if needed */ | ||
| 848 | if (lev < dllref->level) | ||
| 849 | dllref->level = lev; | ||
| 850 | return -1; | ||
| 851 | } | ||
| 852 | } | ||
| 853 | tcc_add_dllref(s1, soname)->level = lev; | ||
| 854 | return 0; | ||
| 855 | } | ||
| 856 | |||
| 857 | #define tbd_parse_movepast(s) \ | 838 | #define tbd_parse_movepast(s) \ |
| 858 | (pos = (pos = strstr(pos, s)) ? pos + strlen(s) : NULL) | 839 | (pos = (pos = strstr(pos, s)) ? pos + strlen(s) : NULL) |
| 859 | #define tbd_parse_movetoany(cs) (pos = strpbrk(pos, cs)) | 840 | #define tbd_parse_movetoany(cs) (pos = strpbrk(pos, cs)) |
| @@ -925,7 +906,8 @@ ST_FUNC int macho_load_tbd(TCCState* s1, int fd, const char* filename, int lev) · 65 unmodified lines | |||
| 925 | if (!tbd_parse_movetoany("\n \"'")) goto the_end; | 906 | if (!tbd_parse_movetoany("\n \"'")) goto the_end; |
| 926 | tbd_parse_trample; | 907 | tbd_parse_trample; |
| 927 | ret = 0; | 908 | ret = 0; |
| 928 | if (macho_add_dllref(s1, lev, soname) != 0) goto the_end; | 909 | if (tcc_add_dllref(s1, soname, lev)->found) |
| 910 | goto the_end; | ||
| 929 | while(pos) { | 911 | while(pos) { |
| 930 | char* sym = NULL; | 912 | char* sym = NULL; |
| 931 | int cont = 1; | 913 | int cont = 1; |
| @@ -1047,7 +1029,7 @@ ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev) · 115 unmodified lines | |||
| 1047 | lc = (struct load_command*) ((char*)lc + lc->cmdsize); | 1029 | lc = (struct load_command*) ((char*)lc + lc->cmdsize); |
| 1048 | } | 1030 | } |
| 1049 | 1031 | ||
| 1050 | if (0 != macho_add_dllref(s1, lev, soname)) | 1032 | if (tcc_add_dllref(s1, soname, lev)->found) |
| 1051 | goto the_end; | 1033 | goto the_end; |
| 1052 | 1034 | ||
| 1053 | if (!nsyms || !nextdef) | 1035 | if (!nsyms || !nextdef) |
| @@ -1533,16 +1533,6 @@ ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t va · 1532 unmodified lines | |||
| 1533 | ); | 1533 | ); |
| 1534 | } | 1534 | } |
| 1535 | 1535 | ||
| 1536 | static int pe_add_dllref(TCCState *s1, const char *dllname) | ||
| 1537 | { | ||
| 1538 | int i; | ||
| 1539 | for (i = 0; i < s1->nb_loaded_dlls; ++i) | ||
| 1540 | if (0 == strcmp(s1->loaded_dlls[i]->name, dllname)) | ||
| 1541 | return i + 1; | ||
| 1542 | tcc_add_dllref(s1, dllname); | ||
| 1543 | return s1->nb_loaded_dlls; | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | static int read_mem(int fd, unsigned offset, void *buffer, unsigned len) | 1536 | static int read_mem(int fd, unsigned offset, void *buffer, unsigned len) |
| 1547 | { | 1537 | { |
| 1548 | lseek(fd, offset, SEEK_SET); | 1538 | lseek(fd, offset, SEEK_SET); |
| @@ -1732,7 +1722,7 @@ static int pe_load_def(TCCState *s1, int fd) · 183 unmodified lines | |||
| 1732 | ++state; | 1722 | ++state; |
| 1733 | break; | 1723 | break; |
| 1734 | case 2: | 1724 | case 2: |
| 1735 | dllindex = pe_add_dllref(s1, dllname); | 1725 | dllindex = tcc_add_dllref(s1, dllname, 0)->index; |
| 1736 | ++state; | 1726 | ++state; |
| 1737 | /* fall through */ | 1727 | /* fall through */ |
| 1738 | default: | 1728 | default: |
| @@ -1769,7 +1759,7 @@ static int pe_load_dll(TCCState *s1, int fd, const char *filename) · 30 unmodified lines | |||
| 1769 | if (ret) { | 1759 | if (ret) { |
| 1770 | return -1; | 1760 | return -1; |
| 1771 | } else if (p) { | 1761 | } else if (p) { |
| 1772 | index = pe_add_dllref(s1, filename); | 1762 | index = tcc_add_dllref(s1, filename, 0)->index; |
| 1773 | for (q = p; *q; q += 1 + strlen(q)) | 1763 | for (q = p; *q; q += 1 + strlen(q)) |
| 1774 | pe_putimport(s1, index, q, 0); | 1764 | pe_putimport(s1, index, q, 0); |
| 1775 | tcc_free(p); | 1765 | tcc_free(p); |