dlinfo函数用法详解
dlinfo函数简介
- 头文件包含
#include <link.h>
#include <dlfcn.h>
- 函数定义
#define _GNU_SOURCE
- 编译链接选项
-ldl
dlinfo函数常见使用错误
- 链接错误
undefined reference to `dlinfo'
解决办法:添加链接选项
-ldl
- 编译错误
warning: implicit declaration of function ‘dlinfo’ [-Wimplicit-function-declaration]
解决办法:包含头文件
#include <link.h>
#include <dlfcn.h>
dlinfo函数详细描述
dlinfo ()函数获得有关handle所引用的动态加载对象的信息(通常通过先前对dlopen (3)或dlmopen (3))的调用获得),request参数指定要返回的信息。info参数是指向用于存储调用返回的信息的缓冲区的指针;该参数的类型取决于request
request支持以下值(括号中显示了info的相应类型):
- RTLD_DI_LMID " (\fILmid_t *\fP)"获取加载handle的链接映射列表(命名空间)的ID。
- RTLD_DI_LINKMAP " (\fIstruct link_map **\fP)"获得一个指向与handle 对应的link_map结构的指针。info参数指向一个指向link_map结构的指针,该结构在
中定义为:.ip
struct link_map {
ElfW(Addr) l_addr; /* Difference between the
address in the ELF file and
the address in memory */
char *l_name; /* Absolute pathname where
object was found */
ElfW(Dyn) *l_ld; /* Dynamic section of the
shared object */
struct link_map *l_next, *l_prev;
/* Chain of loaded objects */
/* Plus additional fields private to the
implementation */
};
- RTLD_DI_ORIGIN " (\fIchar *\fP)"将与handle对应的共享对象源的路径名复制到info 指向的位置
- RTLD_DI_SERINFO " (\fIDl_serinfo *\fP)"获取由handle 引用的共享对象的库搜索路径。info参数是指向包含搜索路径的Dl_serinfo的指针。因为搜索路径的数量可能不同,所以info所指向的结构的大小也可能不同。下面描述的 RTLD_DI_SERINFOSIZE 请求允许应用程序适当地调整缓冲区的大小。调用方必须执行以下步骤:.rs
- 使用 RTLD_DI_SERINFOSIZE 请求用后续 RTLD_DI_SERINFO 请求所需结构的size.ri(dls_size)填充Dl_serinfo结构。
- 分配一个大小正确的Dl_serinfo缓冲区。ri(dls_size)。
- 使用另一个 RTLD_DI_SERINFOSIZE 请求填充上一步中分配的缓冲区的dls_size和dls_cnt字段。
- 使用 RTLD_DI_SERINFO 获取库搜索路径。Dl_serinfo结构定义如下:.ip
typedef struct {
size_t dls_size; /* Size in bytes of
the whole buffer */
unsigned int dls_cnt; /* Number of elements
in \(aqdls_serpath\(aq */
Dl_serpath dls_serpath[1]; /* Actually longer,
\(aqdls_cnt\(aq elements */
} Dl_serinfo;
.ip上述结构中的每个dls_serpath元素都是以下形式的结构:.ip
typedef struct {
char *dls_name; /* Name of library search
path directory */
unsigned int dls_flags; /* Indicates where this
directory came from */
} Dl_serpath;
.ip dls_flags字段当前未使用,并且始终包含零。
- RTLD_DI_SERINFOSIZE " (\fIDl_serinfo *\fP)"用适合分配缓冲区的值填充由info指向的Dl_serinfo结构的dls_size和dls_cnt字段,以便在随后的 RTLD_DI_SERINFO 请求中使用。
- RTLD_DI_TLS_MODID " (\fIsize_t \fP since glibc 24)"获取此共享对象的TLS(线程本地存储)段的模块ID,如在TLS重定位中所使用的那样。如果此对象未定义TLS段,则在info 中放置零
- RTLD_DI_TLS_DATA " (\fIvoid **\fP since glibc 24)"获得一个指针,指向调用线程的TLS块,该块对应于该共享对象的TLS段。如果这个对象没有定义PT_TLS段,或者调用线程没有为它分配块,则NULL将放在*info 中
dlinfo函数返回值
成功后,dlinfo ()返回0。失败时,返回-1;使用dlerror (3)可以诊断错误的原因
dlinfo函数其他说明
此函数派生自同名的Solaris函数,也出现在其他一些系统上。各种实现所支持的请求集仅部分重叠。
dlinfo函数使用举例
下面的程序使用dlopen (3)打开一个共享对象,然后使用 RTLD_DI_SERINFOSIZE 和 RTLD_DI_SERINFO 请求获得库的库搜索路径列表。下面是运行程序时我们可能会看到的一个示例:
$ \fB./a.out /lib64/libm.so.6\fP
dls_serpath[0].dls_name = /lib64
dls_serpath[1].dls_name = /usr/lib64
Program source&
#define _GNU_SOURCE
#include <dlfcn.h>
#include <link.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
void *handle;
Dl_serinfo serinfo;
Dl_serinfo *sip;
if (argc != 2) {
fprintf(stderr, "Usage: %s <libpath>\en", argv[0]);
exit(EXIT_FAILURE);
}
/* Obtain a handle for shared object specified on command line */
handle = dlopen(argv[1], RTLD_NOW);
if (handle == NULL) {
fprintf(stderr, "dlopen() failed: %s\en", dlerror());
exit(EXIT_FAILURE);
}
/* Discover the size of the buffer that we must pass to
RTLD_DI_SERINFO */
if (dlinfo(handle, RTLD_DI_SERINFOSIZE, &serinfo) == \-1) {
fprintf(stderr, "RTLD_DI_SERINFOSIZE failed: %s\en", dlerror());
exit(EXIT_FAILURE);
}
/* Allocate the buffer for use with RTLD_DI_SERINFO */
sip = malloc(serinfo.dls_size);
if (sip == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
/* Initialize the \(aqdls_size\(aq and \(aqdls_cnt\(aq fields in the newly
allocated buffer */
if (dlinfo(handle, RTLD_DI_SERINFOSIZE, sip) == \-1) {
fprintf(stderr, "RTLD_DI_SERINFOSIZE failed: %s\en", dlerror());
exit(EXIT_FAILURE);
}
/* Fetch and print library search list */
if (dlinfo(handle, RTLD_DI_SERINFO, sip) == \-1) {
fprintf(stderr, "RTLD_DI_SERINFO failed: %s\en", dlerror());
exit(EXIT_FAILURE);
}
for (int j = 0; j < serinfo.dls_cnt; j++)
printf("dls_serpath[%d].dls_name = %s\en",
j, sip\->dls_serpath[j].dls_name);
exit(EXIT_SUCCESS);
}
评论区