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の次が出てくれば解決するとおもわれる。

https://android-review.googlesource.com/#/c/40890/1/build/tools/toolchain-patches/binutils/0001-Fix-newer-binutils-not-to-assert-on-non-existence-tag_FP_arch.patch

古い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.mkto 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されなくなります。