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;
}
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);

3
tcc.h
View file

@ -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: */

View file

@ -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);

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);
}
#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)

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)
{
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);