2011年10月05日

アプリをたくさんインストールするとndk-gdbが使えなくなる

NDKを使用してネイティブライブラリをビルドして組み込んだアプリケーションは、ndk-gdbを使ってデバッグすることができます。しかし、ndk-gdbがエラーで起動できないという場面に遭遇し、調べてみると、なんとアプリをたくさんインストールしてある端末でそのようなことが発生するということがわかりました。以下はその詳細です。



なぜかある特定の端末でだけndk-gdbが起動に失敗します。動かしているのはNDKのサンプルプログラムのSanAngelesです。

$ ../../ndk-gdb --start
ERROR: Could not extract package's data directory. Are you sure that
       your installed application is debuggable?

ndk-gdbはshell scriptなので、その中を見てみるとどうもrun-asコマンドのところでエラーになっているらしい。切り分けのためにSanAngelesを手で起動した状態で、adbでログインしてrun-asを試すと

$ adb shell
$ ps

   ....
app_140   4347  2577  184108 19724 ffffffff 00000000 S com.example.SanAngeles
shell     4378  4279  964    340   00000000 afd0b4ac R ps
$
$ run-as com.example.SanAngeles /system/bin/sh -c pwd
run-as: Package 'com.example.SanAngeles' is unknown

やはり run-asがエラーを返しています。

他のうまくいく端末で同じことをすると

$ run-as com.example.SanAngeles /system/bin/sh -c pwd
/data/data/com.example.SanAngeles

これが想定している応答です。

run-asコマンドのソースを見ると、/data/system/packages.list というファイルをopenしてreadしています。このファイルはテキストファイルで、各アプリケーションのパッケージ名、UID、デバッグ可否、ディレクトリが書かれています。run-asコマンドはこのファイルからそのアプリケーションがデバッグを許可しているかを調べ、許可している場合のみそのアプリケーションと同じUIDで指定のコマンドを実行するわけです。

adb shell cat /data/system/packages.list | grep SanAngeles

とすると com.example.SanAngelesも登録されているのがわかりました。

よくよくソースを見ると、run-asコマンドは一回のreadでファイル全体をバッファに読み込んで処理するようになっていますが、そのバッファを固定的に8192バイトしかとっていません。つまりファイルの先頭の8KB分しか読まれない!!

うまくいかない端末での/data/system/packages.list はサイズが13KBくらいありました。

確かに、run-asで /data/system/packages.list の最初のほうのパッケージ名を指定すると、unknown packageというエラーでなく、not debuggable というエラーに変わりました。

つまりrun-asが想定通りに動かないのはバッファのサイズが足りないというコーディングミスによるもののようです。

そのため、/data/system/packages.listのサイズが8KBよりも小さくなるように不要不急なアプリを全てアンインストールしてから、デバッグ対象のプログラムをインストールしたらrun-asコマンドが効くようになり、gdb-ndkを起動することができるようになりました。

最後にインストールしたアプリがこのpackages.listの最後に追加されるというわけではありません。(このファイルを書き出しているところのソースは調べていませんが、メモリ内にハッシュテーブルを作った後にそれをダンプしているような感じです。)そのため、packages.listが8KBを超えた状態では、アプリをインストール、アンインストールすることでndk-gdbが使えたり、使えなかったりという不可思議な状態になると思います。

追記

確認したのはAndroid 2.3.4_r1のソースです。

masterのソースではPACKAGES_LIST_BUFFER_SIZEは8192バイトから65536バイトに拡張されていました。

system/core/run-as/package.c



トラックバックURL

コメントする

名前
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード