leading underscore in ELF

さて,結局のところプログラマなのだから,言葉遣いや労働環境のことは放っておいて,ニッチな調べ物をしよう.

suikan師が最近ツボにはまっているELFにおけるシンボルのleading underscoreの件を追いかけてみた.実は私も以前から気になっていた話題.
色々なところで話題になるのだけれど,どこもイマイチ腑に落ちない.


オブジェクトフォーマットとして ELF を使う場合、アンダースコアのない方が正しかったと思います。確か ELF の ABI 仕様として決まっていたと記憶しています。初期の sh 用 toolchain が、ELF なのにアンダースコアをつけていた方が、変なんじゃないかと ...
上記引用元は,サイトのエラーで表示されない.Googleのキャッシュに残っていたものを引用.


アセンブラのアンダスコアの使い方の違い:a.out の実行形式では外部ラ
ベルには _(アンダスコア) が頭に付いていますが、ELF の実行形式ではそ
うなっていません。これは、手書きのアセンブラコードを組みこまない限
り問題にはなりません。_foo の形のラベルを全て foo に翻訳してやる
か、(移植性を高めたければ) EXTERNAL(foo) のようなマクロを用意し
て、(__ELF__ が定義されていればそのまま変数を返し、定義されていなけ
れば _ を付けるようにするのがいいでしょう。
あたかも決定的な書き方になっているけれども,実際のところ,GCCの*-*-elf ターゲットの多くには leading underscore がついている.この矛盾は何故?

ELF仕様書を当たってみる.

ELF仕様書に立ち返ればいいじゃん.ということで,立ち返る.ELF and ABI Standards
現在,ELF関係の仕様書は,ELFそのものとABIに分かれている.狭い意味でのELF仕様書には,ネーミングコンベンションの話は出てこないっぽい.

そこで,ABI仕様に目を移す.下記引用は,Global Data Symbols.これ以外にも,libcが絡む場合のネーミングコンベンションが複数に分散して書いてある.内容は同じ.


For entries in the following table that are in name - _name form, both symbols in each pair represent the same data. The underscore synonyms are provided to satisfy the ANSI C standard.
システムサービスの箇所では,

name
This gives the traditional name, such as read.
_name
This gives a system service name that follows the ANSI C convention of reserving symbols beginning with an underscore, such as _read.

The title of each of the below tables specifies whether synonyms must exist for the entries in that table.

など書いてある.

結局どういうこと?

結局,こういうことなのだろうと理解.

ELF仕様とよばれるものは,現行のVersion 1.2で,3分冊になっている.バイナリフォーマットを規定している分冊では,ネーミングコンベンションに関しては何も規定していない.
だから,leading underscore がついていたとしても何の問題もない.

SystemV ABI に準拠する処理系では,少なくとも libc やシステムサービスは,ANSI Cの命名規則に従う.アプリケーションではどのようなコンベンションでも構わないようにも読めるが,常識的なモノの考え方でコトを進めれば,ライブラリと同じ方針,つまり,leading underscore はつけないだろう.だから,ELFをバイナリフォーマットとしているPOSIX系OSの多く,特にSystemV ABIを採用しているLinuxでは,leading underscoreをつけないものとして扱われる.

バイナリフォーマットとしてのELF仕様に準拠した上で,SystemV ABIに非準拠でいることは,現行の仕様構成では問題が(たぶん)無い.だから,newlibなどlibc相当のライブラリをGCCが抱えていたとしても,leading underscore が付いていても問題はない.

ELF仕様は,1.1では分冊になっていなかった.だから「確か ELF の ABI 仕様として決まっていたと記憶」っていうのはあながち間違いでもない.でも古い.


ということ…らしい."らしい"ってのは,英文を隅から隅まで読んで理解できる根気も語学力もないため.でもたぶん十中八九は上記の通りだと思う.

余談:さてどうやって対策するか.

GCCの挙動は仕様を逸脱してはいない.しかし,ツールが絡んだ場合,酷く困るケースがある.ツールが SystemV ABI に準拠しているELFを想定している場合,leading underscoreがついているなどとは夢にも思っていない.


うーん.個人的に,現状を踏まえて困るツールと言えば Eclipse くらいなものなので,ちょちょいとハックすれば解決できるだろう.しかし,ELFを弄ってアレコレするツールは Eclipse 以外にもあるはずなので,その都度対応していたら際限がない.
せっかくconfigureに *-*-toppers という triplet を加えてもらっているので,これをテコにして -fno-leading-underscore を常時有効にしてしまえばとは思うのだが,TOPPERSの開発者は,それぞれ使うGCCのバージョンやディストリビューションに拘りがあるようで,指定したものを黙って使うかどうか.それに,私だってTOPPERSカーネルばかり弄っているわけでもない.*-*-elf-gcc で開発しなければならないとき,どうするのか.

悩ましいねぇ.