dlinfo -
возвращает
информацию
о
динамически
загруженном
объекте
Dynamic linking library (
libdl,
-ldl)
#define _GNU_SOURCE
#include <link.h>
#include <dlfcn.h>
int dlinfo(void *restrict handle, int request, void *restrict info);
Функция
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; /* 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; /* имя каталога в
путях поиска библиотек */
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(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;
if (argc != 2) {
fprintf(stderr, "Использование: %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(): %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: %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 'dls_size' and 'dls_cnt' fields in the newly
allocated buffer. */
if (dlinfo(handle, RTLD_DI_SERINFOSIZE, sip) == -1) {
fprintf(stderr, "ошибка RTLD_DI_SERINFOSIZE: %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: %s\n", dlerror());
exit(EXIT_FAILURE);
}
for (size_t j = 0; j < serinfo.dls_cnt; j++)
printf("dls_serpath[%zu].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)
Русский
перевод
этой
страницы
руководства
был сделан Yuri
Kozlov <
[email protected]> и Иван
Павлов <
[email protected]>
Этот
перевод
является
бесплатной
документацией;
прочитайте
Стандартную
общественную
лицензию GNU
версии 3
или более
позднюю,
чтобы
узнать об
условиях
авторского
права. Мы не
несем
НИКАКОЙ
ОТВЕТСТВЕННОСТИ.
Если вы
обнаружите
ошибки в
переводе
этой
страницы
руководства,
пожалуйста,
отправьте
электронное
письмо на
[email protected]