假设main.c
使用来自main.c
声明的共享库和本地函数的符号。
是否有一种漂亮而优雅的方式在运行时打印所有可用function名称和符号的列表?
应该可以,因为数据被加载到.code
段。
由于我有同样的需要在运行时检索所有加载的符号名称,我根据R ..的答案做了一些研究。 所以这里是一个详细的解决方案,用于ELF格式的linux共享库,它与我的gcc 4.3.4一起使用,但希望也可以使用更新的版本。
我主要使用以下来源来开发此解决方案:
这是我的代码。 我使用自我解释变量名称并添加详细注释以使其可理解。 如果出现问题或遗漏,请告诉我……(编辑:我刚刚意识到问题是针对C而我的代码是针对C ++的。但是如果你省略了向量和字符串它也应该适用于C )
#include #include #include using namespace std; /* Callback for dl_iterate_phdr. * Is called by dl_iterate_phdr for every loaded shared lib until something * else than 0 is returned by one call of this function. */ int retrieve_symbolnames(struct dl_phdr_info* info, size_t info_size, void* symbol_names_vector) { /* ElfW is a macro that creates proper typenames for the used system architecture * (eg on a 32 bit system, ElfW(Dyn*) becomes "Elf32_Dyn*") */ ElfW(Dyn*) dyn; ElfW(Sym*) sym; ElfW(Word*) hash; char* strtab = 0; char* sym_name = 0; ElfW(Word) sym_cnt = 0; /* the void pointer (3rd argument) should be a pointer to a vector * in this example -> cast it to make it usable */ vector * symbol_names = reinterpret_cast*>(symbol_names_vector); /* Iterate over all headers of the current shared lib * (first call is for the executable itself) */ for (size_t header_index = 0; header_index < info->dlpi_phnum; header_index++) { /* Further processing is only needed if the dynamic section is reached */ if (info->dlpi_phdr[header_index].p_type == PT_DYNAMIC) { /* Get a pointer to the first entry of the dynamic section. * It's address is the shared lib's address + the virtual address */ dyn = (ElfW(Dyn)*)(info->dlpi_addr + info->dlpi_phdr[header_index].p_vaddr); /* Iterate over all entries of the dynamic section until the * end of the symbol table is reached. This is indicated by * an entry with d_tag == DT_NULL. * * Only the following entries need to be processed to find the * symbol names: * - DT_HASH -> second word of the hash is the number of symbols * - DT_STRTAB -> pointer to the beginning of a string table that * contains the symbol names * - DT_SYMTAB -> pointer to the beginning of the symbols table */ while(dyn->d_tag != DT_NULL) { if (dyn->d_tag == DT_HASH) { /* Get a pointer to the hash */ hash = (ElfW(Word*))dyn->d_un.d_ptr; /* The 2nd word is the number of symbols */ sym_cnt = hash[1]; } else if (dyn->d_tag == DT_STRTAB) { /* Get the pointer to the string table */ strtab = (char*)dyn->d_un.d_ptr; } else if (dyn->d_tag == DT_SYMTAB) { /* Get the pointer to the first entry of the symbol table */ sym = (ElfW(Sym*))dyn->d_un.d_ptr; /* Iterate over the symbol table */ for (ElfW(Word) sym_index = 0; sym_index < sym_cnt; sym_index++) { /* get the name of the i-th symbol. * This is located at the address of st_name * relative to the beginning of the string table. */ sym_name = &strtab[sym[sym_index].st_name]; symbol_names->push_back(string(sym_name)); } } /* move pointer to the next entry */ dyn++; } } } /* Returning something != 0 stops further iterations, * since only the first entry, which is the executable itself, is needed * 1 is returned after processing the first entry. * * If the symbols of all loaded dynamic libs shall be found, * the return value has to be changed to 0. */ return 1; } int main() { vector symbolNames; dl_iterate_phdr(retrieve_symbolnames, &symbolNames); return 0; }
在基于动态链接的ELF的系统上,您可以使用dl_iterate_phdr
函数。 如果是这样,它可用于收集每个加载的共享库文件的信息,并且您获得的信息足以检查符号表。 这个过程基本上是:
您需要的类型都应该在
和
。
这不是特定于C的,但操作系统和二进制格式以及(用于调试符号和未编码的C ++符号名称)甚至是编译器特定的问题。 没有通用的方式,也没有真正优雅的方式。
最便携和面向未来的方式可能是运行外部程序,例如nm
,它位于POSIX中。 在Linux中发现的GNU版本可能有一堆扩展,如果你的目标是可移植性和面向未来,你应该避免使用它们。
它的输出应保持稳定,即使二进制格式发生变化,它也会得到更新并继续工作。 只需使用正确的开关运行它,捕获其输出(可能通过popen
运行以避免临时文件)并解析它。
它应该是dl_iterate_phdr(retrieve_symbolnames, &symbolNames);
以上就是c/c++开发分享在Linux体系结构中使用C代码动态列出所有函数/符号?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/518957.html