次のような簡単なプログラムをコンパイルしました
int main()
{
return 0;
}
Clang を実行可能ファイルに使用otool
し、コンパイラによって生成されたロード コマンドを報告するように求めました。私が興味を持っているのは、特にファイル内のセグメントLC_SEGMENT_64
を記述するものです。__TEXT
私が得る説明はこれです:
$ otool -lV foo
foo:
Load command 0
cmd LC_SEGMENT_64
cmdsize 72
segname __PAGEZERO
vmaddr 0x0000000000000000
vmsize 0x0000000100000000
fileoff 0
filesize 0
maxprot ---
initprot ---
nsects 0
flags (none)
Load command 1
cmd LC_SEGMENT_64
cmdsize 312
segname __TEXT
vmaddr 0x0000000100000000
vmsize 0x0000000000001000
fileoff 0
filesize 4096
maxprot rwx
initprot r-x
nsects 3
flags (none)
Section
sectname __text
segname __TEXT
addr 0x0000000100000f90
size 0x000000000000000f
offset 3984
align 2^4 (16)
reloff 0
nreloc 0
type S_REGULAR
attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
reserved1 0
reserved2 0
私の質問はfileoff
、2 番目のロード コマンドのフィールドがゼロに設定されているのはなぜですか?
このフィールドに関する Apple のドキュメントには、次のように記載されています。
ファイルは、fileoff からメモリ内のセグメントの先頭である vaddr にマップされます。
filesize
これにより、最初は、このフィールドが と組み合わせて、ローダーに次のようなものを示していると信じるようfileoff
にfileoff + filesize
なりました。しかし、もちろん、この値がゼロの場合、私の仮定は成立しません。
セグメントには少なくとも 1 つのセクションがあるため、ローダーはセクションの説明にあるそれぞれのオフセットの値を使用して実行するコードを特定するため、そのような値は必ずしも必要ではないと考えました。 、実際には、このセグメント内の最初のセクションにはoffset
フィールドの値があります (この場合は 3984 で、これは検証済みでotool -s __TEXT __text -j foo
あり、ファイル内でこのセクションが配置されているオフセットを実際に参照しています)。
しかし、同じソース ファイル (つまり、 のMH_OBJECT
代わりにtype を持つファイル) から生成されたオブジェクト ファイルに対して同じことを行うとMH_EXECUTE
、得られる結果は次のようになります。
$ otool -lV foo.o
foo.o:
Load command 0
cmd LC_SEGMENT_64
cmdsize 312
segname
vmaddr 0x0000000000000000
vmsize 0x0000000000000070
fileoff 464
filesize 112
maxprot rwx
initprot rwx
nsects 3
flags (none)
Section
sectname __text
segname __TEXT
addr 0x0000000000000000
size 0x000000000000000f
offset 464
align 2^4 (16)
reloff 0
nreloc 0
type S_REGULAR
attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
reserved1 0
reserved2 0
この場合、load コマンドのfileoff
フィールドの値は、最初のセクションの値と同じ__text
です。