ОБЗОР
#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 показан в скобках):
- RTLD_DI_LMID (Lmid_t *)
- Возвратить ID списка карты связи (link-map list, пространство имён), в который загружен handle.
- RTLD_DI_LINKMAP (struct link_map **)
-
Возвратить указатель на структуру link_map, соответствующую
handle. Аргумент info указывает на указатель на структуру link_map,
определённую в <link.h> следующим образом:
struct link_map { ElfW(Addr) l_addr; /* разница между адресом в файле ELF и адресом в памяти */ char *l_name; /* абсолютный путь, где был найден объект */ ElfW(Dyn) *l_ld; /* динамический раздел общего объекта */ struct link_map *l_next, *l_prev; /* цепочка загруженных объектов */ /* дополнительные поля, зависящие от реализации */ }; - RTLD_DI_ORIGIN (char *)
- Скопировать путь источника общего объекта соответствующего handle в место, указанное info.
- RTLD_DI_SERINFO (Dl_serinfo *)
-
Возвратить пути поиска библиотек общего объекта, на который указывает
handle. Аргумент info — указатель на Dl_serinfo с путями
поиска. Так как количество путей поиска может быть разным, то размер
структуры, на которую указывает info, может быть различным. Запрос
RTLD_DI_SERINFOSIZE, описанный далее, позволяет приложению установить
подходящий размер. Вызывающий должен выполнить следующие шаги:
-
- 1.
- Использовать запрос RTLD_DI_SERINFOSIZE для заполнения структуры Dl_serinfo размером (dls_size) структуры, необходимой для последующего запроса RTLD_DI_SERINFO.
- 2.
- Выделить буфер Dl_serinfo правильного размера (dls_size).
- 3.
- Использовать запрос RTLD_DI_SERINFOSIZE для заполнения полей dls_size и dls_cnt буфера, выделенного на предыдущем шаге.
- 4.
- Использовать RTLD_DI_SERINFO для получения путей поиска библиотек.
-
-
Структура Dl_serinfo определена следующим образом:
typedef struct { size_t dls_size; /* размер в байтах всего буфера */ unsigned int dls_cnt; /* количество элементов в «dls_serpath» */ Dl_serpath dls_serpath[1]; /* на самом деле больше, элементы «dls_cnt» */ } Dl_serinfo;Каждый из элементов dls_serpath, в упомянутой выше структуре, представляет собой структуру следующего вида:typedef struct { char *dls_name; /* имя каталога в путях поиска библиотек */ unsigned int dls_flags; /* показывает, откуда возник каталог */ } Dl_serpath;Поле dls_flags в настоящее время не используется и всегда равно нулю.
- RTLD_DI_SERINFOSIZE (Dl_serinfo *)
- Заполнить поля dls_size и dls_cnt структуры Dl_serinfo, на которую указывает info, значениями, подходящими для выделения буфера, который будет использоваться в последующем запросе RTLD_DI_SERINFO.
- RTLD_DI_TLS_MODID (size_t *, начиная с glibc 2.4)
- Получить ID модуля сегмента TLS (локальное хранилище нити) общего объекта, которое используется в перемещениях TLS. Если этот объект не задаёт сегмент TLS, то в *info помещается ноль.
- RTLD_DI_TLS_DATA (void **, начиная с glibc 2.4)
- Получить указатель на блок TLS вызывающей нити, соответствующий этому сегменту TLS общего объекта. Если этот объект не задаёт сегмент PT_TLS, или если у вызывающей нити для этого не выделен блок, то в *info помещается NULL.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении dlinfo() возвращает 0. При ошибке возвращается -1; причину ошибки можно узнать с помощью dlerror(3).ВЕРСИИ
Функция dlinfo() впервые появилась в glibc версии 2.3.3.АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).| Интерфейс | Атрибут | Значение |
| dlinfo() | безвредность в нитях | безвредно (MT-Safe) |
СООТВЕТСТВИЕ СТАНДАРТАМ
Эта функция является нестандартным расширением GNU.ЗАМЕЧАНИЯ
Данная функция произошла от функции Solaris с тем же именем, а также есть в некоторых других системах. Набор запросов, поддерживаемых различными реализациями, перекрывается лишь частично.ПРИМЕР
Программа, показанная ниже, открывает общие объекты с помощью dlopen(), а затем использует запросы 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);
}

