1.Java中:
Log.e(“dump_test”,Log.getStackTraceString(new Throwable()));
2.C++中:
<1>.test.cpp
#include
#include
void dumping_callstack(){
android::CallStack stack;
//getpid()和gettid()效果一样
//stack.update(2,getpid());
//stack.update(2,gettid());
stack.update();
//输出到printf
stack.dump(1);
//输出到logcat
stack.log("dump_test");
//可以设置第2、3个参数
//stack.log("Dumping Stack",ANDROID_LOG_ERROR ,"123 ");
}
void func1(){
dumping_callstack();
}
void func2(){
func1();
}
void func3(){
func2();
}
int main(){
ALOGE("main_test------------------>");
func3();
}
<2>.Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := test.cpp
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := test
LOCAL_SHARED_LIBRARIES += libcutils libutils
include $(BUILD_EXECUTABLE)
3.C中:
<1>.创建callstack.cpp
#include
extern "C" void dumping_callstack();
void dumping_callstack(){
android::CallStack stack;
stack.update();
stack.log(“dump_test“);
}
<2>.创建callstack.h
void dumping_callstack();
<3>.测试test.c
#include "callstack.h"
static ssize_t out_write(){
dumping_callstack();
}
<4>.Anroid.mk中添加到编译选项:callstack.cpp及库
LOCAL_SHARED_LIBRARIES := libcutils libutils
LOCAL_SRC_FILES := callstack.cpp
4.Kernel中:
#include
printk(KERN_ERR "dump_stack start: %s() %d \n",__FUNCTION__,__LINE__);
dump_stack();
.......
printk(KERN_ERR "dump_stack stop: %s() %d \n",__FUNCTION__,__LINE__);
根据dump stack的log位置加printk()。
测试:
# adb logcat | grep dump_test
打印C堆栈另一种方法
这里需要注意的是,为解决链接问题,最好使用dlopen方式,查找需要用到的接口再直接调用,这样会比较简单。如下为相关的实现代码,只需要在要打印的文件中插入此部分代码,然后调用getCallStack()即可,无需包含太多的头文件和修改Android.mk文件
#define MAX_DEPTH 31
#define MAX_BACKTRACE_LINE_LENGTH 800
#define PATH "/system/lib/libcorkscrew.so"
typedef ssize_t (*unwindFn)(backtrace_frame_t*, size_t, size_t);
typedef void (*unwindSymbFn)(const backtrace_frame_t*, size_t, backtrace_symbol_t*);
typedef void (*unwindSymbFreeFn)(backtrace_symbol_t*, size_t);
static void *gHandle = NULL;
static int getCallStack(void){
ssize_t i = 0;
ssize_t result = 0;
ssize_t count;
backtrace_frame_t mStack[MAX_DEPTH];
backtrace_symbol_t symbols[MAX_DEPTH];
unwindFn unwind_backtrace = NULL;
unwindSymbFn get_backtrace_symbols = NULL;
unwindSymbFreeFn free_backtrace_symbols = NULL;
// open the so.
if(gHandle == NULL) gHandle = dlopen(PATH, RTLD_NOW);
// get the interface for unwind and symbol analyse
if(gHandle != NULL) unwind_backtrace = (unwindFn)dlsym(gHandle, "unwind_backtrace");
if(gHandle != NULL) get_backtrace_symbols = (unwindSymbFn)dlsym(gHandle, "get_backtrace_symbols");
if(gHandle != NULL) free_backtrace_symbols = (unwindSymbFreeFn)dlsym(gHandle, "free_backtrace_symbols");
if(!gHandle ||!unwind_backtrace ||!get_backtrace_symbols || !free_backtrace_symbols ){
ALOGE("Error! cannot get unwind info: handle:%p %p %p %p",
gHandle, unwind_backtrace, get_backtrace_symbols, free_backtrace_symbols );
return result;
}
count= unwind_backtrace(mStack, 1, MAX_DEPTH);
get_backtrace_symbols(mStack, count, symbols);
for (i = 0; i < count; i++) {
char line[MAX_BACKTRACE_LINE_LENGTH];
const char* mapName = symbols[i].map_name ? symbols[i].map_name : "";
const char* symbolName =symbols[i].demangled_name ? symbols[i].demangled_name : symbols[i].symbol_name;
size_t fieldWidth = (MAX_BACKTRACE_LINE_LENGTH - 80) / 2;
if (symbolName) {
uint32_t pc_offset = symbols[i].relative_pc - symbols[i].relative_symbol_addr;
if (pc_offset) {
snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s (%.*s+%u)",
i, symbols[i].relative_pc, fieldWidth, mapName,
fieldWidth, symbolName, pc_offset);
} else {
snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s (%.*s)",
i, symbols[i].relative_pc, fieldWidth, mapName,
ieldWidth, symbolName);
}
} else {
snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s",
i, symbols[i].relative_pc, fieldWidth, mapName);
}
ALOGD("%s", line);
}
free_backtrace_symbols(symbols, count);
return result;
}
https://blog.csdn.net/q1183345443/article/details/82999385