侧边栏壁纸
博主头像
noerror

虚灵不寐,众理具而万事出。

  • 累计撰写 238 篇文章
  • 累计创建 9 个标签
  • 累计收到 2 条评论
标签搜索

目 录CONTENT

文章目录

dlinfo函数用法详解

noerror
2022-10-19 / 0 评论 / 0 点赞 / 35 阅读 / 1,338 字 / 正在检测是否收录...

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_SERINFOSIZERTLD_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);
}
0

评论区