kazmax - Linux で自宅サーバー

dl_iterate_phdr - ライブラリコールの説明 - Linux コマンド集 一覧表

  1. 名前
  2. 書式
  3. 説明
  4. 返り値
  5. 準拠
  6. 関連項目

名前

dl_iterate_phdr - 共有オブジェクトのリストを辿る

書式

#define _GNU_SOURCE
#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 は共有オブジェクトの情報を保持する構造体へのポインタである。 sizeinfo で指される構造体のサイズである。 data は呼び出し元プログラムから dl_iterate_phdr ()の呼び出しの (同じく data という名前の) 第 2 引き数として渡される値のコピーである。
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_phdrdlpi_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;

以下のプログラムは、共有オブジェクトがロードされた パス名の一覧を表示する。 各共有オブジェクトについて、このプログラムは オブジェクトの 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); }

返り値

dl_iterate_phdr ()関数は最後の callback の呼び出しで返された値を返す。

準拠

dl_iterate_phdr ()関数は Linux 固有であり、移植を考えたアプリケーションでは避けるべきである。

関連項目

  ldd (1),   objdump (1),  readelf (1),  dlopen (3),   ld.so (8), オンラインのいろいろな場所で入手できる "Executable and Linking Format Specification"