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 を 1 回ずつ呼び出す。 これは全ての共有オブジェクトが処理されるか、 callback が 0 以外の値を返すまで行われる。

各々の callback 呼び出しは 3 つの引き数を受け取る: info は共有オブジェクトの情報を保持する構造体へのポインターである。 size は info で指される構造体のサイズである。 data は呼び出し元プログラムから dl_iterate_phdr() の呼び出しの (同じく data という名前の) 第 2 引き数として渡される値のコピーである。

info 引き数は、以下のような型の構造体である。

struct dl_phdr_info {
    ElfW(Addr)        dlpi_addr;  /* オブジェクトのベースアドレス */
    const char       *dlpi_name;  /* (ヌル文字で終端された)
                                     オブジェクト名 */
    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 はヌル文字で終端された文字列であり、 このパス名のファイルから共有オブジェクトがロードされる。

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;   /* セグメントの配置 (alignment) */
} 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("name=%s (%d segments)\n", info->dlpi_name,
        info->dlpi_phnum);

    for (j = 0; j < info->dlpi_phnum; j++)
         printf("\t\t header %2d: address=%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

この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。