DL_ITERATE_PHDR(3)

ИМЯ
dl_iterate_phdr - обход списка общих объектов

ОБЗОР
#define _GNU_SOURCE         /* см. feature_test_macros(7) */
#include <link.h>
int dl_iterate_phdr(
          int (*callback) (struct dl_phdr_info *info,
                           size_t size, void *data),
          void *data);

ОПИСАНИЕ
Функция dl_iterate_phdr() позволяет приложению во время выполнения узнать, какие общие объекты были загружены. Функция dl_iterate_phdr() обходит список общих объектов приложения и однократно вызывает функцию callback для каждого объекта до тех пор, пока или все общие объекты не будут просмотрены, или функция callback не вернёт ненулевое значение. При каждом вызове в callback передаётся три параметра: info (указатель на структуру с информацией об общем объекте), size (размер структуры, на которую указывает info) и data (копия любого значения, переданного вызывающей программой во втором параметре (также называемом data) в вызов dl_iterate_phdr(). Параметр info представляет собой структуру следующего вида:
struct dl_phdr_info {
    ElfW(Addr)        dlpi_addr;  /* базовый адрес объекта */
    const char       *dlpi_name;  /* имя объекта
                                     (оканчивается Null) */
    const ElfW(Phdr) *dlpi_phdr;  /* указатель на массив
                                     программных заголовков ELF
                                     этого объекта */
    ElfW(Half)        dlpi_phnum; /* кол-во элементов в dlpi_phdr */
};
(Макрос ElfW() преобразует свой аргумент в имя типа данных ELF, подходящее для аппаратной архитектуры. Например, на 32-битной платформе ElfW(Addr) вернёт имя типа данных Elf32_Addr. Дополнительную информацию можно найти в заголовочных файлах <elf.h> и <link.h>.) В поле dlpi_addr указывается базовый адрес общего объекта (т. е., разница между виртуальным адресом памяти общего объекта и смещением до этого объекта в файле, из которого он был загружен). Поле dlpi_name представляет собой строку с null на конце, определяющую путь, из которого был загружен общий объект. Чтобы понять назначение полей dlpi_phdr и dlpi_phnum, нам необходимо представлять, что общий объект ELF состоит из набора сегментов, каждый из которых имеет соответствующий программный заголовок, описывающий сегмент. Поле dlpi_phdr представляет собой указатель на массив программных заголовков этого общего объекта. В поле dlpi_phnum задаётся размер этого массива. Программные заголовки представляют собой структуры следующего вида:
typedef struct {
    Elf32_Word  p_type;    /* тип сегмента */
    Elf32_Off   p_offset;  /* смещение сегмента в файле */
    Elf32_Addr  p_vaddr;   /* виртуальный адрес сегмента */
    Elf32_Addr  p_paddr;   /* физический адрес сегмента */
    Elf32_Word  p_filesz;  /* размер сегмента в файле */
    Elf32_Word  p_memsz;   /* размер сегмента в памяти */
    Elf32_Word  p_flags;   /* флаги сегмента */
    Elf32_Word  p_align;   /* выравнивание сегмента */
} Elf32_Phdr;
Заметим, что мы можем вычислить расположение определённого программного заголовка x в виртуальной памяти по следующей формуле:
  addr == info->dlpi_addr + info->dlpi_phdr[x].p_vaddr;

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функция dl_iterate_phdr() возвращает значение, которое было получено в результате последнего вызова callback.

ВЕРСИИ
Функция dl_iterate_phdr() доступна в glibc начиная с версии 2.2.4.

СООТВЕТСТВИЕ СТАНДАРТАМ
Функция dl_iterate_phdr() есть только в Linux и не должна использоваться в переносимых приложениях.

ПРИМЕР
Следующая программа выводит список путей общий объектов, из которых они были загружены. Для каждого общего объекта программа показывает виртуальный адрес, по которому загружены сегменты ELF объекта.
#define _GNU_SOURCE
#include <link.h>
#include <stdlib.h>
#include <stdio.h>
static int
callback(struct dl_phdr_info *info, size_t size, void *data)
{
    int j;
    printf("имя=%s (%d сегментов)\n", info->dlpi_name,
        info->dlpi_phnum);
    for (j = 0; j < info->dlpi_phnum; j++)
         printf("\t\t заголовок %2d: адрес=%10p\n", j,
             (void *) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr));
    return 0;
}
int
main(int argc, char *argv[])
{
    dl_iterate_phdr(callback, NULL);
    exit(EXIT_SUCCESS);
}

СМОТРИТЕ ТАКЖЕ
ldd(1), objdump(1), readelf(1), dlopen(3), elf(5), ld.so(8) Executable and Linking Format Specification в веб.