From 71b0634168099422ff522cbcc9da5b5b111d7329 Mon Sep 17 00:00:00 2001 From: Michael Matz <matz@suse.de> Date: Fri, 22 May 2020 04:28:02 +0200 Subject: [PATCH] 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. --- tcc.h | 3 ++- tccelf.c | 32 ++++++++++++++++++++++++++------ tccmacho.c | 2 +- tccrun.c | 11 ++++++----- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/tcc.h b/tcc.h index 4bb90132..c00c7a15 100644 --- a/tcc.h +++ b/tcc.h @@ -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 diff --git a/tccelf.c b/tccelf.c index 99effb6b..b7eeda6b 100644 --- a/tccelf.c +++ b/tccelf.c @@ -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; diff --git a/tccmacho.c b/tccmacho.c index 08b0f625..4507b762 100644 --- a/tccmacho.c +++ b/tccmacho.c @@ -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; diff --git a/tccrun.c b/tccrun.c index 92b0e647..944cd5a3 100644 --- a/tccrun.c +++ b/tccrun.c @@ -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)))