android 打印java堆栈_深入浅出Android NDK之打印调用堆栈

目录

上一篇 深入浅出Android NDK之崩溃分析

为了能在native层打印函数的调用堆栈,找了好久的资料,最后终于找到一个靠谱的链接:

https://www.jianshu.com/p/4a5eeeee6d29

主要通过调用_Unwind_Backtrace函数来获得函数的调用堆栈,但是原文的并不好用,地址通过addr2line转换以后得不到函数名和行号,主要原因我们得到的地址是运行时地址,应该减去SO的基地址再来转换,下面看我改造后的例子,更好用。

#include

#include

#include

#include

#include

static _Unwind_Reason_Code unwindCallback(struct _Unwind_Context* context, void* arg)

{

std::vector<_unwind_word> &stack = *(std::vector<_unwind_word>*)arg;

stack.push_back(_Unwind_GetIP(context));

return _URC_NO_REASON;

}

void callstackDump(std::string &dump) {

std::vector<_unwind_word> stack;

_Unwind_Backtrace(unwindCallback, (void*)&stack);

dump.append("                                                               \n"

"*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"

"pid: 17980, tid: 17980, name: callstack.dump  >>> callstack.dump <<

"signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0\n"

"r0 00000000  r1 00000000  r2 00000001  r3 00000001\n"

"r4 e8efe008  r5 e0537b99  r6 ff970b88  r7 ff970a98\n"

"r8 ff970de0  r9 e7904400  sl e790448c  fp ff970b14\n"

"ip e8ef985c  sp ff970a60  lr e8eca00f  pc e0537d86  cpsr 200b0030\n"

"backtrace:\n");

char buff[256];

for (size_t i = 0; i < stack.size(); i++) {

Dl_info info;

if (!dladdr((void*)stack[i], &info)) {

continue;

}

int addr = (char*)stack[i] - (char*)info.dli_fbase - 1;

if (info.dli_sname == NULL || strlen(info.dli_sname) == 0) {

sprintf(buff, "#%02x pc %08x  %s\n", i, addr, info.dli_fname);

} else {

sprintf(buff, "#%02x pc %08x  %s (%s+00)\n", i, addr, info.dli_fname, info.dli_sname);

}

dump.append(buff);

}

}

void callstackLogcat(int prio, const char* tag) {

std::string dump;

callstackDump(dump);

__android_log_print(prio, tag, "%s", dump.c_str());

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

把调用堆栈拼凑成崩溃日志的样子,主要是为了方便我们使用ndk-stack来解析。

下面来测试一下:

void fun1() {

callstackLogcat(ANDROID_LOG_DEBUG, "MD_DEBUG");

}

void fun2() {

fun1();

}

void fun3() {

fun2();

}

extern "C" JNIEXPORT void Java_com_example_threadtest_PThread_start(JNIEnv *env, jclass clazz) {

fun3();

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

编译运行,得到以下输出:

2019-10-16 12:55:04.839 20856-20856/? D/MD_DEBUG:

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

pid: 17980, tid: 17980, name: callstack.dump  >>> callstack.dump <<<

signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0

r0 00000000  r1 00000000  r2 00000001  r3 00000001

r4 e8efe008  r5 e0537b99  r6 ff970b88  r7 ff970a98

r8 ff970de0  r9 e7904400  sl e790448c  fp ff970b14

ip e8ef985c  sp ff970a60  lr e8eca00f  pc e0537d86  cpsr 200b0030

backtrace:

#00 pc 00009fef  /data/app/com.example.strtest-1/lib/arm/libstrtest.so

#01 pc 0000a207  /data/app/com.example.strtest-1/lib/arm/libstrtest.so

#02 pc 00009f91  /data/app/com.example.strtest-1/lib/arm/libstrtest.so

#03 pc 00009f9f  /data/app/com.example.strtest-1/lib/arm/libstrtest.so

#04 pc 00009fa9  /data/app/com.example.strtest-1/lib/arm/libstrtest.so

#05 pc 00009fc1  /data/app/com.example.strtest-1/lib/arm/libstrtest.so (Java_com_example_threadtest_PThread_start+00)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

通过ndk-stack转换一下,得到:

C:\Users\zy>adb logcat|ndk-stack -sym D:\ndk-demo\StrTest\app\build\intermediates\ndkBuild\debug\obj\local\armeabi-v7a\

********** Crash dump: **********

pid: 17980, tid: 17980, name: callstack.dump  >>> callstack.dump <<<

signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0

Stack frame 10-16 12:55:04.839 20856 20856 D MD_DEBUG: #00 pc 00009fef  /data/app/com.example.strtest-1/lib/arm/libstrtest.so: Routine callstackDump(std::__ndk1::basic_string, std::__ndk1::allocator >&) at D:/ndk-demo/StrTest/app/src/main/jni/CallStack.cpp:19

Stack frame 10-16 12:55:04.839 20856 20856 D MD_DEBUG: #01 pc 0000a207  /data/app/com.example.strtest-1/lib/arm/libstrtest.so: Routine callstackLogcat(int, char const*) at D:/ndk-demo/StrTest/app/src/main/jni/CallStack.cpp:48

Stack frame 10-16 12:55:04.839 20856 20856 D MD_DEBUG: #02 pc 00009f91  /data/app/com.example.strtest-1/lib/arm/libstrtest.so: Routine fun1() at D:/ndk-demo/StrTest/app/src/main/jni/PThread.cpp:47

Stack frame 10-16 12:55:04.839 20856 20856 D MD_DEBUG: #03 pc 00009f9f  /data/app/com.example.strtest-1/lib/arm/libstrtest.so: Routine fun2() at D:/ndk-demo/StrTest/app/src/main/jni/PThread.cpp:51

Stack frame 10-16 12:55:04.839 20856 20856 D MD_DEBUG: #04 pc 00009fa9  /data/app/com.example.strtest-1/lib/arm/libstrtest.so: Routine fun3() at D:/ndk-demo/StrTest/app/src/main/jni/PThread.cpp:55

Stack frame 10-16 12:55:04.839 20856 20856 D MD_DEBUG: #05 pc 00009fc1  /data/app/com.example.strtest-1/lib/arm/libstrtest.so (Java_com_example_threadtest_PThread_start+00): Routine Java_com_example_threadtest_PThread_start at D:/ndk-demo/StrTest/app/src/main/jni/PThread.cpp:59

1

2

3

4

5

6

7

8

9

10

很方便,很完美!

下一篇 深入浅出Android NDK之重写JNIEnv函数

————————————————

版权声明:本文为CSDN博主「taohongtaohuyiwei」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/taohongtaohuyiwei/article/details/105147933

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值