Provided by: manpages-ru-dev_4.21.0-2_all bug

ИМЯ

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

LIBRARY

       Standard C library (libc, -lc)

СИНТАКСИС

       #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 */

               /* Следующие поля были добавлены в glibc 2.4, после опубликования
                  первой версии этой структуры. Из аргумента size,
                  передаваемом в dl_iterate_phdr, можно определить
                  были ли добавлены новые члены. */

               unsigned long long dlpi_adds;
                               /* Incremented when a new object may
                                  have been added */
               unsigned long long dlpi_subs;
                               /* Incremented when an object may
                                  have been removed */
               size_t dlpi_tls_modid;
                               /* If there is a PT_TLS segment, its module
                                  ID as used in TLS relocations, else zero */
               void  *dlpi_tls_data;
                               /* The address of the calling thread's instance
                                  of this module's PT_TLS segment, if it has
                                  one and it has been allocated in the calling
                                  thread, otherwise a null pointer */
           };

       (Макрос  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;

       Возможными значениями p_type поля могут быть (подробности смотрите в <elf.h>):

           #define PT_LOAD         1    /* загружаемый сегмент программы */
           #define PT_DYNAMIC      2    /* информация о динамической компоновке */
           #define PT_INTERP       3    /* интерпретатор программы */
           #define PT_NOTE         4    /* вспомогательная информация */
           #define PT_SHLIB        5    /* зарезервировано */
           #define PT_PHDR         6    /* сам элемент таблицы заголовков */
           #define PT_TLS          7    /* сегмент локального хранилища нити */
           #define PT_GNU_EH_FRAME 0x6474e550 /* сегмент GCC .eh_frame_hdr */
           #define PT_GNU_STACK  0x6474e551 /* показывает, что стек — исполняемый */
           #define PT_GNU_RELRO  0x6474e552 /* только чтения после перемещения */

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

       Функция  dl_iterate_phdr()  возвращает  значение,  которое  было  получено в результате последнего вызова
       callback.

ВЕРСИИ

       dl_iterate_phdr()  has been supported since glibc 2.2.4.

АТРИБУТЫ

       Описание терминов данного раздела смотрите в attributes(7).
       ┌─────────────────────────────────────────────────────────────────────┬──────────────────────┬──────────┐
       │ ИнтерфейсАтрибутЗначение │
       ├─────────────────────────────────────────────────────────────────────┼──────────────────────┼──────────┤
       │ dl_iterate_phdr()                                                   │ Безвредность в нитях │ MT-Safe  │
       └─────────────────────────────────────────────────────────────────────┴──────────────────────┴──────────┘

СТАНДАРТЫ

       Функция dl_iterate_phdr() не описана  в  каком-либо  стандарте.  Эта  функция  есть  в  некоторых  других
       системах,  при  чём возвращаемая структура dl_phdr_info имеет другой формат. В BSD и Solaris, в структуре
       есть поля dlpi_addr, dlpi_name, dlpi_phdr и dlpi_phnum (помимо других внесённых реализацией полей).

ЗАМЕЧАНИЯ

       В будущих версиях библиотеки C в структуре dl_phdr_info могут появиться дополнительные  поля;  для  этого
       случая  предусмотрен  аргумент  size, который предоставляет вызываемой функции механизм обнаружения того,
       что она работает в системе с добавленными полями.

       Первый объект, просматриваемый callback, это главная программа. У главной программы поле dlpi_name  будет
       содержать пустую строку.

ПРИМЕРЫ

       Следующая  программа  выводит  список  путей  общих  объектов, из которых они были загружены. Для каждого
       общего объекта программа выводит информацию из каждого сегмента объектов ELF (виртуальный адрес,  размер,
       флаги и тип).

       В  следующем  сеансе оболочки показан вывод программы, запущенной в системе с архитектурой x86-64. Первый
       показанный общий объект это основная программа (вместо имени пустая строка).

           $ ./a.out
           Имя: "" (9 сегментов)
                0: [      0x400040; memsz:    1f8] flags: 0x5; PT_PHDR
                1: [      0x400238; memsz:     1c] flags: 0x4; PT_INTERP
                2: [      0x400000; memsz:    ac4] flags: 0x5; PT_LOAD
                3: [      0x600e10; memsz:    240] flags: 0x6; PT_LOAD
                4: [      0x600e28; memsz:    1d0] flags: 0x6; PT_DYNAMIC
                5: [      0x400254; memsz:     44] flags: 0x4; PT_NOTE
                6: [      0x400970; memsz:     3c] flags: 0x4; PT_GNU_EH_FRAME
                7: [         (nil); memsz:      0] flags: 0x6; PT_GNU_STACK
                8: [      0x600e10; memsz:    1f0] flags: 0x4; PT_GNU_RELRO
           Имя: "linux-vdso.so.1" (4 сегментов)
                0: [0x7ffc6edd1000; memsz:    e89] flags: 0x5; PT_LOAD
                1: [0x7ffc6edd1360; memsz:    110] flags: 0x4; PT_DYNAMIC
                2: [0x7ffc6edd17b0; memsz:     3c] flags: 0x4; PT_NOTE
                3: [0x7ffc6edd17ec; memsz:     3c] flags: 0x4; PT_GNU_EH_FRAME
           Имя: "/lib64/libc.so.6" (10 сегментов)
                0: [0x7f55712ce040; memsz:    230] flags: 0x5; PT_PHDR
                1: [0x7f557145b980; memsz:     1c] flags: 0x4; PT_INTERP
                2: [0x7f55712ce000; memsz: 1b6a5c] flags: 0x5; PT_LOAD
                3: [0x7f55716857a0; memsz:   9240] flags: 0x6; PT_LOAD
                4: [0x7f5571688b80; memsz:    1f0] flags: 0x6; PT_DYNAMIC
                5: [0x7f55712ce270; memsz:     44] flags: 0x4; PT_NOTE
                6: [0x7f55716857a0; memsz:     78] flags: 0x4; PT_TLS
                7: [0x7f557145b99c; memsz:   544c] flags: 0x4; PT_GNU_EH_FRAME
                8: [0x7f55712ce000; memsz:      0] flags: 0x6; PT_GNU_STACK
                9: [0x7f55716857a0; memsz:   3860] flags: 0x4; PT_GNU_RELRO
           Имя: "/lib64/ld-linux-x86-64.so.2" (7 сегментов)
                0: [0x7f557168f000; memsz:  20828] flags: 0x5; PT_LOAD
                1: [0x7f55718afba0; memsz:   15a8] flags: 0x6; PT_LOAD
                2: [0x7f55718afe10; memsz:    190] flags: 0x6; PT_DYNAMIC
                3: [0x7f557168f1c8; memsz:     24] flags: 0x4; PT_NOTE
                4: [0x7f55716acec4; memsz:    604] flags: 0x4; PT_GNU_EH_FRAME
                5: [0x7f557168f000; memsz:      0] flags: 0x6; PT_GNU_STACK
                6: [0x7f55718afba0; memsz:    460] flags: 0x4; PT_GNU_RELRO

   Исходный код программы

       #define _GNU_SOURCE
       #include <link.h>
       #include <stdint.h>
       #include <stdio.h>
       #include <stdlib.h>

       static int
       callback(struct dl_phdr_info *info, size_t size, void *data)
       {
           char *type;
           int p_type;

           printf("Имя: \"%s\" (%d сегментов)\n", info->dlpi_name,
                      info->dlpi_phnum);

           for (size_t j = 0; j < info->dlpi_phnum; j++) {
               p_type = info->dlpi_phdr[j].p_type;
               type =  (p_type == PT_LOAD) ? "PT_LOAD" :
                       (p_type == PT_DYNAMIC) ? "PT_DYNAMIC" :
                       (p_type == PT_INTERP) ? "PT_INTERP" :
                       (p_type == PT_NOTE) ? "PT_NOTE" :
                       (p_type == PT_INTERP) ? "PT_INTERP" :
                       (p_type == PT_PHDR) ? "PT_PHDR" :
                       (p_type == PT_TLS) ? "PT_TLS" :
                       (p_type == PT_GNU_EH_FRAME) ? "PT_GNU_EH_FRAME" :
                       (p_type == PT_GNU_STACK) ? "PT_GNU_STACK" :
                       (p_type == PT_GNU_RELRO) ? "PT_GNU_RELRO" : NULL;

               printf("    %2zu: [%14p; memsz:%7jx] flags: %#jx; ", j,
                       (void *) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr),
                       (uintmax_t) info->dlpi_phdr[j].p_memsz,
                       (uintmax_t) info->dlpi_phdr[j].p_flags);
               if (type != NULL)
                   printf("%s\n", type);
               else
                   printf("[other (%#x)]\n", p_type);
           }

           return 0;
       }

       int
       main(void)
       {
           dl_iterate_phdr(callback, NULL);

           exit(EXIT_SUCCESS);
       }

СМ. ТАКЖЕ

       ldd(1), objdump(1), readelf(1), dladdr(3), dlopen(3), elf(5), ld.so(8)

       Executable and Linking Format Specification в веб.

ПЕРЕВОД

       Русский перевод этой страницы руководства был сделан  Yuri  Kozlov  <yuray@komyakino.ru>  и  Иван  Павлов
       <pavia00@gmail.com>

       Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3
       или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

       Если  вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо
       на man-pages-ru-talks@lists.sourceforge.net.

Linux man-pages 6.03                            5 февраля 2023 г.                             dl_iterate_phdr(3)