Android 开发高手课
张绍文
前微信高级工程师,Tinker 负责人
52722 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 62 讲
导读 (1讲)
模块一 高质量开发 (25讲)
Android 开发高手课
15
15
1.0x
00:00/00:00
登录|注册

Native下如何获取调用栈?

扩展阅读
总结
Android中的unwind
书本中的unwind
生成backtrace的过程
Native下如何获取调用栈

该思维导图由 AI 生成,仅供参考

你好,我是 simsun,曾在微信从事 Android 开发,也是开源爱好者、Rust 语言“铁粉”。应绍文邀请,很高兴可以在“高手课”里和你分享一些编译方面的底层知识。
当我们在调试 Native 崩溃或者在做 profiling 的时候是十分依赖 backtrace 的,高质量的 backtrace 可以大大减少我们修复崩溃的时间。但你是否了解系统是如何生成 backtrace 的呢?今天我们就来探索一下 backtrace 背后的故事。
下面是一个常见的 Native 崩溃。通常崩溃本身并没有任何 backtrace 信息,可以直接获得的就是当前寄存器的值,但显然 backtrace 才是能够帮助我们修复 Bug 的关键。
pid: 4637, tid: 4637, name: crasher >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
r0 00000000 r1 0000121d r2 00000006 r3 00000008
r4 0000121d r5 0000121d r6 ffb44a1c r7 0000010c
r8 00000000 r9 00000000 r10 00000000 r11 00000000
ip ffb44c20 sp ffb44a08 lr eace2b0b pc eace2b16
backtrace:
#00 pc 0001cb16 /system/lib/libc.so (abort+57)
#01 pc 0001cd8f /system/lib/libc.so (__assert2+22)
#02 pc 00001531 /system/bin/crasher (do_action+764)
#03 pc 00002301 /system/bin/crasher (main+68)
#04 pc 0008a809 /system/lib/libc.so (__libc_init+48)
#05 pc 00001097 /system/bin/crasher (_start_main+38)
在阅读后面的内容之前,你可以先给自己 2 分钟时间,思考一下系统是如何生成 backtrace 的呢?我们通常把生成 backtrace 的过程叫作 unwind,unwind 看似和我们平时开发并没有什么关系,但其实很多功能都是依赖 unwind 的。举个例子,比如你要绘制火焰图或者是在崩溃发生时得到 backtrace,都需要依赖 unwind。

书本中的 unwind

1. 函数调用过程
如果你在大学时期修过汇编原理这门课程,相信你会对下面的内容还有印象。下图就是一个非常标准的函数调用的过程。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了在Native开发中获取调用栈的原理和方法。首先,作者强调了在调试Native崩溃或进行profiling时,backtrace的重要性,并展示了一个常见的Native崩溃的示例。接着,文章详细讲解了函数调用过程和恢复调用帧的原理,以及在ARM体系结构中进行unwind的方法。在Android中,作者分别讨论了Debug版本和Release版本的unwind方法,并介绍了“.eh_frame”段落的构成和作用。最后,文章总结了unwind的难点和解决方法,以及在生产环境中可能遇到的栈破坏情况。整体来说,本文对于从事Native开发或对底层技术感兴趣的读者具有很高的参考价值。读者可以通过本文了解到在Native开发中获取调用栈的原理和方法,为他们在调试和优化Native应用程序提供了重要的技术支持。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Android 开发高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(2)

  • 最新
  • 精选
  • 山鬼
    春节依然继续学习。之前老师讲崩溃优化的时候尝试对native的崩溃进行了捕获,使用的系统提供的uwind工具,当时觉得比较难得在于打印出对应的java堆栈。现在对uwind的原理又了解了一下,但感觉这篇教程的信息量少了些。

    作者回复: 👍🏻,获得java堆栈的方法可以参考卡顿补充篇的做法

    2019-02-03
    3
  • Geek_Yasin28
    请问这里的方法可以用于获取非崩溃情况下其他线程的native堆栈吗? 对于卡顿的分析,除了Simpleperf ,如果想或许线上的native执行情况,是否只能对指定的函数进行GOTHOOK?

    作者回复: 可以的,类似breakpad通过信号量和unwind就可以了

    2019-03-28
    2
收起评论
显示
设置
留言
2
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部