From 944c4003bd8a0be89c96f23b1401cd74e074fec6 Mon Sep 17 00:00:00 2001 From: Jan Boon Date: Mon, 16 Sep 2019 15:24:16 +0800 Subject: [PATCH] Add function to list all symbols, for purpose of linking separate in-memory compilations --- libtcc.h | 4 ++++ tcc.h | 2 ++ tccelf.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/libtcc.h b/libtcc.h index a1b31e30..0c6bb3d6 100644 --- a/libtcc.h +++ b/libtcc.h @@ -93,6 +93,10 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr); /* return symbol value or NULL if not found */ LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name); +/* return symbol value or NULL if not found */ +LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, + void (*symbol_cb)(void *ctx, const char *name, const void *val)); + #ifdef __cplusplus } #endif diff --git a/tcc.h b/tcc.h index 7f01afac..c48b45bf 100644 --- a/tcc.h +++ b/tcc.h @@ -1470,6 +1470,8 @@ 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 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 ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name); #endif diff --git a/tccelf.c b/tccelf.c index 5b6737e7..707ce22d 100644 --- a/tccelf.c +++ b/tccelf.c @@ -471,12 +471,43 @@ ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err) return sym->st_value; } +/* list elf symbol names and values */ +ST_FUNC void list_elf_symbols(TCCState *s, void *ctx, + void (*symbol_cb)(void *ctx, const char *name, const void *val)) +{ + ElfW(Sym) *sym; + Section *symtab; + int sym_index, end_sym; + const char *name; + unsigned char sym_vis, sym_bind; + + symtab = s->symtab; + end_sym = symtab->data_offset / sizeof (ElfSym); + for (sym_index = 0; sym_index < end_sym; ++sym_index) { + sym = &((ElfW(Sym) *)symtab->data)[sym_index]; + if (sym->st_value) { + name = (char *) symtab->link->data + sym->st_name; + sym_bind = ELFW(ST_BIND)(sym->st_info); + sym_vis = ELFW(ST_VISIBILITY)(sym->st_other); + if (sym_bind == STB_GLOBAL && sym_vis == STV_DEFAULT) + symbol_cb(ctx, name, (void*)(uintptr_t)sym->st_value); + } + } +} + /* 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); } +/* list elf symbol names and values */ +LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, + void (*symbol_cb)(void *ctx, const char *name, const void *val)) +{ + list_elf_symbols(s, ctx, symbol_cb); +} + #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE /* return elf symbol value or error */ ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)