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 4c82b00342

48 insertions(+), 77 deletions(-)
This commit is contained in:
grischka 2022-05-28 20:47:48 +02:00
parent 7d31904247
commit e8adc64203
5 changed files with 48 additions and 77 deletions

View file

@ -957,11 +957,29 @@ LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
return 0; 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); strcpy(ref->name, dllname);
dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, ref); dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, ref);
ref->level = level;
ref->index = s1->nb_loaded_dlls;
return ref; 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); soname = macho_tbd_soname(filename);
dl = dlopen(soname, RTLD_GLOBAL | RTLD_LAZY); dl = dlopen(soname, RTLD_GLOBAL | RTLD_LAZY);
if (dl) if (dl)
tcc_add_dllref(s1, soname)->handle = dl, ret = 0; tcc_add_dllref(s1, soname, 0)->handle = dl, ret = 0;
if (filename != soname) if (filename != soname)
tcc_free((void *)soname); tcc_free((void *)soname);
#endif #endif
@ -1070,7 +1088,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
#ifdef TCC_IS_NATIVE #ifdef TCC_IS_NATIVE
void* dl = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); void* dl = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
if (dl) if (dl)
tcc_add_dllref(s1, filename)->handle = dl, ret = 0; tcc_add_dllref(s1, filename, 0)->handle = dl, ret = 0;
#endif #endif
} else } else
ret = tcc_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0); ret = tcc_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);

3
tcc.h
View file

@ -609,6 +609,7 @@ typedef struct Section {
typedef struct DLLReference { typedef struct DLLReference {
int level; int level;
void *handle; void *handle;
unsigned char found, index;
char name[1]; char name[1];
} DLLReference; } DLLReference;
@ -1279,7 +1280,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
#ifdef _WIN32 #ifdef _WIN32
ST_FUNC char *normalize_slashes(char *path); ST_FUNC char *normalize_slashes(char *path);
#endif #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); ST_FUNC char *tcc_load_text(int fd);
/* tcc_parse_args return codes: */ /* tcc_parse_args return codes: */

View file

@ -547,7 +547,7 @@ LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
static void static void
version_add (TCCState *s1) version_add (TCCState *s1)
{ {
int i, j; int i;
ElfW(Sym) *sym; ElfW(Sym) *sym;
ElfW(Verneed) *vn = NULL; ElfW(Verneed) *vn = NULL;
Section *symtab; Section *symtab;
@ -594,14 +594,8 @@ version_add (TCCState *s1)
ElfW(Vernaux) *vna = 0; ElfW(Vernaux) *vna = 0;
if (sv->out_index < 1) if (sv->out_index < 1)
continue; continue;
/* If present in verneed it should be in DT_NEEDED */ /* make sure that a DT_NEEDED tag is put */
for (j = 0; j < s1->nb_loaded_dlls; j++) { tcc_add_dllref(s1, sv->lib, 0);
DLLReference *dllref = s1->loaded_dlls[j];
if (!strcmp(sv->lib, dllref->name)) {
dllref->level = 0;
break;
}
}
vnofs = section_add(verneed_section, sizeof(*vn), 1); vnofs = section_add(verneed_section, sizeof(*vn), 1);
vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); vn = (ElfW(Verneed)*)(verneed_section->data + vnofs);
vn->vn_version = 1; 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(Ehdr) ehdr;
ElfW(Shdr) *shdr, *sh, *sh1; 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(Sym) *sym, *dynsym;
ElfW(Dyn) *dt, *dynamic; ElfW(Dyn) *dt, *dynamic;
char *dynstr; char *dynstr;
int sym_index; int sym_index;
const char *name, *soname; const char *name, *soname;
DLLReference *dllref;
struct versym_info v; struct versym_info v;
full_read(fd, &ehdr, sizeof(ehdr)); 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 */ /* compute the real library name */
soname = tcc_basename(filename); soname = tcc_basename(filename);
for(i = 0, dt = dynamic; i < nb_dts; i++, dt++)
for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { if (dt->d_tag == DT_SONAME)
if (dt->d_tag == DT_SONAME) {
soname = dynstr + dt->d_un.d_val; 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 */ /* if the dll is already loaded, do not load it */
for(i = 0; i < s1->nb_loaded_dlls; i++) { if (tcc_add_dllref(s1, soname, level)->found)
dllref = s1->loaded_dlls[i]; goto ret_success;
if (!strcmp(soname, dllref->name)) {
/* but update level if needed */
if (level < dllref->level)
dllref->level = level;
ret = 0;
goto the_end;
}
}
if (v.nb_versyms != nb_syms) if (v.nb_versyms != nb_syms)
tcc_free (v.versym), v.versym = NULL; tcc_free (v.versym), v.versym = NULL;
else else
store_version(s1, &v, dynstr); store_version(s1, &v, dynstr);
/* add the dll and its level */
tcc_add_dllref(s1, soname)->level = level;
/* add dynamic symbols in dynsym_section */ /* add dynamic symbols in dynsym_section */
for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) { for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
sym_bind = ELFW(ST_BIND)(sym->st_info); 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 */ /* load all referenced DLLs */
for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
switch(dt->d_tag) { switch(dt->d_tag) {
case DT_NEEDED: case DT_NEEDED:
name = dynstr + dt->d_un.d_val; name = dynstr + dt->d_un.d_val;
for(j = 0; j < s1->nb_loaded_dlls; j++) { if (tcc_add_dllref(s1, name, -1))
dllref = s1->loaded_dlls[j]; continue;
if (!strcmp(name, dllref->name))
goto already_loaded;
}
if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) { if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
tcc_error_noabort("referenced dll '%s' not found", name); tcc_error_noabort("referenced dll '%s' not found", name);
ret = -1;
goto the_end; goto the_end;
} }
already_loaded:
break;
} }
} }
ret_success:
ret = 0; ret = 0;
the_end: the_end:
tcc_free(dynstr); tcc_free(dynstr);

