ELFファイルのどの部分をメモリにロードする必要がありますか? 質問する

ELFファイルのどの部分をメモリにロードする必要がありますか? 質問する

実行可能ファイルの ELF ファイルには、プログラム (セグメント) ヘッダーとセクション ヘッダーがあり、 を通じて確認できます。readelf -a次に例を示します。

ここに画像の説明を入力してください

ここに画像の説明を入力してください

上の 2 つの図は、それぞれセクション ヘッダーとプログラム (セグメント) ヘッダーです。セグメント ヘッダーは複数のセクション ヘッダーで構成されており、プログラムをメモリにロードするために使用されることがわかります。

メモリにロードする必要があるのは、.text、.rodata、.data、.bss セクションだけですか?

セグメント内の他のすべてのセクション (例: 3 番目のセグメント内の .ctors、.dtors、.jcr) はアライメントに使用されますか?

ベストアンサー1

セクションとセグメントは完全に異なる概念です。セクションは、そこに保存されるデータのセマンティクス (つまり、それが何に使用されるか) に関係し、デバッグ目的を除いて、プログラムまたは共有ライブラリがリンクされると、実際には無関係になります。セクション ヘッダーを完全に削除 (またはランダムなゴミで上書き) しても、プログラムは動作します。

セグメント (つまりプログラム ヘッダーのロード ディレクティブ) は、カーネルやダイナミック リンカーがプログラムをロードするときに実際に参照するものです。たとえば、このケースでは 2 つのロード ディレクティブがあります。最初のディレクティブは、ファイルの最初の 4k (1 ページ) をアドレス 0x08048000 にマップし、このマッピングの最初の 0x4b8 バイトのみが実際に使用されることを示します (残りはアラインメントです)。2 番目のディレクティブは、ファイルの最初の 8k (2 ページ) をアドレス 0x08049000 にマップします。その大部分はアラインメントです。最初の 0xf14 バイトはロード ディレクティブの一部ではなく (アラインメントのみ)、無駄になります。0x08049f14 から、ファイルからマップされた 0x108 バイトが実際に使用され、別の 0x10 バイト (MemSize 0x118 に達するため) はローダー (カーネルまたはダイナミック リンカー) によってゼロで埋められます。これは 0x0804a02c (2 番目のマップ ページ) まで広がります。2 番目のマップ ページの残りは未使用/無駄です (ただし、mallocヒープの一部として使用するために回復できる可能性があります)。

最後に、セクション ヘッダーはまったく使用されませんが、プログラムの実行中にさまざまなセクションの内容が使用される場合があります。 および のアドレス範囲は 2 番目のロード マッピングの先頭にあるため、実行時にプログラムによってマップされ、アクセス可能であることに注意してください.ctors( .dtorsctor/dtor 属性を持つ C++ または "GNU C" コードが使用された場合、ランタイムの起動/終了コードは、グローバル コンストラクターとデストラクタを実行するためにそれらを使用します)。 また、 は.data2 番目のマップされたページのアドレス 0x0804a00c から始まることにも注意してください。 これにより、再配置が適用された後 (プログラム ヘッダーの RELRO ディレクティブ)、最初のページを読み取り専用で保護できます。

おすすめ記事