NDK r8b ld.exe assertion failの回避
Android NDK r8b で GCC 4.6のtoolchainを使うと大量のassertion failが出力される件の覚書。
当然ながらここに書いてある事は無保証です。真似してやる人は自己責任でやってくださいね。
どういう事象?
出力されるassertion failは以下みたいな感じ。
c:/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld.exe: BFD (GNU Binutils) 2.21 assertion fail /usr/local/google/home/andrewhsieh/ndk-andrewhsieh/src/build/../binutils/binutils-2.21/bfd/elf32-arm.c:10190
詳細
詳細は以下にかかれてます。
http://code.google.com/p/android/issues/detail?id=35209
対応方法
Patchはすでにあるのでr8bの次が出てくれば解決するとおもわれる。
古いbinutilsの出力はtag_FP_archが設定されていない。4.6 toolchainに含まれるldでは、このときにtag_ABI_HardFP_useが1になっていると当該箇所でfailする。
上記のPatchではそもそもこのtag_FP_archが設定されていない場合には当該箇所でassertさせないようにして根本解決をはかっている。
Application.mkを変更してTOOLCHAINを4.4.3に変更する事でも対処可能(You may set NDK_TOOLCHAIN_VERSION=4.4.3
in Application.mk
to select the original one.)。ただ、これやるとunknownな属性とかで別のwarningが出るので4.6で対応したいなと。
方法としては上記のIssueにあがってるgoldのbinaryを使うのが正攻法。ただ、個人的にgoldに変更すると別の問題が出そうで少し不安(^ω^;)。これはr8bのrelease時にMacOSやLinuxではgoldが利用可能になったけれどもDefaultでDisabledな事を鑑みてのこと。
ここで goldに変更するとなぜOKなのか?というと、そもそもこのチェックをしないので問題が無くなるとのこと。
なら通常のtoolchainのld.exeのassertを無効にしちゃえって事でBinary Patchをしてみた。
Binary Patch
大量のassertを吐いてるのはtoolchainの以下のファイル
c:/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/arm-linux-androideabi/bin/ld.exe
のファイルのoffset 0x57BF9をに85 c0がある。こいつは当該Source FileでASSERTしてるin_attr[Tag_ABI_HardFP_use].i == 0の比較にあたるTEST EAX,EAX。
こいつを85c0から31c0に変更することでXOR EAX,EAXとなり、ASSERTされなくなります。