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;
|
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
3
tcc.h
|
@ -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: */
|
||||||
|
|
58
tccelf.c
58
tccelf.c
|
@ -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);
|
||||||
|
|
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);
|
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
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)
|
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue