1 Wrapper Android C++ method into a C function:
1
2
3
4
5
6
7
8
9
external / bluetooth / bluedroid $ cat bta / sys / dump_stack . cpp
#include <utils/CallStack.h>
using namespace android ;
extern "C" void dump_stack_android ( void )
{
CallStack stack ;
stack . update ();
stack . dump ();
}
2 Call this C function from target place:
1
2
3
4
5
6
7
diff -- git a / bta / dm / bta_dm_act . c b / bta / dm / bta_dm_act . c
+ extern void dump_stack_android ( void );
static void bta_dm_adjust_roles ( BOOLEAN delay_role_switch )
{
+ dump_stack_android ();
if ( bta_dm_cb . device_list . count )
{
3 Add library libutils as dependency in LOCAL_SHARED_LIBRARIES,
1
2
3
4
5
6
7
8
diff -- git a / main / Android . mk b / main / Android . mk
LOCAL_SRC_FILES += \
+ .. / bta / sys / dump_stack . cpp \
.. / udrv / ulinux / uipc . c
LOCAL_SHARED_LIBRARIES := \
libcutils \
+ libutils \
I met a ld error as:
1
error: undefined reference to ' android :: CallStack :: CallStack () '
It turned out that I added the libutils dependency into a static library libbt-brcm_bta, which can not solve this dynamic symbol at link time
Move the dependency to dynamic library bluetooth.default.so solved the problem.
The final result on running board is:
1
2
3
4
5
6
7
8
9
10
11
12
root @ android: / # logcat - v time | grep CallStack &
05 - 09 21 : 01 : 57.666 D / CallStack ( 2133 ) : ( null ) # 00 pc 0005 c444 / system / lib / hw / bluetooth . default . so ( dump_stack_android + 15 )
05 - 09 21 : 01 : 57.666 D / CallStack ( 2133 ) : ( null ) # 01 pc 0004 ddb2 / system / lib / hw / bluetooth . default . so
05 - 09 21 : 01 : 57.666 D / CallStack ( 2133 ) : ( null ) # 02 pc 0004 c310 / system / lib / hw / bluetooth . default . so ( bta_sys_conn_close + 27 )
05 - 09 21 : 01 : 57.666 D / CallStack ( 2133 ) : ( null ) # 03 pc 000577 d4 / system / lib / hw / bluetooth . default . so ( bta_av_str_closed + 115 )
05 - 09 21 : 01 : 57.666 D / CallStack ( 2133 ) : ( null ) # 04 pc 0004705 e / system / lib / hw / bluetooth . default . so ( bta_av_ssm_execute + 269 )
05 - 09 21 : 01 : 57.666 D / CallStack ( 2133 ) : ( null ) # 05 pc 00046f 1 c / system / lib / hw / bluetooth . default . so ( bta_av_hdl_event + 159 )
05 - 09 21 : 01 : 57.666 D / CallStack ( 2133 ) : ( null ) # 06 pc 0004 bf02 / system / lib / hw / bluetooth . default . so ( bta_sys_event + 49 )
05 - 09 21 : 01 : 57.666 D / CallStack ( 2133 ) : ( null ) # 07 pc 00074 b70 / system / lib / hw / bluetooth . default . so ( btu_task + 559 )
05 - 09 21 : 01 : 57.666 D / CallStack ( 2133 ) : ( null ) # 08 pc 000427 84 / system / lib / hw / bluetooth . default . so ( gki_task_entry + 91 )
05 - 09 21 : 01 : 57.666 D / CallStack ( 2133 ) : ( null ) # 09 pc 0000e3 d8 / system / lib / libc . so ( __thread_entry + 72 )
05 - 09 21 : 01 : 57.666 D / CallStack ( 2133 ) : ( null ) # 10 pc 0000 dac4 / system / lib / libc . so ( pthread_create + 160 )
This result can be verified as the same as addr2line:
1
2
$ arm - eabi - addr2line - e .. / .. / .. / out / target / product / bg2ct_dmp_emmc / symbols / system / lib / hw / bluetooth . default . so 0004 c310
external / bluetooth / bluedroid / bta / . / sys / bta_sys_conn . c: 236
Update: Peek stack of a running process
Android debuggerd can be used to dump a running process’s stack:
1
2
3
4
5
6
7
8
9
10
11
12
13
ALOGD ( "peeking stack of process %d \n " , pid );
kill ( pid , SIGSTOP );
ptrace ( PTRACE_ATTACH , pid , 0 , 0 );
char * tombstone_path = engrave_tombstone ( pid ,
pid ,
0 /*no signal*/ ,
true /*dump_sibling_threads*/ ,
false /*not quiet*/ ,
& detach_failed ,
& total_sleep_time_usec );
ptrace ( PTRACE_DETACH , pid , 0 , 0 );
kill ( pid , SIGCONT );
The stack of main thread of the process will shown in logcat, and all others will be in the tombstone file.
The target process will resume to execution right after the dump stack finished.
This is useful when debugging some real time issues.