2011年02月08日

Androidのdebuggerd

Androidのポーティング作業や、NDKでネイティブライブラリの開発をしている方は、ネイティブのプログラムの部分で不正なメモリアクセスなどで例外が発生したときに、logcatでのログに、その例外を起こしたプロセスのレジスタやスタックがダンプされるのを見ることがあると思います。

これは一体どのような仕組みでこのダンプがログに出ているのでしょうか?

(English version of this page)



ダンプの例

以前書いたページでSIGBUS(バスエラー)の例外が発生した時のログです。

I/DEBUG   (  543): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG   (  543): Build fingerprint: 'generic/generic/generic/:Donut/Donut/eng.koba.20090827.140821:eng/test-keys'
I/DEBUG   (  543): pid: 590, tid: 590  >>> zygote <<<
I/DEBUG   (  543): signal 7 (SIGBUS), fault addr 00000000
I/DEBUG   (  543):  r0 00001412  r1 4104bbe4  r2 4104bbdc  r3 4104bbe4
I/DEBUG   (  543):  r4 41748086  r5 4104bb94  r6 bef614e8  r7 ad00e640
I/DEBUG   (  543):  r8 000012ad  r9 4104bbdc  10 4104bb84  fp 00000000
I/DEBUG   (  543):  ip 000000ad  sp bef614a8  lr ad01071c  pc ad01119c  cpsr 20000010
I/DEBUG   (  543):          #00  pc 0001119c  /system/lib/libdvm.so
I/DEBUG   (  543):          #01  pc 00017d90  /system/lib/libdvm.so
I/DEBUG   (  543):          #02  pc 000177d4  /system/lib/libdvm.so
I/DEBUG   (  543):          #03  pc 00052974  /system/lib/libdvm.so
I/DEBUG   (  543):          #04  pc 00052992  /system/lib/libdvm.so

debuggerd

このログを実際に出しているのはdebuggerdというプロセスです。

system/core/debuggerd

このプロセスは起動時にinitから起動され、"android:debuggerd"というUNIX domain socketを生成して接続されるのを待っています。

接続されると、ソケットにtid(gettidシステムコールで得られるスレッドID)が書き込まれることになっているので、そのtidに対して、ptraceシステムコールを使ってアタッチします。

つまり、例外を起こして瀕死の状態にあるプロセスを停止状態にします。さらに、そのプロセスのレジスタやメモリをptraceシステムコールを駆使して読み出してログにダンプします。

system/core/debuggerd/debuggerd.c

このソースを見るとptraceシステムコールの使い方が勉強できそうです。

ダイナミックリンカ

さて、debuggerdの開いた"android:debuggerd"というsocketに接続するのはどこでどうやっているのでしょうか。

その部分のソースはここにあります。

bionic/linker/debugger.c

void debugger_init()
{
    signal(SIGILL, debugger_signal_handler);
    signal(SIGABRT, debugger_signal_handler);
    signal(SIGBUS, debugger_signal_handler);
    signal(SIGFPE, debugger_signal_handler);
    signal(SIGSEGV, debugger_signal_handler);
    signal(SIGSTKFLT, debugger_signal_handler);
    signal(SIGPIPE, debugger_signal_handler);
}

これはbionic/linker/debugger.c の最後の部分です。これらのsignalのハンドラが登録されています。debugger_signal_handlerでdebuggerdの開いた"android:debuggerd"というsocketに接続しています。

このソースは実はbionicのダイナミックリンカの一部です。

ダイナミックリンクしているプログラムはmain関数が実行される前にまずダイナミックリンカが動作してメモリ上にダイナミックリンクライブラリをマッピングするわけですが、その時にこの関数debugger_initを呼んでいます。

これはなかなかうまいやり方だと思います。

つまり、ダイナミックリンクしているプログラムは全て自動的にdebuggerdと接続してデバッグダンプする機能を備えることになります。



トラックバックURL

トラックバック一覧

1. [Exploit][Android]Androidエミュレータで脆弱性CVE-2010-1119のExploitコードを実証してみる  [ 思い立ったら書く日記 ]   2011年05月08日 18:20
2011 年 3 月にExploits Database にて、Android が採用している WebKit の脆弱性(CVE-2010-1119)の Exploit コードが公開されました。実際に Android エミュレータで、この Exploit コードを実証してみました。この日記では、Exploit コードの実証結果と実証までの経緯を
2. [android]Android NDKでfork, execは使ってはダメ  [ 組み込みの人。 ]   2011年06月05日 10:56
Android NDKでfork, execのシステムコールは使ってはダメという話。 D/Zygote ( 909): Process 7668 terminated by signal (11) - android-ndk | Google Groups NDKの中でforkとexecを使って子プロセスを起動してデーモン的なプログラムを動かした。しばらくうまく動いてい

コメントする

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

QRコード
QRコード