Add tcc_set_linker_resolve_func()

Useful for resolving symbols dynamically.
This commit is contained in:
Ole André Vadla Ravnås 2019-09-12 22:38:48 +02:00
parent 949e096b02
commit 7e6ed199c2
5 changed files with 47 additions and 4 deletions

View File

@ -617,6 +617,13 @@ LIBTCCAPI void tcc_set_cpp_load_func(TCCState *s, void *cpp_load_opaque,
s->cpp_load_func = cpp_load_func;
}
LIBTCCAPI void tcc_set_linker_resolve_func(TCCState *s, void *resolve_opaque,
void *(*resolve_func)(void *opaque, const char *name))
{
s->linker_resolve_opaque = resolve_opaque;
s->linker_resolve_func = resolve_func;
}
/* error without aborting current compilation */
PUB_FUNC void _tcc_error_noabort(const char *fmt, ...)
{

View File

@ -37,6 +37,10 @@ LIBTCCAPI void *tcc_get_error_opaque(TCCState *s);
LIBTCCAPI void tcc_set_cpp_load_func(TCCState *s, void *cpp_load_opaque,
const char *(*cpp_load_func)(void *opaque, const char *path, int *len));
/* set linker resolver callback */
LIBTCCAPI void tcc_set_linker_resolve_func(TCCState *s, void *resolve_opaque,
void *(*resolve_func)(void *opaque, const char *name));
/* set options as from command line (multiple supported) */
LIBTCCAPI void tcc_set_options(TCCState *s, const char *str);

4
tcc.h
View File

@ -805,6 +805,10 @@ struct TCCState {
void *cpp_load_opaque;
const char *(*cpp_load_func)(void *opaque, const char *path, int *len);
/* linker symbol handling */
void *linker_resolve_opaque;
void *(*linker_resolve_func)(void *opaque, const char *name);
/* output file for preprocessing (-E) */
FILE *ppfp;
enum {

View File

@ -898,20 +898,34 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
ElfW(Sym) *sym;
int sym_bind, sh_num;
const char *name;
void *addr;
for_each_elem(symtab, 1, sym, ElfW(Sym)) {
sh_num = sym->st_shndx;
if (sh_num == SHN_UNDEF) {
name = (char *) s1->symtab->link->data + sym->st_name;
if (s1->linker_resolve_func) {
addr = s1->linker_resolve_func(s1->linker_resolve_opaque, name);
if (addr) {
sym->st_value = (addr_t) addr;
#ifdef DEBUG_RELOC
printf ("relocate_sym: %s -> 0x%lx\n", name,
sym->st_value);
#endif
goto found;
}
}
/* Use ld.so to resolve symbol for us (for tcc -run) */
if (do_resolve) {
#if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE
#ifdef TCC_TARGET_MACHO
/* The symbols in the symtables have a prepended '_'
but dlsym() needs the undecorated name. */
void *addr = dlsym(RTLD_DEFAULT, name + 1);
addr = dlsym(RTLD_DEFAULT, name + 1);
#else
void *addr = dlsym(RTLD_DEFAULT, name);
addr = dlsym(RTLD_DEFAULT, name);
#endif
if (addr) {
sym->st_value = (addr_t) addr;

18
tccpe.c
View File

@ -1248,8 +1248,22 @@ static int pe_check_symbols(struct pe_info *pe)
int imp_sym = pe_find_import(pe->s1, sym);
struct import_symbol *is;
if (imp_sym <= 0)
goto not_found;
if (imp_sym <= 0) {
TCCState *s1 = pe->s1;
if (s1->linker_resolve_func) {
void *addr = s1->linker_resolve_func(
s1->linker_resolve_opaque,
name);
if (addr) {
tcc_add_symbol(s1, name, addr);
imp_sym = pe_find_import(s1, sym);
}
}
if (imp_sym <= 0)
goto not_found;
}
if (type == STT_NOTYPE) {
/* symbols from assembler have no type, find out which */