http://janbarry0914.blogspot.com/2014/07/androiddump-call-stack.html

dump call stack

[文章重點]

了解 Android 各 level ( UI, framework 與 HAL) 與 kernel 間, 如何印出 call stack, 方便追 code 與 debug
[文章目錄]
  1. kernel call stack
  2. Android Java layer
  3. Android framework ( written by c++)
  4. Android HAL ( written by c )
  5. 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 layer call 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");

...
}


如果你所使用是Android 4.4 之後
請改用


#include <utils/CallStack.h>
...
void foo(void) {
...
   android::CallStack stack;
   stack.update( );
   stack.log("XXX");

...
}

在Android.mk 記得要加


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


dump_stack.cpp


#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");
 }
}


如果你所使用是Android 4.4 之後
請改用


#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");
 }
}


同樣地, Android.mk也需要修改


LOCAL_SRC_FILES := \
        …... \
        dump_stack.cpp

LOCAL_SHARED_LIBRARIES += libutils


接下來在C file中要使用時只要


extern void dump_stack_android();

void function_a()
{
 …
 dump_stack_android();
 …
}


[ Call Stack 沒有出現 function name]
有時我們會發現在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 是如何被實作
先回顧一下 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);
}


這是因為它是使用 dladdr() 去讀取該share lib的 dynamic symbol 而獲取 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的方法的更多相关文章

  1. 在Android源码下编译jni所需要知道的事~

    以下只是自己的一些总结,欢迎讨论 通过NDK编译jni网上有很多例子,在这我只总结在Android源码下编译 1.android源码环境下编译so包,编出来的.so的包前面不会自动给添加lib,NDK ...

  2. 【转】Android 源码下利用jni编译自己的项目(参考系统development/samples/SimpleJNI)

    原文网址:http://blog.csdn.net/qiuxiaolong007/article/details/7860481 记于正文前:环境是ubuntu10.10,android 源码是2.0 ...

  3. Android源码分析(十二)-----Android源码中如何自定义TextView实现滚动效果

    一:如何自定义TextView实现滚动效果 继承TextView基类 重写构造方法 修改isFocused()方法,获取焦点. /* * Copyright (C) 2015 The Android ...

  4. Android源码下编译APK步骤

    1.进入android源码目录下的build下执行:source envsetup.sh 后继续在该路径下执行lunch. 2.编写完成工程 3.编写Android.mk文件,放入工程目录下     ...

  5. S5P4418开发板android源码下uboot和内核缺省文件的配置

    uboot 需要配置缺省文件,进入解压的源码目录 android,然后进入 u-boot 目录,如下图所示.如上图所示,如果是 1G 核心板,则使用“cp nsih-1G16b-4418.txt ns ...

  6. Android源码分析(十三)----SystemUI下拉状态栏如何添加快捷开关

    一:如何添加快捷开关 源码路径:frameworks/base/packages/SystemUI/res/values/config.xml 添加headset快捷开关,参考如下修改. Index: ...

  7. 【转】模块编译Android源码方法

    原文网址:http://blog.csdn.net/androidlover1991/article/details/17014055 实际开发中,并不需要每次都编译所有源代码,只需要编译自己修改的模 ...

  8. Android源码解析系列

    转载请标明出处:一片枫叶的专栏 知乎上看了一篇非常不错的博文:有没有必要阅读Android源码 看完之后痛定思过,平时所学往往是知其然然不知其所以然,所以为了更好的深入Android体系,决定学习an ...

  9. Android源码分析(八)-----系统启动流程&IPC简述

    一 :系统启动流程图 从下往上依次启动linux kernel -->zygote-->SystemServer-->NativeService-->AndroidServic ...

随机推荐

  1. 树莓派2 安装mono3.0运行mvc4

    sudo apt-get updatesudo apt-get upgradesudo apt-get mono-completewget -c http://www.linuxdot.net/dow ...

  2. jquery upload

    http://blueimp.github.io/jQuery-File-Upload/ https://github.com/blueimp/jQuery-File-Upload/wiki Back ...

  3. windows10 Build 10074版本上手体验(二)

  4. 部分视图调用方法总结(Action 、 RenderAction 、 Partial 、 RenderPartial)

    Action . RenderAction . Partial . RenderPartial 1.Action . RenderAction Action 方法以字符串的形式返回子视图,可以直接被呈 ...

  5. http://www.itpub.net/thread-1778530-1-1.html

    http://www.itpub.net/thread-1778530-1-1.html

  6. SPRING IN ACTION 第4版笔记-第五章BUILDING SPRING WEB APPLICATIONS-005-以path parameters的形式给action传参数(value=“{}”、@PathVariable)

    一 1.以path parameters的形式给action传参数 @Test public void testSpittle() throws Exception { Spittle expecte ...

  7. ANDROID_MARS学习笔记_S02_002_Date\TimePicker

    一.文档用法 1.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" ...

  8. 【HDOJ】2430 Beans

    这题目用线段树超时了,其实也差不多应该超时.10^6大数据量.看了一下网上的解法是单调队列.大概了解了一下,是个挺有意思的数据结构.首先,需要求满足0<=(S[r]-S[l])%p<=k时 ...

  9. 【HDOJ】2062 Subset sequence

    这道题目非常好,饶了点儿圈子.我的思路是,先按照组排列.例如,1            2           31 2         2 1        3 11 2 3      2 1 3  ...

  10. 错误信息:A TCP error (10013: 以一种访问权限不允许的方式做了一个访问套接字的尝试。) occurred while listening on IP Endpoint=192.168.1.18:8002.

    百度之后,知道这个原因是端口已经被其他进程打开了 使用cmd命令,查看8002端口被哪一个程序占用了 C:\Windows\System32>netstat -ano | find " ...