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/
に書かれている。