在运行时,我需要打印出一个地址,并找出该地址所在的函数。这些函数位于共享库中,因此不在固定地址上。我的映射文件只显示每个共享库函数的相对偏移量。在运行时是否可以查询加载了哪个库,以便我可以从我的地址中减去该值,以获得正确的映射文件偏移量?
目前,我正在使用一种略微不规范的方法,即同时打印出库中一个函数的地址,然后在映射文件中找到该函数,以确定加载地址必须在哪里。我宁愿有一种通用的方法,不需要您命名引用函数。
(在我的设置中没有GDB可用)。 谢谢。
在运行时,我需要打印出一个地址,并找出该地址所在的函数。这些函数位于共享库中,因此不在固定地址上。我的映射文件只显示每个共享库函数的相对偏移量。在运行时是否可以查询加载了哪个库,以便我可以从我的地址中减去该值,以获得正确的映射文件偏移量?
目前,我正在使用一种略微不规范的方法,即同时打印出库中一个函数的地址,然后在映射文件中找到该函数,以确定加载地址必须在哪里。我宁愿有一种通用的方法,不需要您命名引用函数。
(在我的设置中没有GDB可用)。 谢谢。
dl_iterate_phdr
函数来查找共享库的地址。dladdr是这样做的,完了。:-)
更全面地说,dladdr会获取一个地址并确定它对应的库和符号...然后它会给你每个库的名称、每个符号的名称以及它们的基址。我个人认为这很棒,也让我的当前调试工作变得更容易。
希望这能帮到你!
请查看/proc/[PID]/maps文件。其中包含了进程内存地址空间中库映射的地址。
如果您想访问可执行部分,请在库上使用readelf,并查找.text部分的偏移量。
请查看System V ABI第5章,对于懒惰的人,以下是支持ELF二进制格式系统的标准方法:
#include <link.h>
off_t load_offset;
for (Elf64_Dyn *dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn) {
if (dyn->d_tag == DT_DEBUG) {
struct r_debug *r_debug = (struct r_debug *) dyn->d_un.d_ptr;
struct link_map *link_map = r_debug->r_map;
while (link_map) {
if (strcmp(link_map->l_name, libname) == 0) {
load_offset = (off_t)link_map->l_addr;
break;
}
link_map = link_map->l_next;
}
break;
}
}
这不依赖于任何GNU扩展。
在GNU系统上,宏ElfW(Dyn)将返回方便的Elf64_Dyn或Elf32_Dyn。