如何获取dlopen函数实际加载的动态库完整文件路径?
获取dlopen加载库的实际完整路径
当你用dlopen("foo", RTLD_NOW)或RTLD_LAZY加载动态库后,想要获取实际加载的完整路径,可以用以下几种方法:
方法1:借助dladdr()函数
dladdr()可以通过符号地址反查所属库的信息。步骤如下:
- 先用
dlsym()从已获取的句柄中,拿到库内任意一个导出函数(或全局变量)的地址; - 调用
dladdr()传入该地址,从返回的Dl_info结构体中提取dli_fname字段,就是库的完整路径。
示例代码:
#include <dlfcn.h> #include <stdio.h> int main() { void* handle = dlopen("foo", RTLD_NOW); if (!handle) { fprintf(stderr, "%s\n", dlerror()); return 1; } // 替换为库中实际存在的导出函数名 void (*target_func)() = dlsym(handle, "foo_exported_func"); if (!target_func) { fprintf(stderr, "%s\n", dlerror()); dlclose(handle); return 1; } Dl_info info; if (dladdr(target_func, &info)) { printf("实际加载路径:%s\n", info.dli_fname); } else { fprintf(stderr, "无法获取路径:%s\n", dlerror()); } dlclose(handle); return 0; }
方法2:解析/proc/self/maps(Linux专属)
Linux系统中,/proc/self/maps文件记录了进程所有内存映射的详细信息,包括已加载动态库的路径。可以通过以下步骤提取:
- 先通过
dladdr()获取库的基地址; - 打开
/proc/self/maps逐行读取,找到包含基地址的内存区间行,该行末尾就是库的完整路径。
示例代码片段:
#include <stdio.h> #include <dlfcn.h> #include <stdlib.h> #include <string.h> void get_lib_path_from_proc_maps(void* handle) { Dl_info info; if (!dladdr(dlsym(handle, ""), &info)) { fprintf(stderr, "%s\n", dlerror()); return; } void* lib_base = info.dli_fbase; FILE* maps_file = fopen("/proc/self/maps", "r"); if (!maps_file) { perror("打开/proc/self/maps失败"); return; } char line_buf[1024]; while (fgets(line_buf, sizeof(line_buf), maps_file)) { void* map_start, *map_end; char lib_path[1024]; if (sscanf(line_buf, "%p-%p %*s %*s %*s %*s %s", &map_start, &map_end, lib_path) == 3) { if (lib_base >= map_start && lib_base < map_end) { printf("实际加载路径:%s\n", lib_path); break; } } } fclose(maps_file); }
方法3:使用dlinfo()函数(部分系统支持)
Linux、BSD等系统提供了dlinfo()函数,可直接通过dlopen句柄获取库路径。需要借助link_map结构体:
示例代码:
#include <dlfcn.h> #include <link.h> #include <stdio.h> int main() { void* handle = dlopen("foo", RTLD_NOW); if (!handle) { fprintf(stderr, "%s\n", dlerror()); return 1; } struct link_map* link_info; if (dlinfo(handle, RTLD_DI_LINKMAP, &link_info) == 0) { printf("实际加载路径:%s\n", link_info->l_name); } else { fprintf(stderr, "调用dlinfo失败:%s\n", dlerror()); } dlclose(handle); return 0; }
内容的提问来源于stack exchange,提问作者einpoklum
相关产品推荐
相关产品推荐

