Thursday, May 12, 2011

debuggerd of Android

If you port Android to your system or develop native libraries using NDK, you have a experience to see debug dump on logcat. That shows CPU registers and stack dumps of the process caused memory fault or other exception.

Who and how does the debug dump generate?
(Japanese version)


Example of debug dump


This is a log when the exception of SIGBUS (bus error) occurred on the page written before (in Japanese).

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

It is a process named debuggerd that has actually given this log. system/core/debuggerd It is started from init at boot time, and this process generates UNIX domain socket "Android:debuggerd" and waits to be connected. Because tid (thread ID obtained by the gettid system call) is supposed to be written in the socket when connected, the ptrace system call is used and attached for the tid. In a word, the process that caused the exception and dropped to the state of the neardeath, is put into the halt condition by debuggerd. In addition, the register and the memory of the process are read by the ptrace system call and it dumps it to the log. system/core/debuggerd/debuggerd.c I think this is good example to learn how to use the ptrace system call.

dynamic linker

Well, What part is there connecting it with socket "Android:debuggerd" where debuggerd opens? and how? The source in the part is here. 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);
}
This is the last part of bionic/linker/debugger.c. The handler of these signal is registered here. It connects it with socket "Android:debuggerd" where debuggerd opens by debugger_signal_handler. In fact, this source is a part of the dynamic linker of bionic. At first a dynamic linker works before main function is carried out. Then the dynamic linker maps dynamic link libraries on memory. At the time, it calls this function(debugger_init). In other words, all programs which is dynamic linked have functionality to connect to debuggerd and generate debug dump, automatically and implicitly. I think that this is a very good and smart way.

Related pages

How to examine the problem occurrence point on the source code from a debug dump of Android (in Japanese)

No comments:

Post a Comment