ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
Oracle Solaris 11.1 リンカーとライブラリガイド Oracle Solaris 11.1 Information Library (日本語) |
7. システムのパフォーマンスを最適化するオブジェクトの構築
パート IV ELF アプリケーションバイナリインタフェース
ELF ファイルの内容を解析するために、標準の UNIX ユーティリティー dump(1)、nm(1)、size(1) など、さまざまなツールが使用できます。Oracle Solaris では、これらのツールは大部分が elfdump(1) に置き換えられました。
以降のセクションで説明するさまざまなパフォーマンスの問題を調べるには、eldump を使用して ELF オブジェクトの内容を診断すると役に立つことがあります。
ELF 形式では、データがセクションにまとめられます。次に、セクションはセグメントと呼ばれる単位に割り当てられます。セグメントには、ファイルの一部がどのようにメモリーにマップされるかが記述されます。mmapobj(2) を参照してください。これらの読み込み可能セグメントは、elfdump(1) コマンドを使用して PT_LOAD エントリを調べることによって表示できます。
$ elfdump -p -NPT_LOAD libfoo.so.1 Program Header[0]: p_vaddr: 0 p_flags: [ PF_X PF_R ] p_paddr: 0 p_type: [ PT_LOAD ] p_filesz: 0x53c p_memsz: 0x53c p_offset: 0 p_align: 0x10000 Program Header[1]: p_vaddr: 0x1053c p_flags: [ PF_X PF_W PF_R ] p_paddr: 0 p_type: [ PT_LOAD ] p_filesz: 0x114 p_memsz: 0x13c p_offset: 0x53c p_align: 0x10000
共有オブジェクト libfoo.so.1 には、一般に「テキスト」セグメントおよび「データ」セグメントと呼ばれる 2 つの読み込み可能なセグメントがあります。テキストセグメントがマップされ、その内容 (PF_X と PF_R) の読み込みと実行が可能になります。データセグメントもマップされ、その内容 PF_W が変更できるようになります。データセグメントのメモリーサイズ (p_memsz) は、ファイルサイズ (p_filesz) とは異なります。この違いは、データセグメントの一部であり、セグメントが読み込まれると動的に作成される .bss セクションを示すものです。
プログラマがファイルについて考えるとき、多くの場合、そのコード内の関数とデータ要素を定義するシンボルの点から考えます。これらのシンボルは、elfdump の -s オプションを使用すると表示できます。
$ elfdump -sN.symtab libfoo.so.1 Symbol Table Section: .symtab index value size type bind oth ver shndx name .... [36] 0x00010628 0x00000028 OBJT GLOB D 0 .data data .... [38] 0x00010650 0x00000028 OBJT GLOB D 0 .bss bss .... [40] 0x00000520 0x0000000c FUNC GLOB D 0 .init _init .... [44] 0x00000508 0x00000014 FUNC GLOB D 0 .text foo .... [46] 0x0000052c 0x0000000c FUNC GLOB D 0 .fini _fini
elfdump で表示されるシンボルテーブル情報には、シンボルに関連するセクションが含まれます。elfdump の -c オプションを使用すると、これらのセクションに関する情報を表示できます。
$ elfdump -c libfoo.so.1 .... Section Header[6]: sh_name: .text sh_addr: 0x4f8 sh_flags: [ SHF_ALLOC SHF_EXECINSTR ] sh_size: 0x28 sh_type: [ SHT_PROGBITS ] sh_offset: 0x4f8 sh_entsize: 0 sh_link: 0 sh_info: 0 sh_addralign: 0x8 Section Header[7]: sh_name: .init sh_addr: 0x520 sh_flags: [ SHF_ALLOC SHF_EXECINSTR ] sh_size: 0xc sh_type: [ SHT_PROGBITS ] sh_offset: 0x520 sh_entsize: 0 sh_link: 0 sh_info: 0 sh_addralign: 0x4 Section Header[8]: sh_name: .fini sh_addr: 0x52c sh_flags: [ SHF_ALLOC SHF_EXECINSTR ] sh_size: 0xc sh_type: [ SHT_PROGBITS ] sh_offset: 0x52c sh_entsize: 0 sh_link: 0 sh_info: 0 sh_addralign: 0x4 .... Section Header[12]: sh_name: .data sh_addr: 0x10628 sh_flags: [ SHF_WRITE SHF_ALLOC ] sh_size: 0x28 sh_type: [ SHT_PROGBITS ] sh_offset: 0x628 sh_entsize: 0 sh_link: 0 sh_info: 0 sh_addralign: 0x4 .... Section Header[14]: sh_name: .bss sh_addr: 0x10650 sh_flags: [ SHF_WRITE SHF_ALLOC ] sh_size: 0x28 sh_type: [ SHT_NOBITS ] sh_offset: 0x650 sh_entsize: 0 sh_link: 0 sh_info: 0 sh_addralign: 0x4 ....
上記の例の elfdump(1) からの出力は、関数 _init、foo、および _fini と、セクション .init、.text、および .fini との関連を示します。これらのセクションは読み取り専用であるため、「テキスト」セグメントの一部です。
同様に、データ配列 data と bss は、それぞれセクション .data と .bss に関連付けられています。これらのセクションは書き込み可能であるため、「データ」セグメントの一部です。