View file

@ -835,25 +835,6 @@ static uint32_t macho_swap32(uint32_t x)
return (x >> 24) | (x << 24) | ((x >> 8) & 0xff00) | ((x & 0xff00) << 8); return (x >> 24) | (x << 24) | ((x >> 8) & 0xff00) | ((x & 0xff00) << 8);
} }
#define SWAP(x) (swap ? macho_swap32(x) : (x)) #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) \ #define tbd_parse_movepast(s) \
(pos = (pos = strstr(pos, s)) ? pos + strlen(s) : NULL) (pos = (pos = strstr(pos, s)) ? pos + strlen(s) : NULL)
#define tbd_parse_movetoany(cs) (pos = strpbrk(pos, cs)) #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; if (!tbd_parse_movetoany("\n \"'")) goto the_end;
tbd_parse_trample; tbd_parse_trample;
ret = 0; 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) { while(pos) {
char* sym = NULL; char* sym = NULL;
int cont = 1; 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); 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; goto the_end;
if (!nsyms || !nextdef) if (!nsyms || !nextdef)

14
tccpe.c
View file

@ -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) static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
{ {
lseek(fd, offset, SEEK_SET); lseek(fd, offset, SEEK_SET);
@ -1732,7 +1722,7 @@ static int pe_load_def(TCCState *s1, int fd)
++state; ++state;
break; break;
case 2: case 2:
dllindex = pe_add_dllref(s1, dllname); dllindex = tcc_add_dllref(s1, dllname, 0)->index;
++state; ++state;
/* fall through */ /* fall through */
default: default:
@ -1769,7 +1759,7 @@ static int pe_load_dll(TCCState *s1, int fd, const char *filename)
if (ret) { if (ret) {
return -1; return -1;
} else if (p) { } 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)) for (q = p; *q; q += 1 + strlen(q))
pe_putimport(s1, index, q, 0); pe_putimport(s1, index, q, 0);
tcc_free(p); tcc_free(p);