NDK打印调用堆栈_打印堆栈信息命令

虽然android源码里有android::CallStack用来打印堆栈,但是NDK里面并没有包含它,所以不能直接调用它,所以要尝试用动态调用的方式来实现。

我测试的手机是安卓8.1.0版本,android::CallStack位于/system/lib/libutils.so库中,使用ida pro打开libutils.so,找到
android::CallStack::CallStack函数

.text:0000996C ; _DWORD __fastcall android::CallStack::CallStack(android::CallStack *__hidden this, const char *, int)
.text:0000996C                 EXPORT _ZN7android9CallStackC2EPKci
.text:0000996C _ZN7android9CallStackC2EPKci            ; DATA XREF: LOAD:0000158C↑o
.text:0000996C                                         ; LOAD:00001CDC↑o

可以看到函数的导出符号为
_ZN7android9CallStackC2EPKci,因为它是类的构造方法,在反编译代码中第一次参数是一个隐藏的this指针,这个指针用来指向对象本身,动态调用我们需要自己malloc这个指针。

void* handle = dlopen(NULL, RTLD_NOW);
//查找函数导出符号
void* (*android_CallStack_CallStack)(void*, const char *, int) = (void *(*)(void *, const char *, int))dlsym(handle_121, "_ZN7android9CallStackC2EPKci");
//malloc出android::CallStack指针,这里也可以写死数字,8.1.0中android::CallStack大小为20
void* stack = malloc(sizeof(android::CallStack));
//将堆栈信息打印到logcat中,Log Tag为jyy
android_CallStack_CallStack(stack, "jyy", 1);

如果担心这种方式会造成内存泄漏,也可以在打印完堆栈后主动调用android::CallStack的析构函数,并在最后free掉this指针

.text:00009B20 ; void __fastcall android::CallStack::~CallStack(android::CallStack *__hidden this)
.text:00009B20                 EXPORT _ZN7android9CallStackD2Ev
.text:00009B20 _ZN7android9CallStackD2Ev               ; CODE XREF: android::ProcessCallStack::update(void)+E0↓p
void (*free_CallStack)(void*) = (void (*)(void*))dlsym(handle_121, "_ZN7android9CallStackD2Ev");
//主动调用析构函数
free_CallStack(stack);
//free this指针
free(stack);

这样就可以主动打印NDK的调用堆栈了

原文链接:,转发请注明来源!