unresolved symbol __moddi3…とか

gccは除算を最適化するために、/とか%の演算を__moddi3の呼び出しに変更してしまうようだ。いや変更はしないのだが、呼び出す選択肢もあって、シンボルだけは参照するのかな。それでとにかく、除算を含むプログラムをあるコンパイル方法でコンパイルしたときには、

unresolved symbol __moddi3
unresolved symbol __divdi3
can't resolve symbol '__moddi3'
can't resolve symbol '__divdi3'

などのエラーが出る。「あるコンパイル方法」というのは単に-nostdlibつき、ということなんだけど、__moddi3とかはlibgcc.aに含まれているので、libgcc.aをリンクしないような指定である-nostdlibをつけるとダメなのだ。-nostdlibをつけないか、あるいは手動でlibgcc.aをリンクすればよい。あるいはがんばって除算を使わないようにするという選択肢もある。しかし__moddi3等を使わないようにするコンパイルオプションも欲しいところ。

他にも、libgcc.aに入っている隠し関数(? hidden属性がついたシンボル)はこんな感じで、たくさんある。

__muldi3, __negdi2, __lshrdi3, __ashldi3, __ashrdi3, __ffsdi2, __clz_tab, __cmpdi2, __ucmpdi2, __floatdidf, __floatdisf, __fixunsdfsi, __fixunssfsi, __fixunsdfdi, __fixdfdi, __fixunssfdi, __fixsfdi, __fixxfdi, __fixunsxfdi, __floatdixf, __fixunsxfsi, __clear_cache, __absvsi2, __absvdi2, __addvsi3, __addvdi3, __subvsi3, __subvdi3, __mulvsi3, __mulvdi3, __negvsi2, __negvdi2, __divdi3, __moddi3, __udivdi3, __umoddi3, __udiv_w_sdiv, __udivmoddi4, __eprintf, __bb_exit_func, __bb_fork_func, __bb_init_func, __gcc_bcmp

気をつけられたい。

あ、__bb_*はbasic blockのプロファイラ用だな。こんなところにあったのか。また別の話になるけど、これはおもしろい機能で、テストカバレッジを調べるツールなんだけど、プログラムの各行を走った回数がわかるので、プロファイルにも使える。普通のgcc -pgは関数単位だけど、gcc -fprofile-arcs -ftest-coverageはbasic block単位なのだ(簡単に言えば行単位…と言うと説明が間違ってるけど)。そしてgcovで出てきた結果を解析する。

詳しくはgcovのマニュアル(info)を読んでみるとよいだろう。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です