| DLINFO(3) | Руководство программиста Linux | DLINFO(3) | 
dlinfo - возвращает информацию о динамически загруженном объекте
#define _GNU_SOURCE #include <link.h> #include <dlfcn.h>
int dlinfo(void *handle, int request, void *info);
Компонуется при указании параметра -ldl.
Функция dlinfo() возвращает информацию о динамически загруженном объекте, на который указывает handle (обычно полученный ранее вызовом dlopen(3) или dlmopen(3)). В аргументе request указывается какую информацию нужно получить. Аргумент info — указатель на буфер для хранения информации, возвращаемой вызовом; тип данного аргумента зависит от request.
Для request поддерживаются следующие значения (соответствующий тип info показан в скобках):
struct link_map {
    ElfW(Addr) l_addr;  /* разница между
                           адресом в файле ELF и
                           адресом в памяти */
    char      *l_name;  /* абсолютный путь, где
                           был найден объект */
    ElfW(Dyn) *l_ld;    /* динамический раздел
                           общего объекта */
    struct link_map *l_next, *l_prev;
                        /* цепочка загруженных объектов */
    /* дополнительные поля, зависящие от
       реализации */
};
    
  typedef struct {
    size_t dls_size;           /* размер в байтах
                                  всего буфера */
    unsigned int dls_cnt;      /* количество элементов
                                  в «dls_serpath» */
    Dl_serpath dls_serpath[1]; /* на самом деле больше,
                                  элементы «dls_cnt» */
} Dl_serinfo;
    
  typedef struct {
    char *dls_name;            /* имя каталога в
                                   путях поиска библиотек */
    unsigned int dls_flags;    /* показывает, откуда
                                  возник каталог */
} Dl_serpath;
    
  При успешном выполнении dlinfo() возвращает 0. При ошибке возвращается -1; причину ошибки можно узнать с помощью dlerror(3).
Функция dlinfo() впервые появилась в glibc версии 2.3.3.
Описание терминов данного раздела смотрите в attributes(7).
| Интерфейс | Атрибут | Значение | 
| dlinfo() | Безвредность в нитях | MT-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
#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, "Использование: %s <libpath>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    /* получаем описатель общего объекта, указанного в командной строке */
    handle = dlopen(argv[1], RTLD_NOW);
    if (handle == NULL) {
        fprintf(stderr, "ошибка dlopen(): %s\n", dlerror());
        exit(EXIT_FAILURE);
    }
    /* определяем размер буфера, который мы должны передать
       RTLD_DI_SERINFO */
    if (dlinfo(handle, RTLD_DI_SERINFOSIZE, &serinfo) == -1) {
        fprintf(stderr, "ошибка RTLD_DI_SERINFOSIZE: %s\n", dlerror());
        exit(EXIT_FAILURE);
    }
    /* выделяем буфер для RTLD_DI_SERINFO */
    sip = malloc(serinfo.dls_size);
    if (sip == NULL) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    /* инициализируем поля 'dls_size' и 'dls_cnt' в только
       что выделенном буфере */
    if (dlinfo(handle, RTLD_DI_SERINFOSIZE, sip) == -1) {
        fprintf(stderr, "ошибка RTLD_DI_SERINFOSIZE: %s\n", dlerror());
        exit(EXIT_FAILURE);
    }
    /* получаем и печатаем список поиска библиотек */
    if (dlinfo(handle, RTLD_DI_SERINFO, sip) == -1) {
        fprintf(stderr, "ошибка RTLD_DI_SERINFO: %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)
| 2019-03-06 | Linux |