ELFファイルのレイアウトとそのメンバについてわからないことがあります。
OS情報です。
Linux linux-mint 4.10.0-42-generic #46~16.04.1-Ubuntu SMP Mon Dec 4 15:57:59 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
以下は単純なCプログラム(main関数からsleep()を呼び出してスリープするだけです)からreadelf -l a.outでELFの情報を出したものです。
Program Headersのところには、プログラムヘッダの一覧が出ています。
lang
1typedef struct { 2 uint32_t p_type; /* セグメントのタイプ */ 3 uint32_t p_flags; /* セグメントに関係するフラグ */ 4 Elf64_Off p_offset; /* ファイル先頭からセグメントまでのオフセット */ 5 Elf64_Addr p_vaddr; /* セグメントの最初のバイトが格納される仮想アドレス */ 6 Elf64_Addr p_paddr; /* セグメントの最初のバイトが格納される物理アドレス */ 7 uint64_t p_filesz; /* セグメントのファイルイメージサイズ */ 8 uint64_t p_memsz; /* メモリ上に配置されるセグメントのサイズ */ 9 uint64_t p_align; /* アライメント */ 10} Elf64_Phdr;
プログラムヘッダを表現する構造体は上記です。
また、先ほどのCプログラムを実行した時の/proc/pid/mapsの出力を見てみると以下のようになっています。
わからないことの1つ目なのですが、Elf64_Phdrのメンバであるp_vaddrは、manページによるとセグメントの先頭バイトがある仮想アドレスを保持しているはずです。例えば、図1の上から4番目のLOADタイプのセグメントはDATAセグメントだと思われます。また、そのp_vaddrは0x0000000000600e10となっていますが、図2の3行目では開始アドレスは0x006010000となっており、ELFファイルが保持する情報と一致していないように思われます。
しかし、図1の上から3番目のLOADタイプのTEXTセグメントと思われるセグメントのp_vaddrは0x0000000000400000となっていますが、図2の一行目の開始アドレスは0x00400000となっており、こちらは一致しているように見えます。
これはなんなのでしょうか?
2つめですが、セグメントの位置と大きさについてです。図1にあるDATAセグメントの開始アドレスが0x0000000000600e10であり、 メモリ上のセグメントサイズを表すp_memszは0x230となっています。とすると、データセグメントの終了アドレスは以下のようになると思います。(1つめの疑問からいろいろと間違っているかもしれませんが、一応自分の頭の中で考えていることとして書きます)
0x0000000000601040 = 0x0000000000600e10 + 0x230
ですが、文字通りにとれば、DATAセグメントが0x0000000000601040で終わるとすると、その下のDYNAMICセグメントの開始アドレス0x0000000000600e28と被ってしまうはずです。
ELFはどのようにメモリにロードされているのでしょうか?
よろしくお願いします。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/05/17 12:19 編集