UPDATE | TL;DR :
I actually found shorter way:
auto library = dlopen("/path/to/lib.so", RTLD_LAZY | RTLD_GLOBAL); const char * libname = "lib.so"; struct link_map * map = nullptr; dlinfo(library, RTLD_DI_LINKMAP, &map); Elf64_Sym * symtab = nullptr; char * strtab = nullptr; int symentries = 0; for (auto section = map->l_ld; section->d_tag != DT_NULL; ++section) { if (section->d_tag == DT_SYMTAB) { symtab = (Elf64_Sym *)section->d_un.d_ptr; } if (section->d_tag == DT_STRTAB) { strtab = (char*)section->d_un.d_ptr; } if (section->d_tag == DT_SYMENT) { symentries = section->d_un.d_val; } } int size = strtab - (char *)symtab; for (int k = 0; k < size / symentries; ++k) { auto sym = &symtab[k]; // If sym is function if (ELF64_ST_TYPE(symtab[k].st_info) == STT_FUNC) { //str is name of each symbol auto str = &strtab[sym->st_name]; printf("%s\n", str); } }
OLD
I believe author does not need this anymore but maybe someone need actual code and here it is (based on previous answer)
First, we need a callback for dl_iterate_phdr():
static int callback(struct dl_phdr_info *info, size_t size, void *data) { // data is copy of 2nd arg in dl_iterate_phdr // you can use it for your lib name as I did const char * libname = (const char *)data; // if current elf's name contains your lib if (strstr(info->dlpi_name, libname)) { printf("loaded %s from: %s\n", libname, info->dlpi_name); for (int j = 0; j < info->dlpi_phnum; j++) { // we need to save dyanmic section since it contains symbolic table if (info->dlpi_phdr[j].p_type == PT_DYNAMIC) { Elf64_Sym * symtab = nullptr; char * strtab = nullptr; int symentries = 0; auto dyn = (Elf64_Dyn *)(info->dlpi_addr + info->dlpi_phdr[j].p_vaddr); for (int k = 0; k < info->dlpi_phdr[j].p_memsz / sizeof(Elf64_Dyn); ++k) { if (dyn[k].d_tag == DT_SYMTAB) { symtab = (Elf64_Sym *)dyn[k].d_un.d_ptr; } if (dyn[k].d_tag == DT_STRTAB) { strtab = (char*)dyn[k].d_un.d_ptr; } if (dyn[k].d_tag == DT_SYMENT) { symentries = dyn[k].d_un.d_val; } } int size = strtab - (char *)symtab; // for each string in table for (int k = 0; k < size / symentries; ++k) { auto sym = &symtab[k]; auto str = &strtab[sym->st_name]; printf("%s\n", str); } break; } } } return 0; }
Next, we call dl_iterate_phdr():
int main() { auto library = dlopen("/path/to/library.so", RTLD_LAZY | RTLD_GLOBAL); const char * libname = "library.so"; dl_iterate_phdr(callback, (void*)libname); return 0; }
If you need to store those names somewhere, you can pass a pointer to your container, restore it with cast and write there.
For my example library:
#include "simple_lib.h" #include <cstdio> void __attribute__ ((constructor)) initLibrary(void) { printf("Library is initialized\n"); } void __attribute__ ((destructor)) cleanUpLibrary(void) { printf("Library is exited\n"); } void make_number() { printf("1\n"); }
Prints this:
Library is initialized _ITM_deregisterTMCloneTable puts __gmon_start__ _ITM_registerTMCloneTable __cxa_finalize _Z11initLibraryv make_number _Z14cleanUpLibraryv Library is exited
man elffor the ELF API. There are various implementations such as fedorahosted.org/elfutils or sourceforge.net/p/elftoolchain/wiki/libelf