DLINFO - Linux手册页

时间:2019-08-20 18:00:08  来源:igfitidea点击:

Linux程序员手册 第3部分
更新日期: 2020-06-09

名称

dlinfo-获取有关动态加载对象的信息

语法

#define _GNU_SOURCE
#include <link.h>
#include <dlfcn.h>

int dlinfo(void *handle, int request, void *info);

Link with -ldl.

说明

dlinfo()函数获取有关句柄引用的动态加载对象的信息(通常是通过对dlopen(3)或dlmopen(3)的较早调用获得的)。 request参数指定要返回的信息。 info参数是一个指向缓冲区的指针,该缓冲区用于存储调用返回的信息。此参数的类型取决于请求。

支持以下值进行请求(括号中显示信息的相应类型):

RTLD_DI_LMID(Lmid_t *)
获取在其中加载了句柄的链接映射列表(名称空间)的ID。
RTLD_DI_LINKMAP(struct link_map **)
获取指向对应于句柄的link_map结构的指针。 info参数指向一个指向link_map结构的指针,该结构定义为:
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(char *)
将对应于句柄的共享库的原点的路径名复制到info指向的位置。
RTLD_DI_SERINFO(Dl_serinfo *)
Obtain the library search paths for the shared object referred to by handle.

The
info

argument is a pointer to a
Dl_serinfo

that contains the search paths.
Because the number of search paths may vary,
the size of the structure pointed to by
info

can vary.
The
RTLD_DI_SERINFOSIZE

request described below allows applications to size the buffer suitably.
The caller must perform the following steps:

1.
使用RTLD_DI_SERINFOSIZE请求以后续RTLD_DI_SERINFO请求所需结构的大小(dls_size)填充Dl_serinfo结构。
2.
分配正确大小(dls_size)的Dl_serinfo缓冲区。
3.
使用另一个RTLD_DI_SERINFOSIZE请求填充上一步中分配的缓冲区的dls_size和dls_cnt字段。
4.
使用RTLD_DI_SERINFO获取库搜索路径。
Dl_serinfo结构定义如下:
typedef struct {
    size_t dls_size;           /* Size in bytes of
                                  the whole buffer */
    unsigned int dls_cnt;      /* Number of elements
                                  in 'dls_serpath' */
    Dl_serpath dls_serpath[1]; /* Actually longer,
                                  'dls_cnt' elements */
} Dl_serinfo;
上述结构中的每个dls_serpath元素都是以下形式的结构:
typedef struct {
    char *dls_name;            /* Name of library search
                                  path directory */
    unsigned int dls_flags;    /* Indicates where this
                                  directory came from */
} Dl_serpath;
dls_flags字段当前未使用,并且始终包含零。
RTLD_DI_SERINFOSIZE(Dl_serinfo *)
使用适合于分配缓冲区以供后续RTLD_DI_SERINFO请求使用的值,填充info指向的Dl_serinfo结构的dls_size和dls_cnt字段。
RTLD_DI_TLS_MODID(size_t *, since glibc 2.4)
获取此共享对象的TLS(线程本地存储)段的模块ID,如TLS重定位中所使用。如果此对象未定义TLS段,则* info中将置零。
RTLD_DI_TLS_DATA(void **, since glibc 2.4)
获取指向与该共享库的TLS段相对应的调用线程的TLS块的指针。如果此对象未定义PT_TLS段,或者调用线程尚未为其分配块,则将* NULL放置在* info中。

返回值

成功时,dlinfo()返回0。失败时,它返回-1;否则,它返回-1。可以使用dlerror(3)诊断错误原因。

版本

dlinfo()最早出现在glibc 2.3.3中。

属性

有关本节中使用的术语的说明,请参见attribute(7)。

InterfaceAttributeValue
dlinfo()Thread safetyMT-Safe

遵循规范

此函数是非标准的GNU扩展。

备注

该函数源自同名的Solaris函数,并且还出现在某些其他系统上。各种实现所支持的请求集仅部分重叠。

示例

下面的程序使用dlopen(3)打开共享库,然后使用RTLD_DI_SERINFOSIZE和RTLD_DI_SERINFO请求获取库的库搜索路径列表。这是运行程序时可能看到的示例:

$ ./a.out /lib64/libm.so.6
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;
    int j;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <libpath>\n", 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\n", 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\n", 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_sizeaq and aqdls_cntaq fields in the newly
       allocated buffer */

    if (dlinfo(handle, RTLD_DI_SERINFOSIZE, sip) == -1) {
        fprintf(stderr, "RTLD_DI_SERINFOSIZE failed: %s\n", 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\n", dlerror());
        exit(EXIT_FAILURE);
    }

    for (j = 0; j < serinfo.dls_cnt; j++)
        printf("dls_serpath[%d].dls_name = %s\n",
                j, sip->dls_serpath[j].dls_name);

    exit(EXIT_SUCCESS);
}

另外参见

dl_iterate_phdr(3),dladdr(3),dlerror(3),dlopen(3),dlsym(3),ld.so(8)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/