【ELF形式】.note.gnu.build-id セクション

「.note.*」セクションは、「注釈セクション」というものらしいです。

ORACLE Documentation リンカーとライブラリ 第7章オブジェクトファイル 注釈セクション」
http://docs.oracle.com/cd/E19620-01/805-5821/6j5ga47bq/index.html#chapter6-18048

オブジェクトファイルの注釈セクションの内容は、readelfコマンドで出力されます。

$ readelf -Wn sample

オフセット 0x00000168, 長さ 0x00000020 の備考:
  所有者            データサイズ	説明
  GNU                  0x00000010	NT_GNU_ABI_TAG (ABI バージョンタグ)
    OS: Linux, ABI: 2.6.24

オフセット 0x00000188, 長さ 0x00000024 の備考:
  所有者            データサイズ	説明
  GNU                  0x00000014	NT_GNU_BUILD_ID (一意なビルドID ビット列)
    ビルドID: 7abe98cbbf3c90a91120f62954c08001a5452873

「.note.gnu.build-id」のセクションヘッダの内容をダンプしてみます。

#
# .note.gnu.build-id
#
# セクションヘッダ
$ od -x -A x -j0x11c4 -N0x28 sample
0011c4 0031 0000 0007 0000 0002 0000 8188 0804
0011d4 0188 0000 0024 0000 0000 0000 0000 0000
0011e4 0004 0000 0000 0000
0011ec

セクションヘッダの内容は、以下の通り。

Elf_Shdr バイナリ 項目 バイナリの意味
.sh_name 0x00000031 セクション名 ".note.gnu.build-id"
.sh_type 0x00000007 セクションのタイプ 注釈セクション(SHT_NOTE)
.sh_flags 0x00000002 各種フラグ ロード時にメモリ上に領域確保するセクション(SHF_ALLOC)
.sh_addr 0x08048188 ロード先アドレス 0x08048188
.sh_offset 0x00000188 ELF形式中でのセクションの位置 0x188
.sh_size 0x00000024 セクションのバイトサイズ 36バイト
.sh_link 0x00000000 (セクションのタイプ依存で利用) -
.sh_info 0x00000000 (同上) -
.sh_addralign 0x00000004 セクションがメモリにロードされる際のバイトアラインメント 4バイト
.sh_entsize 0x00000000 構造体配列になっているセクションで利用される。配列要素のサイズ -

セクション内容をダンプしてみます。

# セクション
$ od -x -A x -j0x188 -N0x24 sample
000188 0004 0000 0014 0000 0003 0000 4e47 0055
000198 be7a cb98 3cbf a990 2011 29f6 c054 0180
0001a8 45a5 7328
0001ac

$ readelf -x3 sample

セクション '.note.gnu.build-id' の 十六進数ダンプ:
  0x08048188 04000000 14000000 03000000 474e5500 ............GNU.
  0x08048198 7abe98cb bf3c90a9 1120f629 54c08001 z....<... .)T...
  0x080481a8 a5452873                            .E(s

注釈セクションの構造体Elf32_Nhdrは、/usr/include/elf.hで定義されています。

1026 /* Note section contents.  Each entry in the note section begins with
1027    a header of a fixed form.  */
1028 
1029 typedef struct
1030 {
1031   Elf32_Word n_namesz;          /* Length of the note's name.  */
1032   Elf32_Word n_descsz;          /* Length of the note's descriptor.  */
1033   Elf32_Word n_type;            /* Type of the note.  */
1034 } Elf32_Nhdr;
1035 

上の構造体を当てはめてみるとデータの意味は以下の通りとなります。

シンボル バイナリ 項目 値の意味
Elf32_Nhdr.n_namesz 0000 0004 nameサイズ 4バイト
Elf32_Nhdr.n_descsz 0000 0014 descサイズ 20バイト
Elf32_Nhdr.n_type 0000 0003 NT_GNU_BUILD_ID 3
name 474e5500 name "GNU\0"
desc 7abe 98cb bf3c 90a9 1120 f629 54c0 8001 a545 2873 ビルドID -

160ビットのビルドIDは、ldコマンドのオプション「--build-id=<style>」でアルゴリズムを指定して生成されます。「--build-id」を指定しない場合、デフォルトのアルゴリズムであるSHA1が使用されます。<style>に指定できる値は以下の通り。

style アルゴリズム
uuid 128 random bits
sha1 160-bit SHA1 hash(デフォルト)
md5 128-bit MD5 hash
none .note.gnu.build-id セクションを作成しない

【参考】
「LD 2.1 Command Line Options」
https://sourceware.org/binutils/docs-2.20/ld/Options.html#Options