ldd for Android コマンドを作る(とりあえず)

前々回のブログ記事「ldd for Android: lddコマンドのようにライブラリ情報を表示」で変更を加えたlinkerを使って、リンクしているシェアードライブラリを表示するシェルスクリプトのlddコマンドを作ってみました。

[作ったlddコマンドの実行例]

$ ldd /system/bin/date                            
	liblog.so => /system/lib/liblog.so
	libc.so => /system/lib/libc.so
	libstdc++.so => /system/lib/libstdc++.so
	libm.so => /system/lib/libm.so
	libcutils.so => /system/lib/libcutils.so
	libusbhost.so => /system/lib/libusbhost.so
$ ldd /system/bin/bluetoothd                      
	libbluetoothd.so => /system/lib/libbluetoothd.so
	libbluetooth.so => /system/lib/libbluetooth.so
	libcutils.so => /system/lib/libcutils.so
	liblog.so => /system/lib/liblog.so
	libc.so => /system/lib/libc.so
	libstdc++.so => /system/lib/libstdc++.so
	libm.so => /system/lib/libm.so
	libbtio.so => /system/lib/libbtio.so
	libglib.so => /system/lib/libglib.so
	libdbus.so => /system/lib/libdbus.so
$ ldd /system/bin/gdbserver                       
Command is not dynamically linked.

以下、作ったコマンドです。

[/system/bin/ldd(シェルスクリプト)]
http://otake.knowd2.com/drupal-rotake/download/Android/ldd
[/system/bin/link02(Android4.0.3のリンカのソースlinker.cを変更して生成したバイナリ)]
http://otake.knowd2.com/drupal-rotake/download/Android/link02
[Android4.0.3のlinker.cの変更箇所]
http://otake.knowd2.com/drupal-rotake/download/Android/patch-linker.c

本来はlinker.cを書き換えて、バイナリコマンドとして「ldd コマンド名」のようにして実行できるようにしたかったのですが、それにはカーネルがコマンドをロードして引数としてELFの情報がlinkerに渡される代わりに、linkerの中でそれと同じ操作をする必要があり、作業に時間がかかりそうなのでちょっと反則的な方法ですがとりあえず作ってみました。(いずれ、本来のかたちで作ってみようと思います)
/system/bin/linkerを置き換えることなく、それとは別のコマンド(/system/bin/link02)として実行するために、ELFフォーマットのコマンドの中の.interpセクションに入っているダイナミックリンカのパス名をsedコマンドで書き換えて実行するシェルスクリプト(/system/bin/ldd)にしました。書き換えたコマンドは/data/local/tmpにコピーして実行するようにしています。(linkerを置き換えて、そのまま使うのであればこのような"変なこと"をする必要はないのですが、別コマンドにすれば、安心して実験しやすいので。)
lddシェルスクリプトの中で使っている、cut, strings, grep, basename, sedといったコマンドはbusyboxをインストールして使っています。 → こちらこちらを参照

patch-linker.cはdiffコマンドで、デフォルトのnormal形式で作ってます。

$ diff linker.c linker.c.new > patch-linker.c

linkerのソースコードlinker.cを変更するには次のようにします。

$ cp linker.c linker.c.orig
$ patch linker.c patch-linker.c