Add find_c_sym and friends

for handling leading underscores when looking up symbols.
Necessary on MacOS, as there C symbols have a '_' prepended.
get_sym_addr (replacing get_elf_sym_addr) gets an argument to
specify if bare/raw/ELF symbols should be looked up or if decorated
C symbols should be looked up.  That reflects into tcc_get_symbol.
tcc_add_symbol is _not_ yet changed, but probably should be.
This commit is contained in:
Michael Matz 2020-05-22 04:28:02 +02:00
parent cc11750bda
commit 71b0634168
4 changed files with 35 additions and 13 deletions

3
tcc.h
View file

@ -1535,7 +1535,8 @@ ST_FUNC void build_got_entries(TCCState *s1);
ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc);
ST_FUNC void squeeze_multi_relocs(Section *sec, size_t oldrelocoffset);
ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err);
ST_FUNC int find_c_sym(TCCState *, const char *name);
ST_FUNC addr_t get_sym_addr(TCCState *s, const char *name, int err, int forc);
ST_FUNC void list_elf_symbols(TCCState *s, void *ctx,
void (*symbol_cb)(void *ctx, const char *name, const void *val));
#if defined TCC_IS_NATIVE || defined TCC_TARGET_PE

View file

@ -481,13 +481,33 @@ ST_FUNC int find_elf_sym(Section *s, const char *name)
return 0;
}
/* return elf symbol value, signal error if 'err' is nonzero */
ST_FUNC addr_t get_elf_sym_addr(TCCState *s1, const char *name, int err)
ST_FUNC int find_c_sym(TCCState *s1, const char *name)
{
int ret;
CString cstr;
if (s1->leading_underscore) {
cstr_new(&cstr);
cstr_ccat(&cstr, '_');
cstr_cat(&cstr, name, 0);
name = cstr.data;
}
ret = find_elf_sym(s1->symtab, name);
if (s1->leading_underscore)
cstr_free(&cstr);
return ret;
}
/* return elf symbol value, signal error if 'err' is nonzero, decorate
name if FORC */
ST_FUNC addr_t get_sym_addr(TCCState *s1, const char *name, int err, int forc)
{
int sym_index;
ElfW(Sym) *sym;
sym_index = find_elf_sym(s1->symtab, name);
if (forc)
sym_index = find_c_sym(s1, name);
else
sym_index = find_elf_sym(s1->symtab, name);
sym = &((ElfW(Sym) *)s1->symtab->data)[sym_index];
if (!sym_index || sym->st_shndx == SHN_UNDEF) {
if (err)
@ -524,7 +544,7 @@ ST_FUNC void list_elf_symbols(TCCState *s, void *ctx,
/* return elf symbol value */
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
{
return (void*)(uintptr_t)get_elf_sym_addr(s, name, 0);
return (void*)(uintptr_t)get_sym_addr(s, name, 0, 1);
}
/* list elf symbol names and values */
@ -538,7 +558,7 @@ LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
/* return elf symbol value or error */
ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
{
return (void*)(uintptr_t)get_elf_sym_addr(s, name, 1);
return (void*)(uintptr_t)get_sym_addr(s, name, 1, 1);
}
#endif
@ -2177,7 +2197,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
default:
case TCC_OUTPUT_EXE:
ehdr.e_type = ET_EXEC;
ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
ehdr.e_entry = get_sym_addr(s1, "_start", 1, 0);
break;
case TCC_OUTPUT_DLL:
ehdr.e_type = ET_DYN;

View file

@ -818,7 +818,7 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
Section *s;
collect_sections(s1, &mo);
relocate_syms(s1, s1->symtab, 0);
mo.ep.entryoff = get_elf_sym_addr(s1, "_main", 1) - mo.seg[1]->vmaddr;
mo.ep.entryoff = get_sym_addr(s1, "_main", 1, 0) - mo.seg[1]->vmaddr;
if (s1->nb_errors)
goto do_ret;

View file

@ -126,8 +126,8 @@ ST_FUNC void tcc_run_free(TCCState *s1)
static void run_cdtors(TCCState *s1, const char *start, const char *end)
{
void **a = tcc_get_symbol(s1, start);
void **b = tcc_get_symbol(s1, end);
void **a = (void **)get_sym_addr(s1, start, 0, 0);
void **b = (void **)get_sym_addr(s1, end, 0, 0);
while (a != b)
((void(*)(void))*a++)();
}
@ -140,12 +140,12 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
rt_context *rc = &g_rtctxt;
#endif
s1->runtime_main = s1->nostdlib ? "_start" : s1->leading_underscore ? "_main" : "main";
if ((s1->dflag & 16) && !find_elf_sym(s1->symtab, s1->runtime_main))
s1->runtime_main = s1->nostdlib ? "_start" : "main";
if ((s1->dflag & 16) && !find_c_sym(s1, s1->runtime_main))
return 0;
#ifdef CONFIG_TCC_BACKTRACE
if (s1->do_debug)
tcc_add_symbol(s1, "exit", rt_exit);
tcc_add_symbol(s1, "_exit" + !s1->leading_underscore, rt_exit);
#endif
if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
return -1;
@ -182,6 +182,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
errno = 0; /* clean errno value */
fflush(stdout);
fflush(stderr);
/* These aren't C symbols, so don't need leading underscore handling. */
run_cdtors(s1, "__init_array_start", "__init_array_end");
#ifdef CONFIG_TCC_BACKTRACE
if (!rc->do_jmp || !(ret = setjmp(rc->jmp_buf)))