From e8adc64203acc1b95c5ee0879fb4b07af773d218 Mon Sep 17 00:00:00 2001 From: grischka Date: Sat, 28 May 2022 20:47:48 +0200 Subject: [PATCH] libtcc: extend tcc_add_dllref() 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(-) --- libtcc.c | 26 ++++++++++++++++++++---- tcc.h | 3 ++- tccelf.c | 58 ++++++++++++++++++------------------------------------ tccmacho.c | 24 +++------------------- tccpe.c | 14 ++----------- 5 files changed, 48 insertions(+), 77 deletions(-) diff --git a/libtcc.c b/libtcc.c index 59f846cd..f446cdf8 100644 --- a/libtcc.c +++ b/libtcc.c @@ -957,11 +957,29 @@ LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname) return 0; } -ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname) +/* add/update a 'DLLReference', Just find if level == -1 */ +ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level) { - DLLReference *ref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname)); + DLLReference *ref = NULL; + int i; + for (i = 0; i < s1->nb_loaded_dlls; i++) + if (0 == strcmp(s1->loaded_dlls[i]->name, dllname)) { + ref = s1->loaded_dlls[i]; + break; + } + if (level == -1) + return ref; + if (ref) { + if (level < ref->level) + ref->level = level; + ref->found = 1; + return ref; + } + ref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname)); strcpy(ref->name, dllname); dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, ref); + ref->level = level; + ref->index = s1->nb_loaded_dlls; return ref; } @@ -1042,7 +1060,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) soname = macho_tbd_soname(filename); dl = dlopen(soname, RTLD_GLOBAL | RTLD_LAZY); if (dl) - tcc_add_dllref(s1, soname)->handle = dl, ret = 0; + tcc_add_dllref(s1, soname, 0)->handle = dl, ret = 0; if (filename != soname) tcc_free((void *)soname); #endif @@ -1070,7 +1088,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) #ifdef TCC_IS_NATIVE void* dl = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); if (dl) - tcc_add_dllref(s1, filename)->handle = dl, ret = 0; + tcc_add_dllref(s1, filename, 0)->handle = dl, ret = 0; #endif } else ret = tcc_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0); diff --git a/tcc.h b/tcc.h index d4708bbd..67218089 100644 --- a/tcc.h +++ b/tcc.h @@ -609,6 +609,7 @@ typedef struct Section { typedef struct DLLReference { int level; void *handle; + unsigned char found, index; char name[1]; } DLLReference; @@ -1279,7 +1280,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind); #ifdef _WIN32 ST_FUNC char *normalize_slashes(char *path); #endif -ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname); +ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level); ST_FUNC char *tcc_load_text(int fd); /* tcc_parse_args return codes: */ diff --git a/tccelf.c b/tccelf.c index 078e98d7..a72d0466 100644 --- a/tccelf.c +++ b/tccelf.c @@ -547,7 +547,7 @@ LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, static void version_add (TCCState *s1) { - int i, j; + int i; ElfW(Sym) *sym; ElfW(Verneed) *vn = NULL; Section *symtab; @@ -594,14 +594,8 @@ version_add (TCCState *s1) ElfW(Vernaux) *vna = 0; if (sv->out_index < 1) continue; - /* If present in verneed it should be in DT_NEEDED */ - for (j = 0; j < s1->nb_loaded_dlls; j++) { - DLLReference *dllref = s1->loaded_dlls[j]; - if (!strcmp(sv->lib, dllref->name)) { - dllref->level = 0; - break; - } - } + /* make sure that a DT_NEEDED tag is put */ + tcc_add_dllref(s1, sv->lib, 0); vnofs = section_add(verneed_section, sizeof(*vn), 1); vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); vn->vn_version = 1; @@ -3425,14 +3419,13 @@ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) { ElfW(Ehdr) ehdr; ElfW(Shdr) *shdr, *sh, *sh1; - int i, j, nb_syms, nb_dts, sym_bind, ret; + int i, nb_syms, nb_dts, sym_bind, ret = -1; ElfW(Sym) *sym, *dynsym; ElfW(Dyn) *dt, *dynamic; char *dynstr; int sym_index; const char *name, *soname; - DLLReference *dllref; struct versym_info v; 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) } } + if (!dynamic) + goto the_end; + /* compute the real library name */ soname = tcc_basename(filename); - - for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { - if (dt->d_tag == DT_SONAME) { + for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) + if (dt->d_tag == DT_SONAME) soname = dynstr + dt->d_un.d_val; - } else if (dt->d_tag == DT_RPATH) { - tcc_add_library_path(s1, dynstr + dt->d_un.d_val); - } - } /* if the dll is already loaded, do not load it */ - for(i = 0; i < s1->nb_loaded_dlls; i++) { - dllref = s1->loaded_dlls[i]; - if (!strcmp(soname, dllref->name)) { - /* but update level if needed */ - if (level < dllref->level) - dllref->level = level; - ret = 0; - goto the_end; - } - } + if (tcc_add_dllref(s1, soname, level)->found) + goto ret_success; if (v.nb_versyms != nb_syms) tcc_free (v.versym), v.versym = NULL; else store_version(s1, &v, dynstr); - /* add the dll and its level */ - tcc_add_dllref(s1, soname)->level = level; - /* add dynamic symbols in dynsym_section */ for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) { 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) } } + for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) + if (dt->d_tag == DT_RPATH) + tcc_add_library_path(s1, dynstr + dt->d_un.d_val); + /* load all referenced DLLs */ for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { switch(dt->d_tag) { case DT_NEEDED: name = dynstr + dt->d_un.d_val; - for(j = 0; j < s1->nb_loaded_dlls; j++) { - dllref = s1->loaded_dlls[j]; - if (!strcmp(name, dllref->name)) - goto already_loaded; - } + if (tcc_add_dllref(s1, name, -1)) + continue; if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) { tcc_error_noabort("referenced dll '%s' not found", name); - ret = -1; goto the_end; } - already_loaded: - break; } } + + ret_success: ret = 0; the_end: tcc_free(dynstr); diff --git a/tccmacho.c b/tccmacho.c index 8e86b75f..f9048ea3 100644 --- a/tccmacho.c +++ b/tccmacho.c @@ -835,25 +835,6 @@ static uint32_t macho_swap32(uint32_t x) return (x >> 24) | (x << 24) | ((x >> 8) & 0xff00) | ((x & 0xff00) << 8); } #define SWAP(x) (swap ? macho_swap32(x) : (x)) - -ST_FUNC int macho_add_dllref(TCCState* s1, int lev, const char* soname) -{ - /* if the dll is already loaded, do not load it */ - DLLReference *dllref; - int i; - for(i = 0; i < s1->nb_loaded_dlls; i++) { - dllref = s1->loaded_dlls[i]; - if (!strcmp(soname, dllref->name)) { - /* but update level if needed */ - if (lev < dllref->level) - dllref->level = lev; - return -1; - } - } - tcc_add_dllref(s1, soname)->level = lev; - return 0; -} - #define tbd_parse_movepast(s) \ (pos = (pos = strstr(pos, s)) ? pos + strlen(s) : NULL) #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) if (!tbd_parse_movetoany("\n \"'")) goto the_end; tbd_parse_trample; ret = 0; - if (macho_add_dllref(s1, lev, soname) != 0) goto the_end; + if (tcc_add_dllref(s1, soname, lev)->found) + goto the_end; while(pos) { char* sym = NULL; int cont = 1; @@ -1047,7 +1029,7 @@ ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev) lc = (struct load_command*) ((char*)lc + lc->cmdsize); } - if (0 != macho_add_dllref(s1, lev, soname)) + if (tcc_add_dllref(s1, soname, lev)->found) goto the_end; if (!nsyms || !nextdef) diff --git a/tccpe.c b/tccpe.c index 07501a96..f70c8b99 100644 --- a/tccpe.c +++ b/tccpe.c @@ -1533,16 +1533,6 @@ ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t va ); } -static int pe_add_dllref(TCCState *s1, const char *dllname) -{ - int i; - for (i = 0; i < s1->nb_loaded_dlls; ++i) - if (0 == strcmp(s1->loaded_dlls[i]->name, dllname)) - return i + 1; - tcc_add_dllref(s1, dllname); - return s1->nb_loaded_dlls; -} - static int read_mem(int fd, unsigned offset, void *buffer, unsigned len) { lseek(fd, offset, SEEK_SET); @@ -1732,7 +1722,7 @@ static int pe_load_def(TCCState *s1, int fd) ++state; break; case 2: - dllindex = pe_add_dllref(s1, dllname); + dllindex = tcc_add_dllref(s1, dllname, 0)->index; ++state; /* fall through */ default: @@ -1769,7 +1759,7 @@ static int pe_load_dll(TCCState *s1, int fd, const char *filename) if (ret) { return -1; } else if (p) { - index = pe_add_dllref(s1, filename); + index = tcc_add_dllref(s1, filename, 0)->index; for (q = p; *q; q += 1 + strlen(q)) pe_putimport(s1, index, q, 0); tcc_free(p);