ICSのEmulatorとKernelを自前でビルドしたときの罠

Ice Cream Sandwichが対応するKernelのバージョンは3.0だ。なので、自前でkernelを用意する場合は、android-goldfish-3.0をダウンロード&ビルドすればいいはず。
しかし、android-4.0.3_r1をビルドし、その環境のEmulatorで使用すると、どうも動かない。起動に失敗しているようだ。(他のバージョンや、SDKのものでは試していない)
とりあえず周囲の方々の助力を得て無理やりデバッグして原因を探ってみた。するとどうやらlibc.soの初期化時にTLSレジスタのアドレスを取得するのだが、ここで落ちている。
goldfish-3.0は、TLSレジスタがあるものとしてビルドされていた(configの設定次第で変わるようだが、ARMv7に対応させるとこうなるようだ)。しかしEmulator側はTLSレジスタがないものとして、アドレス0xFFFF0FF0を直接参照していた。
この部分はTLSレジスタをサポートする場合とそうでない場合で切り分けられている。"ARCH_ARM_HAVE_TLS_REGISTER=true"とすれば、TLSレジスタを使用してくれる。…というか、device/samsung/crespo/BoardConfigCommon.mkやdevice/moto/wingray/BoardConfig.mkを見れば、ちゃんと指定されている。もっとちゃんと調べろよ俺…
generic(goldfish)環境のBoardConfig.mkはdevice/genericではなくbuild/target/board/genericにあるので、これに追加すればよい。またはmake時に直接指定してやればよい。

build/target/board/generic/BoardConfig.mkに追加する場合

ARCH_ARM_HAVE_TLS_REGISTER := true

直接指定する場合

$ make ARCH_ARM_HAVE_TLS_REGISTER=true -jN

これによって、無事Emulatorは起動した。この設定の影響を直接受けるのはbionic/libc, bionic/linkerのようだが、他にもあるかもしれない(そこまでは調査してない)。

なお、goldfish-3.0が古いと他にも問題が出てくるが、最新版を使うかパッチを適用すれば解決する。…するはず。未確認。

しかし、こんな既出っぽい件で随分手間をかけてしまった。世のAndroid開発者にとっては、こんなのは簡単な、躓くことのない部類なんですかねぇ?