(android 源码下开发应用程序) 如何在 Android 各 level ( 包含 user space 與 kernel space ) 使用dump call stack的方法
2017-09-22 18:51
721 查看
http://janbarry0914.blogspot.com/2014/07/androiddump-call-stack.html
了解 Android 各 level ( UI, framework 與 HAL) 與 kernel 間, 如何印出 call stack, 方便追 code 與 debug
[文章目錄]
kernel call stack
Android Java layer
Android framework ( written by c++)
Android HAL ( written by c )
Call
Stack 沒有出現function name
如果想知道call stack,也就是說, 我們想知道是誰call到func_foo(). 此時,我們可以利用 dump_stack(),放在你想dump back trace的地方就OK囉.
Java layer call stack
在Java檔案, 可以使用下述方法得到dump call stack
在C/C++ 檔案, Android 已經有寫了frameworks/native/libs/utils/CallStack.cpp 供我們使用
如果你所使用是Android 4.4 之後
請改用
在Android.mk 記得要加
由於C去call C++需要做一些宣告, 所以將它獨立出來方便使用(dump_stack.cpp與 dump_stack.h)
dump_stack.h
dump_stack.cpp
如果你所使用是Android 4.4 之後
請改用
同樣地, Android.mk也需要修改
接下來在C file中要使用時只要
[ Call Stack 沒有出現 function name]
有時我們會發現在C++ 或 C 語言中使用 CallStack , 在 call dump 中並沒有出現 function name
我們追一下 CallStack 是如何被實作
先回顧一下 CallStack 是如何被使用 (以 Android 4.4 為例)
先看一下 update( ) function 的定義 ( it is under system/core/include/utils/CallStack.h)
所以透過 update( ) function, 我們可以設定想看哪一個 thread 並 dump 出多少層的 call stack, 如果都沒寫, 就是以當前的 thread 去做 call stack dump, update( ) function 會將實際可以 dump 多少的 frame 給抓出來, 其中 frame 的數量記錄在 mCount 變數, 各 frame 的資訊則記錄在 mStack[ ] 裡面, 接下來再透過 log( ) function 把 call stack 裡的 program
counter 所記載的記憶體位址去把相對應的 function name 給解析出來.
看一下 get_backtrace_symbols( ) 在做些什麼
這是因為它是使用 dladdr() 去讀取該share lib的 dynamic symbol 而獲取 function name
(http://stackoverflow.com/questions/11731229/dladdr-doesnt-return-the-function-name
)
但是如果該 function 是宣告成 static, 該 function name 就不會出現在 dynamic symbol 裡 (你可以使用 arm-linux-androideabi-nm -D xxxx.so
| grep the_function_name , 如果沒有出現, 就表示該 funciton name 並不在 dynamic symbol 裡), 遇到這情況就只好使用 add2line 指令去讀 out folder 下的 symbol 了, 各位可以參考我另一篇文章http://janbarry0914.blogspot.tw/2011/07/android-crash-tombstone.html
. 感謝.
dump call stack
[文章重點]
了解 Android 各 level ( UI, framework 與 HAL) 與 kernel 間, 如何印出 call stack, 方便追 code 與 debug[文章目錄]
kernel call stack
Android Java layer
Android framework ( written by c++)
Android HAL ( written by c )
Call
Stack 沒有出現function name
kernel call stack
如果想知道call stack,也就是說, 我們想知道是誰call到func_foo(). 此時,我們可以利用 dump_stack(),放在你想dump back trace的地方就OK囉.void func_foo(void){ int a=3; ... dump_stack(); ... } |
在Java檔案, 可以使用下述方法得到dump call stack
public void foo(boolean state, int flags) { ... Log.d(TAG,"xxxx", new Throwable()); ... } |
C++ layer call stack
在C/C++ 檔案, Android 已經有寫了frameworks/native/libs/utils/CallStack.cpp 供我們使用#include <utils/CallStack.h> ... void foo(void) { ... android::CallStack stack; stack.update(); stack.dump("XXX"); ... } |
請改用
#include <utils/CallStack.h> ... void foo(void) { ... android::CallStack stack; stack.update( ); stack.log("XXX"); ... } |
LOCAL_SHARED_LIBRARIES += libutils |
C layer call stack
由於C去call C++需要做一些宣告, 所以將它獨立出來方便使用(dump_stack.cpp與 dump_stack.h)dump_stack.h
#ifdef __cplusplus extern "C" { #endif void dump_stack_android(void); #ifdef __cplusplus } #endif |
#include "dump_stack.h" #include <utils/CallStack.h> using namespace android; extern "C"{ void dump_stack_android(void) { CallStack stack; stack.update(); stack.dump("XXX"); } } |
請改用
#include "dump_stack.h" #include <utils/CallStack.h> using namespace android; extern "C"{ void dump_stack_android(void) { CallStack stack; stack.update(); stack.log("XXX"); } } |
LOCAL_SRC_FILES := \ …... \ dump_stack.cpp LOCAL_SHARED_LIBRARIES += libutils |
extern void dump_stack_android(); void function_a() { … dump_stack_android(); … } |
有時我們會發現在C++ 或 C 語言中使用 CallStack , 在 call dump 中並沒有出現 function name
D/XXX( 147): #00 pc 00001b90 /system/lib/hw/audio.primary.mrvl.so (dump_stack_android+19) D/XXX( 147): #01 pc 00004b56 /system/lib/hw/audio.primary.mrvl.so D/XXX( 147): #02 pc 0001f828 /system/lib/libaudioflinger.so D/XXX( 147): #03 pc 00019138 /system/lib/libaudioflinger.so D/XXX( 147): #04 pc 00023bb6 /system/lib/libaudioflinger.so D/XXX( 147): #05 pc 0000e9fe /system/lib/libutils.so (android::Thread::_threadLoop(void*)+213) D/XXX( 147): #06 pc 0000e530 /system/lib/libutils.so D/XXX( 147): #07 pc 0000d208 /system/lib/libc.so (__thread_entry+72) D/XXX( 147): #08 pc 0000d3a4 /system/lib/libc.so (pthread_create+240) |
先回顧一下 CallStack 是如何被使用 (以 Android 4.4 為例)
CallStack stack; stack.update(); stack.log();
先看一下 update( ) function 的定義 ( it is under system/core/include/utils/CallStack.h)
// Immediately collect the stack traces for the specified thread. void update(int32_t ignoreDepth=1, int32_t maxDepth=MAX_DEPTH, pid_t tid=CURRENT_THREAD);
所以透過 update( ) function, 我們可以設定想看哪一個 thread 並 dump 出多少層的 call stack, 如果都沒寫, 就是以當前的 thread 去做 call stack dump, update( ) function 會將實際可以 dump 多少的 frame 給抓出來, 其中 frame 的數量記錄在 mCount 變數, 各 frame 的資訊則記錄在 mStack[ ] 裡面, 接下來再透過 log( ) function 把 call stack 裡的 program
counter 所記載的記憶體位址去把相對應的 function name 給解析出來.
log( ) |--> print( ) |--> get_backtrace_symbols( )
看一下 get_backtrace_symbols( ) 在做些什麼
void get_backtrace_symbols(const backtrace_frame_t* backtrace, size_t frames, backtrace_symbol_t* backtrace_symbols) { ... for (size_t i = 0; i < frames; i++) { ... Dl_info info; if (dladdr((const void*)frame->absolute_pc, &info) && info.dli_sname) { symbol->relative_symbol_addr = (uintptr_t)info.dli_saddr - (uintptr_t)info.dli_fbase; symbol->symbol_name = strdup(info.dli_sname); symbol->demangled_name = demangle_symbol_name(symbol->symbol_name); } ... } release_my_map_info_list(milist); } |
(http://stackoverflow.com/questions/11731229/dladdr-doesnt-return-the-function-name
)
但是如果該 function 是宣告成 static, 該 function name 就不會出現在 dynamic symbol 裡 (你可以使用 arm-linux-androideabi-nm -D xxxx.so
| grep the_function_name , 如果沒有出現, 就表示該 funciton name 並不在 dynamic symbol 裡), 遇到這情況就只好使用 add2line 指令去讀 out folder 下的 symbol 了, 各位可以參考我另一篇文章http://janbarry0914.blogspot.tw/2011/07/android-crash-tombstone.html
. 感謝.
相关文章推荐
- (android 源码下开发应用程序) 如何在 Android 各 level ( 包含 user space 與 kernel space ) 使用dump call stack的方法
- Android开发教程之Fragment定义、创建与使用方法详解【包含Activity通讯,事务执行等】
- Android入门之使用eclipse进行源码开发的方法
- mars老师[Android开发视频教学].01_16_SQLite使用方法 视频源码
- 如何使用Android Studio开发/调试Android源码
- Android网络开发中如何使用JSON进行网络通信---Android JSON数据通讯方法解析
- 如何使用Android Studio开发/调试Android源码
- (转)如何使用Eclipse开发Android源码
- 如何使用Android Studio开发/调试Android源码
- 如何使用Eclipse开发Android源码
- 如何使用Android Studio开发/调试Android源码
- mars老师[Android开发视频教学].01_16_SQLite使用方法 视频源码
- Android网络开发中如何使用JSON进行网络通信---Android_JSON数据通讯方法解析
- Android网络开发中如何使用JSON进行网络通信---Android JSON数据通讯方法解析
- 如何使用Android Studio开发/调试Android源码
- 如何使用Android Studio开发/调试Android源码
- 如何使用Android Studio开发/调试Android源码
- 如何使用Android中hide的类和方法进行开发?
- 【转发】如何使用Android Studio开发/调试Android源码
- 如何使用Android Studio开发/调试Android源码