2015年10月09日
GNU ldのwarning: sh_link not set for section `.ARM.exidx'警告
GNU ld が ARM ターゲットのプログラムのリンク時に以下のような警告を出すケースに遭遇しました。(XXX.out は ELF ファイル名)
C:/PATH/TO/ld.exe: XXX.out: warning: sh_link not set for section `.ARM.exidx'普通は出ない珍しい警告で、日本語ではほとんど情報が無くて調査に苦労したので、メモしておきます。
この警告は、どうやら、".ARM.exidx" セクションの sh_link メンバの値(セクションヘッダテーブルの index 値)が ".text" セクションを指して無い時に出る警告のようです。
".ARM.exidx" セクションは、libgcc によって使用される C++ の例外処理用コード等が含まれるセクションで、このプロジェクトではプログラムが C で記述されていたためか、空(0 バイト)となっていました。
通常、0 バイトのセクションは、ELF ファイルに出力されないようなのですが、リンカスクリプトのセクション定義で ALIGN 指令を使っていると、例えアライメントが既に揃っていて、一切ロケーションカウンタに影響を与えない場合でも、0 バイトのセクションを出力してしまうようです。
(ドキュメントを読んでも、この ALIGN の動作に関しての記述を見つけることができなかったのですが、現在の最新の binutils 2.25 の GNU ld では、とりあえずそのような動作になるようです。)
警告が出ない ELF は、readelf でセクションヘッダをダンプしてみると、以下のように ".ARM.exidx" の中身がある場合は、ちゃんと ".text" を指しているか、空セクションで ".ARM.exidx" セクション自体が出力されないかの、いずれかになります。(Lk が sh_link の値で、".text" の index=1 になっています。)
参考サイト
「[llvm] r174372 - Link .ARM.exidx with corresponding text section.」
http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20130204/164356.html
".ARM.exidx" セクションは、libgcc によって使用される C++ の例外処理用コード等が含まれるセクションで、このプロジェクトではプログラムが C で記述されていたためか、空(0 バイト)となっていました。
通常、0 バイトのセクションは、ELF ファイルに出力されないようなのですが、リンカスクリプトのセクション定義で ALIGN 指令を使っていると、例えアライメントが既に揃っていて、一切ロケーションカウンタに影響を与えない場合でも、0 バイトのセクションを出力してしまうようです。
(ドキュメントを読んでも、この ALIGN の動作に関しての記述を見つけることができなかったのですが、現在の最新の binutils 2.25 の GNU ld では、とりあえずそのような動作になるようです。)
... .ARM.exidx : { . = ALIGN(4); *(.ARM.exidx* .gnu.linkonce.armexidx.*); } ...そして、その出力された空セクションの sh_link が 0 で(空なので、0 番目の NULL セクションを指している?)、".text" セクションを指していないので、警告が出ていたようでした。(どのみち使用されないセクションなので、実害は無いと思われますが。)
警告が出ない ELF は、readelf でセクションヘッダをダンプしてみると、以下のように ".ARM.exidx" の中身がある場合は、ちゃんと ".text" を指しているか、空セクションで ".ARM.exidx" セクション自体が出力されないかの、いずれかになります。(Lk が sh_link の値で、".text" の index=1 になっています。)
>readelf -S YYY.out Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 20000000 010000 0073bc 00 AX 0 0 16 ... [ 4] .ARM.exidx ARM_EXIDX 20007418 017418 000008 00 AL 1 0 4警告が出る場合、以下のように sh_link が 0 になっていました。
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
...
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 10000000 010000 000750 00 AX 0 0 16
...
[ 4] .ARM.exidx ARM_EXIDX 1000075c 020004 000000 00 WL 0 0 1
ちなみに、以下のようにリンカスクリプトの記述を修正することで、この警告は回避できました。(もちろんセクション定義の前でアライメントを揃えておいても良いですし、そもそも通常はこの部分は ALIGN 指定する必要は無いように最初から書かれています。あくまでも、今回リンカスクリプト編集中にたまたま発生した、この珍しい警告の原因調査と、この警告を回避するために、セクション定義の中カッコの内部で ALIGN 指令を使用しないようにした、という例です。)
... .ARM.exidx ALIGN(4) : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } ...
参考サイト
「[llvm] r174372 - Link .ARM.exidx with corresponding text section.」
http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20130204/164356.html
The sh_link in the ELF section header of .ARM.exidx should be filled with the section index of the corresponding text section.