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:
parent
7d31904247
commit
e8adc64203
5 changed files with 48 additions and 77 deletions
26
libtcc.c
26
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);
|
||||
|
|
3
tcc.h
3
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: */
|
||||
|
|
58
tccelf.c
58
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);
|
||||
|
|
24
tccmacho.c
24
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)
|
||||
|
|
14
tccpe.c
14
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);
|
||||
|
|
Loading…
Reference in a new issue