dladdr(3) транслирует адрес в информацию о символе

Other Alias

dladdr1

ОБЗОР

#define _GNU_SOURCE
#include <dlfcn.h>
int dladdr(void *addr, Dl_info *info);
int dladdr1(void *addr, Dl_info *info, void **extra_info, int flags);
Компонуется при указании параметра -ldl.

ОПИСАНИЕ

Функция dladdr() определяет, в каком из загруженных общих объектов приложения расположен адрес, указанный в addr. Если объект находится, то dladdr() возвращает информацию об общем объекте и символе, который относится к адресу addr. Данная информация возвращается в виде структуры Dl_info:

typedef struct {
    const char *dli_fname;  /* путь к общему объекту, который
                               содержит адрес */
    void       *dli_fbase;  /* начальный адрес, по которому расположен
                               общий объект */
    const char *dli_sname;  /* имя символа, к которому относится
                               адрес addr */
    void       *dli_saddr;  /* точный адрес символа с
                               именем dli_sname */
} Dl_info;

Если символ, соответствующий адресу addr, не найден, то dli_sname и dli_saddr устанавливаются в NULL.

Функция dladdr1() подобна dladdr(), но возвращает дополнительную информацию в аргументе extra_info. Возвращаемая информация зависит от значения, указанного в flags, которое может быть одним из:

RTLD_DL_LINKMAP
Возвратить указатель на карту ссылок для совпадающего файла. Аргумент extra_info указывает на указатель на структуру link_map (т. е., struct 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_DL_SYMENT
Возвращает указатель на элемент символьной таблицы ELF с совпадающим символом. Аргумент extra_info — указатель на символьный указатель: const ElfW(Sym) **. Макрос ElfW() преобразует этот аргумент в имя типа данных ELF, подходящее для аппаратной архитектуры. Например, на 64-битной платформе ElfW(Sym) возвращает имя типа данных Elf64_Sym, которое определено в <elf.h> так:

typedef struct  {
    Elf64_Word    st_name;     /* имя символа */
    unsigned char st_info;     /* тип символа и привязка */
    unsigned char st_other;    /* видимость символа */
    Elf64_Section st_shndx;    /* номер раздела */
    Elf64_Addr    st_value;    /* значение символа */
    Elf64_Xword   st_size;     /* размер символа */
} Elf64_Sym;

Поле st_name — номер в строковой таблице.

В поле st_info закодирован тип и привязка символа. Тип можно извлечь с помощью макроса ELF64_ST_TYPE(st_info) (или ELF32_ST_TYPE(), на 32-битных платформах), который возвращает одно из следующих значений:

ЗначениеОписание
STT_NOTYPEтип символа не указан
STT_OBJECTсимвол является объектом данных
STT_FUNCСимвол является объектом кода
STT_SECTIONсимвол, связанный с разделом
STT_FILEимя символа является именем файла
STT_COMMONсимвол является объектом общих данных
STT_TLSсимвол является объектом локальных данных нити
STT_GNU_IFUNCсимвол является объектом скрытого кода
Привязку символа можно извлечь из поля st_info с помощью макроса ELF64_ST_BIND(st_info) (или ELF32_ST_BIND(), на 32-битных платформах), который возвращает одно из следующих значений:

ЗначениеОписание
STB_LOCALлокальный символ
STB_GLOBALглобальный символ
STB_WEAKсимвол со слабой привязкой
STB_GNU_UNIQUEуникальный символ
В поле st_other содержится значение видимости символа, которую можно извлечь с помощью макроса ELF64_ST_VISIBILITY(st_info) (или ELF32_ST_VISIBILITY(), на 32-битных платформах), который возвращает одно из следующих значений:
ЗначениеОписание
STV_DEFAULTвидимость символа по умолчательным правилам
STV_INTERNALскрытый класс, связанный с процессором
STV_HIDDENсимвол недоступен в других модулях
STV_PROTECTEDне вытесняемый, не экспортируемый

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении эти функции возвращают ненулевое значение. Если адрес, указанный в addr, мог бы совпасть с общим объектом, но не с символом в общем объекте, то полям info->dli_sname и info->dli_saddr присваивается значение NULL.

Если адрес, указанный addr, мог бы совпасть с общим объектом, то эти функции возвращают 0. В этом случае сообщение об ошибке не доступно через dlerror(3).

ВЕРСИИ

Функция dladdr() есть в glibc 2.0 и новее. Функция dladdr1() впервые появилась в glibc 2.3.3.

АТРИБУТЫ

Описание терминов данного раздела смотрите в attributes(7).
ИнтерфейсАтрибутЗначение
dladdr(), dladdr1() безвредность в нитяхбезвредно (MT-Safe)

СООТВЕТСТВИЕ СТАНДАРТАМ

Данные функции являются нестандартными расширениями GNU, которые также присутствуют в Solaris.

ДЕФЕКТЫ

Иногда указатели на функции, передаваемые в dladdr(), могут вас удивить. На некоторых архитектурах (в частности, i386 и x86_64), dli_fname и dli_fbase могут указывать на объект, из которого вызывалась функция dladdr(), даже если функция, использовавшаяся как аргумент, должна быть из динамически скомпонованной библиотеки.

Проблема в том, что указатель на функцию по прежнему ищется во время компиляции, но всего лишь указывает на раздел plt (таблицу компоновки процедур) первоначального объекта (которая размещает вызов после запроса динамического компоновщика на поиск символа). Чтобы обойти это, вы можете попробовать скомпилировать независимый от размещения код: в этом случае компилятор больше не сможет подготовить указатель во время компиляции и gcc(1) создаст код, который просто загрузит конечный адрес символа из got (глобальной таблицы смещений) при запуске до передачи его в dladdr().