酷酷的哀殿


  • 首页

  • 技术

  • 笔记

  • 杂记

  • Todo

  • 关于

  • 搜索
close

时间: 0001-01-01   |   阅读: 5422 字 ~11分钟

崩溃日志的栈帧缺失

[toc]

问题背景

有位网友反馈自己负责的一款多种语言(objective-c/Swift/kotlin)混编的 APP 深受崩溃日志栈帧丢失的困扰。

如下所示:

  • 第一张图是通过 Xcode 看到的相对”真实“的 Backtrace(函数调用栈)

  • 第二张图是通过崩溃捕获工具获得的 Backtrace(函数调用栈)

通过对比两张截图,我们很容易发现,第二份崩溃日志的 Backtrace(函数调用栈) 缺失了 KaMPKitiOS -[TestOCInvokeKotlin testFun:]

image-20210127230811560

image-20210127230440090

本系列文章将会比较两种获取 Backtrace(函数调用栈) 的原理,并提供一种捕获完整崩溃日志的方案。

崩溃捕获 Backtrace(函数调用栈) 的原理

大部分的崩溃捕获工具的核心代码都是依赖 Fast unwind 捕获 **Backtrace(函数调用栈)**的。

什么是 Fast unwind?

Fast unwind 是指只依赖有限的寄存器获取 Backtrace(函数调用栈) 的方案。

如下面的演示代码所示,Fast unwind 只需要简单的几行代码获取 Backtrace(函数调用栈)。

注意:以下方法只进行展示;线上产品应该充分考虑各种异常情况,避免因为栈帧异常,触发二次崩溃

void fastUnwind() {
    void **fp = __builtin_frame_address(0);
    for (;;) {
        void **next_fp = *fp;
        if (next_fp <= fp) break;
        printf("%p\n", *(fp+1));
        fp = next_fp;
    }
}

什么是 Backtrace(函数调用栈)

根据官方文档,**Backtrace(函数调用栈)**就是 “APP 崩溃时,每个线程运行的代码”。

通常情况下,它会按照以下方式展示:

0   TouchCanvas                       0x0000000102afb3d0 CanvasView.updateEstimatedPropertiesForTouches(_:) + 62416 (CanvasView.swift:231)
1   TouchCanvas                       0x0000000102afb3d0 CanvasView.updateEstimatedPropertiesForTouches(_:) + 62416 (CanvasView.swift:231)
2   TouchCanvas                       0x0000000102af7d10 ViewController.touchesMoved(_:with:) + 48400 (<compiler-generated>:0)
3   TouchCanvas                       0x0000000102af80b8 @objc ViewController.touchesMoved(_:with:) + 49336 (<compiler-generated>:0)
4   UIKitCore                         0x00000001ba9d8da4 forwardTouchMethod + 328
5   UIKitCore                         0x00000001ba9d8e40 -[UIResponder touchesMoved:withEvent:] + 60
6   UIKitCore                         0x00000001ba9d8da4 forwardTouchMethod + 328
7   UIKitCore                         0x00000001ba9d8e40 -[UIResponder touchesMoved:withEvent:] + 60
8   UIKitCore                         0x00000001ba9e6ea4 -[UIWindow _sendTouchesForEvent:] + 1896
9   UIKitCore                         0x00000001ba9e8390 -[UIWindow sendEvent:] + 3352
10  UIKitCore                         0x00000001ba9c4a9c -[UIApplication sendEvent:] + 344
11  UIKitCore                         0x00000001baa3cc20 __dispatchPreprocessedEventFromEventQueue + 5880
12  UIKitCore                         0x00000001baa3f17c __handleEventQueueInternal + 4924
13  UIKitCore                         0x00000001baa37ff0 __handleHIDEventFetcherDrain + 108
14  CoreFoundation                    0x00000001b68a4a00 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
15  CoreFoundation                    0x00000001b68a4958 __CFRunLoopDoSource0 + 80
16  CoreFoundation                    0x00000001b68a40f0 __CFRunLoopDoSources0 + 180
17  CoreFoundation                    0x00000001b689f23c __CFRunLoopRun + 1080
18  CoreFoundation                    0x00000001b689eadc CFRunLoopRunSpecific + 464
19  GraphicsServices                  0x00000001c083f328 GSEventRunModal + 104
20  UIKitCore                         0x00000001ba9ac63c UIApplicationMain + 1936
21  TouchCanvas                       0x0000000102af16dc main + 22236 (AppDelegate.swift:12)
22  libdyld.dylib                     0x00000001b6728360 start + 4

其中,崩溃的每一行代表 Backtrace(函数调用栈) 中的一个 栈帧。

21  TouchCanvas                       0x0000000102af16dc main + 22236 (AppDelegate.swift:12)

栈帧 的每一列都包含有关崩溃时执行的代码的信息。

每一列代表的含义如下所示:

  • 21 :栈帧帧号。

    栈帧按调用顺序排列,其中帧0是暂停执行时正在执行的函数。帧1是调用 帧0 的函数。后续的依此类推。

  • TouchCanvas:包含正在执行的函数的二进制文件的名称。

    通常情况下,我们只会见到三种名称:1、系统库 2、可执行文件 3、动态库

  • 0x0000000102af16dc:正在执行的机器指令的地址。

    对于帧0,这是 APP 暂停或终止时在线程上执行的机器指令的地址。对于其他栈帧,这是在控制权返回到该栈帧之后执行的第一条机器指令的地址。

  • main:在完全符号化的崩溃报告中,正在执行的函数的名称。出于隐私原因,苹果提供的函数名会限制到前 100 个字符。

  • 22236:+ 后面的数字是从函数入口到函数当前指令的字节偏移量。

  • AppDelegate.swift:12:代码的文件名和行号

    在某些情况下,文件名或行号信息与原始源代码不对应:

    • 如果源文件名为<compiler-generated>,则代表该函数是编译器为框架创建的源码

    • 如果源文件的行号为0,则表示该 栈帧 不会映射到原始代码中的特定代码行。

      无法映射的原因有很多,比如编译器对函数进行了内联

Fast unwind 测试

在讲解 Fast unwind 的原理前,我们先看看上面代码的实际效果

完整测试代码:


- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    NSLog(@"开始打印:[NSThread callStackSymbols]");
    NSLog(@"%@", [NSThread callStackSymbols]);

    NSLog(@"===== 分隔符 =====");
    fastUnwind();
}

static long idx = 0;
// 为了直观对比效果,将 函数名 和 指令的字节偏移量 进行打印
void dumpAddress(const void *p) {
    char *(*demangle)(char const *) = dlsym(RTLD_DEFAULT, "demangle");
    Dl_info info;
    if (dladdr(p, &info)) {
        char *demangleName = demangle(info.dli_sname);
        if (demangleName && strlen(demangleName) > 0) {
            printf("%ld 0x%016lx  %s + %ld \n", idx, (unsigned long)p, demangleName, p - info.dli_saddr);
        } else {
            printf("%ld 0x%016lx  %s + %ld \n", idx, (unsigned long)p, info.dli_sname , p - info.dli_saddr);
        }
    } else {
        printf("非法地址");
    }
    ++idx;
}

void fastUnwind() {
    void **fp = __builtin_frame_address(0);
    for (;;) {
        void **next_fp = *fp;
        if (next_fp <= fp) break;
        dumpAddress(*(fp + 1));
        // printf("%p\n", *(fp+1));
        fp = next_fp;
    }
}

两种获取 Backtrace(函数调用栈) 方式的日志对比:

    0   Demo                                0x0000000101383d32 -[ViewController viewDidAppear:] + 114
    1   UIKitCore                           0x00007fff23f4730c -[UIViewController _setViewAppearState:isAnimating:] + 920
    2   UIKitCore                           0x00007fff23f47ce3 -[UIViewController __viewDidAppear:] + 146
    3   UIKitCore                           0x00007fff23f47fbc -[UIViewController _endAppearanceTransition:] + 232
    4   UIKitCore                           0x00007fff23e18dda __48-[UIPresentationController transitionDidFinish:]_block_invoke + 138
    5   UIKitCore                           0x00007fff24b700ce -[_UIAfterCACommitBlock run] + 54
    6   UIKitCore                           0x00007fff24683de4 _runAfterCACommitDeferredBlocks + 333
    7   UIKitCore                           0x00007fff24673e8c _cleanUpAfterCAFlushAndRunDeferredBlocks + 221
    8   UIKitCore                           0x00007fff246a5700 _afterCACommitHandler + 85
    9   CoreFoundation                      0x00007fff2038b1e8 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    10  CoreFoundation                      0x00007fff20385a67 __CFRunLoopDoObservers + 547
    11  CoreFoundation                      0x00007fff2038600a __CFRunLoopRun + 1113
    12  CoreFoundation                      0x00007fff203856c6 CFRunLoopRunSpecific + 567
    13  GraphicsServices                    0x00007fff2b76adb3 GSEventRunModal + 139
    14  UIKitCore                           0x00007fff24675187 -[UIApplication _run] + 912
    15  UIKitCore                           0x00007fff2467a038 UIApplicationMain + 101
    16  Demo                                0x0000000101384052 main + 114
    17  libdyld.dylib                       0x00007fff20256409 start + 1

===== 分隔符 =====

0 0x0000000101383d75  -[ViewController viewDidAppear:] + 181 
1 0x00007fff23f4730c  -[UIViewController _setViewAppearState:isAnimating:] + 920 
2 0x00007fff23f47ce3  -[UIViewController __viewDidAppear:] + 146 
3 0x00007fff23f47fbc  -[UIViewController _endAppearanceTransition:] + 232 
4 0x00007fff23e18dda  __48-[UIPresentationController transitionDidFinish:]_block_invoke + 138 
5 0x00007fff24b700ce  -[_UIAfterCACommitBlock run] + 54 
6 0x00007fff24683de4  _runAfterCACommitDeferredBlocks + 333 
7 0x00007fff24673e8c  _cleanUpAfterCAFlushAndRunDeferredBlocks + 221 
8 0x00007fff246a5700  _afterCACommitHandler + 85 
9 0x00007fff2038b1e8  __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23 
10 0x00007fff20385a67  __CFRunLoopDoObservers + 547 
11 0x00007fff2038600a  __CFRunLoopRun + 1113 
12 0x00007fff203856c6  CFRunLoopRunSpecific + 567 
13 0x00007fff2b76adb3  GSEventRunModal + 139 
14 0x00007fff24675187  -[UIApplication _run] + 912 
15 0x00007fff2467a038  UIApplicationMain + 101 
16 0x0000000101384052  main + 114 
17 0x00007fff20256409  start + 1 

通过对照两份日志,我们可以看到可以发现 fastUnwind 和 [NSThread callStackSymbols] 的打印内容是一致的。

实际上,本文的 fastUnwind 函数就是通过将 [NSThread callStackSymbols] 的源码精简后得到的。

Fast unwind 实现原理

Fast unwind 实现原理依赖以下两个机制:

  • 编译器或者开发者在 prolog 阶段按照规则保证相关的 lr 信息
  • 带链接的跳转指令(比如 arm64 的 bl 指令会更新 lr)

Fast unwind 机制演示

相信很多朋友会和我一样,看到上面的描述会一头雾水。

不要着急,我们用一个实际的例子感受一下。

  • 第一步:我们需要先准备几个函数方便并添加断点

测试代码:

image-20210129001436670

  • 第二步,执行程序,并在 testB 处命中断点,打印寄存器和堆栈信息
(lldb) x/2a $fp
0x16bba0f70: 0x000000016bba0f80
0x16bba0f78: 0x0000000104262b74 KaMPKitiOS`testA + 12 at TestOCInvokeKotlin.m:66:1
(lldb) x/2a $sp
0x16bba0f70: 0x000000016bba0f80
0x16bba0f78: 0x0000000104262b74 KaMPKitiOS`testA + 12 at TestOCInvokeKotlin.m:66:1
(lldb) p/a $lr
(unsigned long) $5 = 0x0000000104262b74 KaMPKitiOS`testA + 12 at TestOCInvokeKotlin.m:66:1
(lldb) 

本文主要使用 arm64 架构为例进行讲解:

x29/fp 是 帧指针,用于存储栈帧相关的信息

x30/lr 是 链接寄存器,该寄存器存储的内容是某个函数的的地址。

sp 是 堆栈寄存器

整理后的栈内存如下:

    //             +=============================+
    // 0x16fb7c750 |                             |
    //             +-----------------------------+
    // 0x16fb7c758 |                             |
    //             +=============================+
    // 0x16fb7c760 |                             |
        //             +-----------------------------+
    // 0x16fb7c768 |                             |
    //             +=============================+
    // 0x16fb7c770 |   fp (0x000000016bba0f80)   |    <- fp,sp
        //             +-----------------------------+
    // 0x16fb7c778 |        testA + 12           |
    //             +=============================+
  • 第三步:继续执行程序,并在 testC 处命中断点,打印寄存器和堆栈信息
(lldb) p/a $lr
(unsigned long) $6 = 0x0000000104262b88 KaMPKitiOS`testB + 12 at TestOCInvokeKotlin.m:70:1
(lldb) x/2a $sp
0x16bba0f50: 0x000000016bba0f80
0x16bba0f58: 0x00000001a3bc0d9c libobjc.A.dylib`objc_storeStrong + 44
(lldb) x/2a $fp
0x16bba0f60: 0x000000016bba0f70
0x16bba0f68: 0x0000000104262b88 KaMPKitiOS`testB + 12 at TestOCInvokeKotlin.m:70:1
(lldb) 

整理后的栈内存如下:

    //             +=============================+
    // 0x16fb7c750 |                             |    <- sp
    //             +-----------------------------+
    // 0x16fb7c758 |                             |
    //             +=============================+
    // 0x16fb7c760 |   fp (0x000000016bba0f70)   |    <- fp    
        //             +-----------------------------+
    // 0x16fb7c768 |        testB + 12           |
    //             +=============================+
    // 0x16fb7c770 |   fp (0x000000016bba0f80)   | 
        //             +-----------------------------+
    // 0x16fb7c778 |        testA + 12           |
    //             +=============================+

现在,我们总结一下 fp 寄存器的规律:fp 存储的值是内存地址 0x16bba0f60,0x16bba0f60 存储了上一帧的地址 0x000000016bba0f70 。

根据上面的规律,我们可以发现,寄存器 fp 就像一个链表的起始地址,通过它可以将整个 Backtrace(函数调用栈) 进行串联。

为了节省篇幅,我们不会将整个 Backtrace(函数调用栈) 讲解一遍,而是只提供下面的几个 栈帧,希望读者能够结合本文的第一份代码相互印证。

(lldb) x/2a $fp
0x16b904700: 0x000000016b904710
0x16b904708: 0x00000001044feb88 KaMPKitiOS`testB + 12 at TestOCInvokeKotlin.m:70:1
(lldb) x/2a 0x000000016b904710
0x16b904710: 0x000000016b904720
0x16b904718: 0x00000001044feb74 KaMPKitiOS`testA + 12 at TestOCInvokeKotlin.m:66:1
(lldb) x/2a 0x000000016b904720
0x16b904720: 0x000000016b904760
0x16b904728: 0x00000001044fec2c KaMPKitiOS`-[TestOCInvokeKotlin testOc:] + 56 at TestOCInvokeKotlin.m:78:6
(lldb) x/2a 0x000000016b904760
0x16b904760: 0x000000016b9047c0
0x16b904768: 0x00000001045050f8 KaMPKitiOS`KaMPKitiOS.BreedsViewController.(testOcInvokeKotlinLostFrameStack in _A334B59FD68BA9444D870B4E917DE9AA)() -> () + 252 at ViewController.swift:88:19
(lldb) x/2a 0x000000016b9047c0
0x16b9047c0: 0x000000016b9047e0
0x16b9047c8: 0x0000000104504ff0 KaMPKitiOS`KaMPKitiOS.BreedsViewController.toggleFavorite(__C.SharedBreed) -> () + 32 at ViewController.swift:83:5
(lldb) 

小结 1:寄存器 fp 就像一个链表,可以将整个 Backtrace(函数调用栈) 进行串联

栈帧 lowering

通常情况下,我们的的代码会经过 llvm 的 栈帧 lowering 过程生成函数的 prolog(序章) 和 epilog (尾声) 。

以 llvm 对 arm64 架构的处理为例, AArch64FrameLowering.cpp 文件的 llvm::AArch64FrameLowering::emitPrologue 方法负责生成函数的 prologue

image-20210128143107890

prolog(序章)

prolog(序言) 是函数起始部分的指令。

函数的初始化代码。分配堆栈空间、调用其他函数、保存非易失性寄存器或使用异常处理的每个函数都必须具有 prolog

epilog(尾声)

epilog (尾声) 是函数结束部分的指令。

每个函数在每次退出时会有一个 epilog ,每个函数通常只有一个 prolog,而可以有多个 epilog。 Epilog 代码将堆栈剪裁为固定分配大小(如有必要),解除分配固定堆栈分配,通过从堆栈中弹出其保存的值来还原非易失性寄存器,然后返回。

注意:函数结束部分的指令不一定是 epilog

下面以 testA 和 testB 两个函数为例介绍 epilog (尾声)

    KaMPKitiOS`testA:
    0x1042ea288 <+0>:  stp    x29, x30, [sp, #-0x10]!
    0x1042ea28c <+4>:  mov    x29, sp

->  0x1042ea290 <+8>:  bl     0x1042ea29c               ; testB at TestOCInvokeKotlin.m:113

    0x1042ea294 <+12>: ldp    x29, x30, [sp], #0x10
    0x1042ea298 <+16>: ret    
KaMPKitiOS`testB:
    0x1042ea29c <+0>:  stp    x29, x30, [sp, #-0x10]!
    0x1042ea2a0 <+4>:  mov    x29, sp

->  0x1042ea2a4 <+8>:  bl     0x1042ea2b0               ; testC at TestOCInvokeKotlin.m:117

    0x1042ea2a8 <+12>: ldp    x29, x30, [sp], #0x10
    0x1042ea2ac <+16>: ret       

两个函数的前两行是 prolog,会保存寄存器 x29/fp 、x30/lr 并更新 sp 和 x29/fp 寄存器的内容:

  • stp x29, x30, [sp, #-0x10]! 会先将 sp 减去 0x10;随后,会将寄存器 x29 和 x30 存储到 sp 指向的位置

  • mov x29, sp 等价于 $x29 = $sp

这里留一个小作业,有兴趣的读者可以结合前面的两个栈内存 分析一下 testC 的 prolog。

两个函数的后两行是 epilog:

  • ldp x29, x30, [sp], #0x10 会恢复寄存器 x29/fp 、x30/lr 并更新 sp 寄存器

  • ret 表示返回,该指令执行后lr寄存器保存的位置开始执行

小结 2 : prolog 会保存寄存器 x29/fp 、x30/lr 并更新 sp 和 x29/fp 寄存器的内容

bl 指令 与 编译器优化

本节会先简单介绍 bl 指令的用法,并介绍编译器优化对 Backtrace(函数调用栈) 的影响。

bl 指令

bl 会在更新 lr 寄存器的同时进行跳转。

该指令会执行两个任务:

  • 将返回地址存放到链接寄存器中
  • 将 pc 设置为子例程的地址

以 testB 为例:

寄存器 lr 的值会更新为 0x1042ea2a8(bl 的下一个指令),然后从 0x1042ea2b0 开始执行

->  0x1042ea2a4 <+8>:  bl     0x1042ea2b0               ; testC at TestOCInvokeKotlin.m:117
    0x1042ea2a8 <+12>: ldp    x29, x30, [sp], #0x10
    0x1042ea2ac <+16>: ret  

除了 bl 指令外,还有很多用于调整的指令,比如 b 指令。

image-20210131235629220

编译器优化

可能读者有些奇怪为什么前文会多次强调 带链接的跳转指令。

现在,我们用具体的例子看看编译器优化对 Backtrace(函数调用栈) 的影响

指令精简

  • 首先,需要在 Build Settings 开启 Os 级别的编译优化

    image-20210201002312593

  • 强制关闭编译器对 testA 和 testB 的内联优化

__attribute__((__noinline__))
void testA() {
    testB();
}

__attribute__((__noinline__))
void testB() {
    testC();
}
  • 重新运行 APP,我们可以看到两个函数的指令都被缩减到一个 b 指令
KaMPKitiOS`testA:
    0x100792608 <+0>: b      0x10079260c               ; testB at TestOCInvokeKotlin.m:114:5

KaMPKitiOS`testB:
->  0x10079260c <+0>: b      0x100792610               ; testC at TestOCInvokeKotlin.m:117

通过打印 lr 寄存器的内容,我们可以注意到执行命令 b 以后, lr 寄存器不会被更新

image-20210201003006201

通过 FastUnwind 获取的函数调用栈也会缺失 testA 和 testB

image-20210201003210038

函数内联

现在,我们把 testA 和 testB 的 __attribute__((__noinline__)) 修饰符移除并重新运行:

因为 testA 和 testB 的内容比较简单,编译器会直接在 dumpUnwind 调用 testC 函数。

image-20210201004230498

经过函数内联优化后,通过 FastUnwind 获取的函数调用栈同样会缺失 testA 和 testB

小结 3:开启编译器优化后,会影响 Backtrace(函数调用栈) 的回溯

FastUnwind 机制原理小结

现在,我们再强调一下本节的内容:

FastUnwind 实现原理依赖以下两个机制:

  • 编译器或者开发者在 prolog 阶段按照规则保证相关的 lr 信息
  • 带链接的跳转指令(比如 arm64 的 bl 指令会更新 lr)

Xcode 的 unwind 机制

前面通过介绍 FastUnwind 的实现原理,并介绍了两种可能导致栈帧缺失的原因:指令精简和函数内联。

现在,我们看看为什么 Xcode 可以展示缺失的堆栈。

Xcode 与 lldb

因为从 Xcode 5 1 开始,Xcode 不再支持 LLVM-GCC 编译器和 GDB 调试器。所以,我们本文只介绍 lldb 调试器。

lldb 是一款

Call Frame Information (CFI)
CFA - Canonical Frame Address, is the address of the stack pointer just before a call instruction is executed.

FDE - Frame Descriptor Entries are unique to each section and holds the CFI information in eh_frame section

CIE - Common Information Entries that hold information that is common to multiple FDEs in eh_frame section.

https://reviews.llvm.org/D79978

我们重点看一下前面的几行代码:




classDiagram

      class frame_data{
          frame_data frame_addr_next
          frame_data_addr_t ret_addr
      }

lldb

因为 Xcode

Got compact unwind encoding 0x52160000 for function objc2kotlin.138
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 73.1 74.1
  * frame #0: 0x00000001006d2b55 LLDB`lldb_private::CompactUnwindInfo::GetUnwindPlan(this=0x0000000117cd60e0, target=0x0000000118875a00, addr=Address @ 0x00007ffeefbfd8f8, unwind_plan=0x000000011bca0510) at CompactUnwindInfo.cpp:195:7 [opt]
    frame #1: 0x00000001006dfbc7 LLDB`lldb_private::FuncUnwinders::GetCompactUnwindUnwindPlan(this=0x0000000117a9ec40, target=0x0000000118875a00) at FuncUnwinders.cpp:94:27 [opt]
    frame #2: 0x00000001006df1ed LLDB`lldb_private::FuncUnwinders::GetUnwindPlanAtCallSite(this=0x0000000117a9ec40, target=0x0000000118875a00, thread=0x0000000117e3d528) at FuncUnwinders.cpp:72:30 [opt]
    frame #3: 0x000000010074230f LLDB`lldb_private::RegisterContextUnwind::GetFullUnwindPlanForFrame(this=0x0000000117e74430) at RegisterContextUnwind.cpp:906:41 [opt]
    frame #4: 0x00000001007401aa LLDB`lldb_private::RegisterContextUnwind::InitializeNonZerothFrame(this=0x0000000117e74430) at RegisterContextUnwind.cpp:548:29 [opt]
    frame #5: 0x000000010073e8fe LLDB`lldb_private::RegisterContextUnwind::RegisterContextUnwind(this=0x0000000117e74430, thread=0x0000000117e3d528, next_frame=std::__1::shared_ptr<lldb_private::RegisterContextUnwind>::element_type @ 0x00000001179a22a0 strong=1 weak=2, sym_ctx=0x0000000117e74920, frame_number=6, unwind_lldb=0x0000000117c38350) at RegisterContextUnwind.cpp:70:5 [opt]
    frame #6: 0x00000001007dac8e LLDB`lldb_private::UnwindLLDB::GetOneMoreFrame(this=0x0000000117c38350, abi=0x0000000117c383f0) at UnwindLLDB.cpp:128:40 [opt]
    frame #7: 0x00000001007da4eb LLDB`lldb_private::UnwindLLDB::AddOneMoreFrame(this=0x0000000117c38350, abi=0x0000000117c383f0) at UnwindLLDB.cpp:345:23 [opt]
    frame #8: 0x00000001007db1ff LLDB`lldb_private::UnwindLLDB::DoGetFrameInfoAtIndex(this=0x0000000117c38350, idx=5, cfa=0x00007ffeefbfe078, pc=0x00007ffeefbfe070, behaves_like_zeroth_frame=0x00007ffeefbfe097) at UnwindLLDB.cpp:402:36 [opt]
    frame #9: 0x0000000100753763 LLDB`lldb_private::StackFrameList::GetFramesUpTo(unsigned int) [inlined] lldb_private::Unwind::GetFrameInfoAtIndex(this=0x0000000117c38350, frame_idx=<unavailable>, cfa=0x00007ffeefbfe078, pc=0x00007ffeefbfe070, behaves_like_zeroth_frame=0x00007ffeefbfe097) at Unwind.h:53:12 [opt]
    frame #10: 0x0000000100753742 LLDB`lldb_private::StackFrameList::GetFramesUpTo(this=0x0000000117c402d8, end_idx=<unavailable>) at StackFrameList.cpp:502 [opt]
    frame #11: 0x0000000100755467 LLDB`lldb_private::StackFrameList::GetFrameAtIndex(this=0x0000000117c402d8, idx=<unavailable>) at StackFrameList.cpp:678:3 [opt]
    frame #12: 0x0000000100755f8a LLDB`lldb_private::StackFrameList::GetStatus(this=<unavailable>, strm=0x00007ffeefbfe978, first_frame=<unavailable>, num_frames=<unavailable>, show_frame_info=true, num_frames_with_source=0, show_unique=<unavailable>, selected_frame_marker="* ") at StackFrameList.cpp:989:16 [opt]
    frame #13: 0x00000001007bb8be LLDB`lldb_private::Thread::GetStatus(this=0x0000000117e3d528, strm=0x00007ffeefbfe978, start_frame=0, num_frames=4294967295, num_frames_with_source=0, stop_format=<unavailable>, only_stacks=<unavailable>) at Thread.cpp:1814:45 [opt]
    frame #14: 0x0000000100c75b06 LLDB`CommandObjectThreadBacktrace::HandleOneThread(this=0x0000000117927e60, tid=271703, result=0x00007ffeefbfe978) at CommandObjectThread.cpp:361:18 [opt]
    frame #15: 0x0000000100c756e8 LLDB`CommandObjectIterateOverThreads::DoExecute(this=0x0000000117927e60, command=0x00007ffeefbfe498, result=0x00007ffeefbfe978) at CommandObjectThread.cpp:85:23 [opt]
    frame #16: 0x00000001006a90ea LLDB`lldb_private::CommandObjectParsed::Execute(this=<unavailable>, args_string=<unavailable>, result=0x00007ffeefbfe978) at CommandObject.cpp:993:19 [opt]
    frame #17: 0x00000001006a0678 LLDB`lldb_private::CommandInterpreter::HandleCommand(this=0x00000001179098b0, command_line=<unavailable>, lazy_add_to_history=eLazyBoolNo, result=0x00007ffeefbfe978, override_context=0x0000000117909a90, repeat_on_empty_command=<unavailable>, no_context_switching=<unavailable>) at CommandInterpreter.cpp:1812:14 [opt]
    frame #18: 0x00000001006aa905 LLDB`lldb_private::CommandObjectRegexCommand::DoExecute(this=<unavailable>, command=(Data = <no value available>, Length = 0), result=0x00007ffeefbfe978) at CommandObjectRegexCommand.cpp:57:28 [opt]
    frame #19: 0x00000001006a92d2 LLDB`lldb_private::CommandObjectRaw::Execute(this=0x0000000117947460, args_string="", result=0x00007ffeefbfe978) at CommandObject.cpp:1015:17 [opt]
    frame #20: 0x00000001006a0678 LLDB`lldb_private::CommandInterpreter::HandleCommand(this=0x00000001179098b0, command_line=<unavailable>, lazy_add_to_history=eLazyBoolNo, result=0x00007ffeefbfe978, override_context=0x0000000117909a90, repeat_on_empty_command=<unavailable>, no_context_switching=<unavailable>) at CommandInterpreter.cpp:1812:14 [opt]
    frame #21: 0x00000001006a3a42 LLDB`lldb_private::CommandInterpreter::IOHandlerInputComplete(this=0x00000001179098b0, io_handler=0x0000000117c39058, line=<unavailable>) at CommandInterpreter.cpp:2850:3 [opt]
    frame #22: 0x00000001005e2a32 LLDB`lldb_private::IOHandlerEditline::Run(this=0x0000000117c39058) at IOHandler.cpp:562:22 [opt]
    frame #23: 0x00000001005c85af LLDB`lldb_private::Debugger::RunIOHandlers(this=0x0000000117908fc0) at Debugger.cpp:866:16 [opt]
    frame #24: 0x00000001006a4cde LLDB`lldb_private::CommandInterpreter::RunCommandInterpreter(this=0x00000001179098b0, options=0x00007ffeefbfecb0) at CommandInterpreter.cpp:3089:16 [opt]
    frame #25: 0x00000001003984d9 LLDB`lldb::SBDebugger::RunCommandInterpreter(this=0x00007ffeefbff178, auto_handle_events=<unavailable>, spawn_thread=<unavailable>) at SBDebugger.cpp:1178:42 [opt]
    frame #26: 0x000000010000568e lldb`Driver::MainLoop(this=<unavailable>) at Driver.cpp:675:18 [opt]
    frame #27: 0x0000000100006fb0 lldb`main(argc=<unavailable>, argv=<unavailable>) at Driver.cpp:932:26 [opt]
    frame #28: 0x00007fff68079cc9 libdyld.dylib`start + 1
    frame #29: 0x00007fff68079cc9 libdyld.dylib`start + 1
(lldb) 
lldb) p this->m_section_sp.__ptr_->m_parent_wp.__ptr_->m_name.m_string
(const char *) $8 = 0x000000011901ef38 "__TEXT"
(lldb) p this->m_section_sp.__ptr_->m_name.m_string
(const char *) $9 = 0x00000001190fb530 "__eh_frame"
(lldb) p this->m_objfile.m_module_wp.__ptr_->m_file.m_filename
(lldb_private::ConstString) $10 = (m_string = "shared")
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 70.1
  * frame #0: 0x00000001006dcef4 LLDB`lldb_private::DWARFCallFrameInfo::GetCFIData(this=0x000000011bb348c0) at DWARFCallFrameInfo.cpp:399:14 [opt]
    frame #1: 0x00000001006dc3f4 LLDB`lldb_private::DWARFCallFrameInfo::GetFDEIndex(this=0x000000011bb348c0) at DWARFCallFrameInfo.cpp:435:5 [opt]
    frame #2: 0x00000001006dae45 LLDB`lldb_private::DWARFCallFrameInfo::GetFirstFDEEntryInRange(this=0x000000011bb348c0, range=0x0000000117837398) at DWARFCallFrameInfo.cpp:199:3 [opt]
    frame #3: 0x00000001006dadb1 LLDB`lldb_private::DWARFCallFrameInfo::GetUnwindPlan(this=0x000000011bb348c0, range=0x0000000117837398, unwind_plan=0x000000011783a2b8) at DWARFCallFrameInfo.cpp:167:50 [opt]
    frame #4: 0x00000001006df9b9 LLDB`lldb_private::FuncUnwinders::GetEHFrameUnwindPlan(this=0x0000000117837390, target=<unavailable>) at FuncUnwinders.cpp:136:22 [opt]
    frame #5: 0x00000001006df1a8 LLDB`lldb_private::FuncUnwinders::GetUnwindPlanAtCallSite(this=0x0000000117837390, target=0x0000000119128200, thread=0x0000000117b61178) at FuncUnwinders.cpp:70:30 [opt]
    frame #6: 0x000000010074230f LLDB`lldb_private::RegisterContextUnwind::GetFullUnwindPlanForFrame(this=0x0000000117a5ce50) at RegisterContextUnwind.cpp:906:41 [opt]
    frame #7: 0x00000001007401aa LLDB`lldb_private::RegisterContextUnwind::InitializeNonZerothFrame(this=0x0000000117a5ce50) at RegisterContextUnwind.cpp:548:29 [opt]
    frame #8: 0x000000010073e8fe LLDB`lldb_private::RegisterContextUnwind::RegisterContextUnwind(this=0x0000000117a5ce50, thread=0x0000000117b61178, next_frame=std::__1::shared_ptr<lldb_private::RegisterContextUnwind>::element_type @ 0x000000011bb2c2e0 strong=1 weak=2, sym_ctx=0x0000000117a5cd90, frame_number=6, unwind_lldb=0x0000000119c211f0) at RegisterContextUnwind.cpp:70:5 [opt]
    frame #9: 0x00000001007dac8e LLDB`lldb_private::UnwindLLDB::GetOneMoreFrame(this=0x0000000119c211f0, abi=0x0000000119c21150) at UnwindLLDB.cpp:128:40 [opt]
    frame #10: 0x00000001007da4eb LLDB`lldb_private::UnwindLLDB::AddOneMoreFrame(this=0x0000000119c211f0, abi=0x0000000119c21150) at UnwindLLDB.cpp:345:23 [opt]
    frame #11: 0x00000001007db1ff LLDB`lldb_private::UnwindLLDB::DoGetFrameInfoAtIndex(this=0x0000000119c211f0, idx=5, cfa=0x00007ffeefbfe078, pc=0x00007ffeefbfe070, behaves_like_zeroth_frame=0x00007ffeefbfe097) at UnwindLLDB.cpp:402:36 [opt]
    frame #12: 0x0000000100753763 LLDB`lldb_private::StackFrameList::GetFramesUpTo(unsigned int) [inlined] lldb_private::Unwind::GetFrameInfoAtIndex(this=0x0000000119c211f0, frame_idx=<unavailable>, cfa=0x00007ffeefbfe078, pc=0x00007ffeefbfe070, behaves_like_zeroth_frame=0x00007ffeefbfe097) at Unwind.h:53:12 [opt]
    frame #13: 0x0000000100753742 LLDB`lldb_private::StackFrameList::GetFramesUpTo(this=0x0000000117e148d8, end_idx=<unavailable>) at StackFrameList.cpp:502 [opt]
    frame #14: 0x0000000100755467 LLDB`lldb_private::StackFrameList::GetFrameAtIndex(this=0x0000000117e148d8, idx=<unavailable>) at StackFrameList.cpp:678:3 [opt]
    frame #15: 0x0000000100755f8a LLDB`lldb_private::StackFrameList::GetStatus(this=<unavailable>, strm=0x00007ffeefbfe978, first_frame=<unavailable>, num_frames=<unavailable>, show_frame_info=true, num_frames_with_source=0, show_unique=<unavailable>, selected_frame_marker="* ") at StackFrameList.cpp:989:16 [opt]
    frame #16: 0x00000001007bb8be LLDB`lldb_private::Thread::GetStatus(this=0x0000000117b61178, strm=0x00007ffeefbfe978, start_frame=0, num_frames=4294967295, num_frames_with_source=0, stop_format=<unavailable>, only_stacks=<unavailable>) at Thread.cpp:1814:45 [opt]
    frame #17: 0x0000000100c75b06 LLDB`CommandObjectThreadBacktrace::HandleOneThread(this=0x0000000117c9ab60, tid=134225, result=0x00007ffeefbfe978) at CommandObjectThread.cpp:361:18 [opt]
    frame #18: 0x0000000100c756e8 LLDB`CommandObjectIterateOverThreads::DoExecute(this=0x0000000117c9ab60, command=0x00007ffeefbfe498, result=0x00007ffeefbfe978) at CommandObjectThread.cpp:85:23 [opt]
    frame #19: 0x00000001006a90ea LLDB`lldb_private::CommandObjectParsed::Execute(this=<unavailable>, args_string=<unavailable>, result=0x00007ffeefbfe978) at CommandObject.cpp:993:19 [opt]
    frame #20: 0x00000001006a0678 LLDB`lldb_private::CommandInterpreter::HandleCommand(this=0x0000000117c7c1f0, command_line=<unavailable>, lazy_add_to_history=eLazyBoolNo, result=0x00007ffeefbfe978, override_context=0x0000000117c7c3d0, repeat_on_empty_command=<unavailable>, no_context_switching=<unavailable>) at CommandInterpreter.cpp:1812:14 [opt]
    frame #21: 0x00000001006aa905 LLDB`lldb_private::CommandObjectRegexCommand::DoExecute(this=<unavailable>, command=(Data = <no value available>, Length = 0), result=0x00007ffeefbfe978) at CommandObjectRegexCommand.cpp:57:28 [opt]
    frame #22: 0x00000001006a92d2 LLDB`lldb_private::CommandObjectRaw::Execute(this=0x0000000117cba160, args_string="", result=0x00007ffeefbfe978) at CommandObject.cpp:1015:17 [opt]
    frame #23: 0x00000001006a0678 LLDB`lldb_private::CommandInterpreter::HandleCommand(this=0x0000000117c7c1f0, command_line=<unavailable>, lazy_add_to_history=eLazyBoolNo, result=0x00007ffeefbfe978, override_context=0x0000000117c7c3d0, repeat_on_empty_command=<unavailable>, no_context_switching=<unavailable>) at CommandInterpreter.cpp:1812:14 [opt]
    frame #24: 0x00000001006a3a42 LLDB`lldb_private::CommandInterpreter::IOHandlerInputComplete(this=0x0000000117c7c1f0, io_handler=0x0000000117e8a908, line=<unavailable>) at CommandInterpreter.cpp:2850:3 [opt]
    frame #25: 0x00000001005e2a32 LLDB`lldb_private::IOHandlerEditline::Run(this=0x0000000117e8a908) at IOHandler.cpp:562:22 [opt]
    frame #26: 0x00000001005c85af LLDB`lldb_private::Debugger::RunIOHandlers(this=0x0000000117c7b800) at Debugger.cpp:866:16 [opt]
    frame #27: 0x00000001006a4cde LLDB`lldb_private::CommandInterpreter::RunCommandInterpreter(this=0x0000000117c7c1f0, options=0x00007ffeefbfecb0) at CommandInterpreter.cpp:3089:16 [opt]
    frame #28: 0x00000001003984d9 LLDB`lldb::SBDebugger::RunCommandInterpreter(this=0x00007ffeefbff178, auto_handle_events=<unavailable>, spawn_thread=<unavailable>) at SBDebugger.cpp:1178:42 [opt]
    frame #29: 0x000000010000568e lldb`Driver::MainLoop(this=<unavailable>) at Driver.cpp:675:18 [opt]
    frame #30: 0x0000000100006fb0 lldb`main(argc=<unavailable>, argv=<unavailable>) at Driver.cpp:932:26 [opt]
    frame #31: 0x00007fff68079cc9 libdyld.dylib`start + 1
    frame #32: 0x00007fff68079cc9 libdyld.dylib`start + 1
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 22.1
  * frame #0: 0x00000001005664c6 clang`llvm::AArch64FrameLowering::emitPrologue(this=<unavailable>, MF=<unavailable>, MBB=<unavailable>) const at AArch64FrameLowering.cpp:1505:9 [opt]
    frame #1: 0x0000000100e6cc81 clang`(anonymous namespace)::PEI::runOnMachineFunction(llvm::MachineFunction&) at PrologEpilogInserter.cpp:1097:9 [opt]
    frame #2: 0x0000000100e6cc36 clang`(anonymous namespace)::PEI::runOnMachineFunction(this=0x0000000110d04ec0, MF=<unavailable>) at PrologEpilogInserter.cpp:256 [opt]
    frame #3: 0x0000000100d8c14d clang`llvm::MachineFunctionPass::runOnFunction(this=0x0000000110d04ec0, F=0x0000000110b196b8) at MachineFunctionPass.cpp:73:13 [opt]
    frame #4: 0x00000001010a7cc1 clang`llvm::FPPassManager::runOnFunction(this=<unavailable>, F=0x0000000110b196b8) at LegacyPassManager.cpp:1516:27 [opt]
    frame #5: 0x00000001010ad948 clang`llvm::FPPassManager::runOnModule(this=0x0000000110e44a30, M=<unavailable>) at LegacyPassManager.cpp:1552:16 [opt]
    frame #6: 0x00000001010a831f clang`llvm::legacy::PassManagerImpl::run(llvm::Module&) at LegacyPassManager.cpp:1617:27 [opt]
    frame #7: 0x00000001010a8079 clang`llvm::legacy::PassManagerImpl::run(this=<unavailable>, M=0x0000000110b13510) at LegacyPassManager.cpp:614 [opt]
    frame #8: 0x0000000101a6e59f clang`clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::DataLayout const&, llvm::Module*, clang::BackendAction, std::__1::unique_ptr<llvm::raw_pwrite_stream, std::__1::default_delete<llvm::raw_pwrite_stream> >) at BackendUtil.cpp:979:19 [opt]
    frame #9: 0x0000000101a6ce7e clang`clang::EmitBackendOutput(Diags=<unavailable>, HeaderOpts=0x0000000110e2e700, CGOpts=<unavailable>, TOpts=0x0000000000000000, LOpts=0x0000000000000000, TDesc=0x0000000110e336c0, M=0x0000000110b13510, Action=Backend_EmitAssembly, OS=llvm::raw_pwrite_stream @ 0x00007ffeefbfc730) at BackendUtil.cpp:1692 [opt]
    frame #10: 0x0000000101d22c73 clang`clang::CodeGenAction::ExecuteAction(this=0x0000000110e316a0) at CodeGenAction.cpp:1173:5 [opt]
    frame #11: 0x0000000101fe6764 clang`clang::FrontendAction::Execute(this=0x0000000110e2f530) at FrontendAction.cpp:956:8 [opt]
    frame #12: 0x0000000101f8e193 clang`clang::CompilerInstance::ExecuteAction(this=0x0000000110e2d120, Act=0x0000000110e2f530) at CompilerInstance.cpp:1007:33 [opt]
    frame #13: 0x000000010205a41a clang`clang::ExecuteCompilerInvocation(Clang=<unavailable>) at ExecuteCompilerInvocation.cpp:284:25 [opt]
    frame #14: 0x000000010000420b clang`cc1_main(Argv=ArrayRef<const char *> @ 0x00007fd1d5bd6bd0, Argv0=<unavailable>, MainAddr=0x000000010000df20) at cc1_main.cpp:240:15 [opt]
    frame #15: 0x0000000100010f16 clang`ExecuteCC1Tool(ArgV=<unavailable>) at driver.cpp:330:12 [opt]
    frame #16: 0x0000000100010b53 clang`main(argc_=<unavailable>, argv_=<unavailable>) at driver.cpp:407:12 [opt]
    frame #17: 0x00007fff6ee27cc9 libdyld.dylib`start + 1
(lldb) 

参考文章

Canonical Frame Address

cfi 指令

* thread #1, queue = ‘com.apple.main-thread’, stop reason = breakpoint 79.1

* frame #0: 0x00000001006e0a88 LLDB`lldb_private::CompactUnwindInfo::ScanIndex(this=0x0000000120c1f270, process_sp=std::__1::shared_ptr<lldb_private::Process>::element_type @ 0x0000000119879c18 strong=6 weak=22) at CompactUnwindInfo.cpp:256:5

frame #1: 0x00000001006dd285 LLDB`lldb_private::CompactUnwindInfo::IsValid(this=0x0000000120c1f270, process_sp=std::__1::shared_ptr<lldb_private::Process>::element_type @ 0x0000000119879c18 strong=6 weak=22) at CompactUnwindInfo.cpp:239:3

frame #2: 0x00000001006dcca1 LLDB`lldb_private::CompactUnwindInfo::GetUnwindPlan(this=0x0000000120c1f270, target=0x0000000119873000, addr=Address @ 0x00007ffeefbfd8e8, unwind_plan=0x000000011813eae0) at CompactUnwindInfo.cpp:174:8

frame #3: 0x00000001007061d4 LLDB`lldb_private::FuncUnwinders::GetCompactUnwindUnwindPlan(this=0x000000011a5b7d60, target=0x0000000119873000) at FuncUnwinders.cpp:94:27

frame #4: 0x0000000100705790 LLDB`lldb_private::FuncUnwinders::GetUnwindPlanAtCallSite(this=0x000000011a5b7d60, target=0x0000000119873000, thread=0x000000011a525358) at FuncUnwinders.cpp:72:30

frame #5: 0x00000001007dcb0f LLDB`lldb_private::RegisterContextUnwind::GetFullUnwindPlanForFrame(this=0x0000000120c23350) at RegisterContextUnwind.cpp:906:41 [opt]

frame #6: 0x00000001007da9aa LLDB`lldb_private::RegisterContextUnwind::InitializeNonZerothFrame(this=0x0000000120c23350) at RegisterContextUnwind.cpp:548:29 [opt]

frame #7: 0x00000001007d90fe LLDB`lldb_private::RegisterContextUnwind::RegisterContextUnwind(this=0x0000000120c23350, thread=0x000000011a525358, next_frame=std::__1::shared_ptr<lldb_private::RegisterContextUnwind>::element_type @ 0x0000000120c225e0 strong=1 weak=2, sym_ctx=0x0000000120c21d00, frame_number=6, unwind_lldb=0x000000011861ab00) at RegisterContextUnwind.cpp:70:5 [opt]

frame #8: 0x000000010087548e LLDB`lldb_private::UnwindLLDB::GetOneMoreFrame(this=0x000000011861ab00, abi=0x000000011863cc10) at UnwindLLDB.cpp:128:40 [opt]

frame #9: 0x0000000100874ceb LLDB`lldb_private::UnwindLLDB::AddOneMoreFrame(this=0x000000011861ab00, abi=0x000000011863cc10) at UnwindLLDB.cpp:345:23 [opt]

frame #10: 0x00000001008759ff LLDB`lldb_private::UnwindLLDB::DoGetFrameInfoAtIndex(this=0x000000011861ab00, idx=5, cfa=0x00007ffeefbfe088, pc=0x00007ffeefbfe080, behaves_like_zeroth_frame=0x00007ffeefbfe0a7) at UnwindLLDB.cpp:402:36 [opt]

frame #11: 0x00000001007edf63 LLDB`lldb_private::StackFrameList::GetFramesUpTo(unsigned int) [inlined] lldb_private::Unwind::GetFrameInfoAtIndex(this=0x000000011861ab00, frame_idx=, cfa=0x00007ffeefbfe088, pc=0x00007ffeefbfe080, behaves_like_zeroth_frame=0x00007ffeefbfe0a7) at Unwind.h:53:12 [opt]

frame #12: 0x00000001007edf42 LLDB`lldb_private::StackFrameList::GetFramesUpTo(this=0x0000000120c06df8, end_idx=) at StackFrameList.cpp:502 [opt]

frame #13: 0x00000001007efc67 LLDB`lldb_private::StackFrameList::GetFrameAtIndex(this=0x0000000120c06df8, idx=) at StackFrameList.cpp:678:3 [opt]

frame #14: 0x00000001007f078a LLDB`lldb_private::StackFrameList::GetStatus(this=, strm=0x00007ffeefbfe988, first_frame=, num_frames=, show_frame_info=true, num_frames_with_source=0, show_unique=, selected_frame_marker="* “) at StackFrameList.cpp:989:16 [opt]

frame #15: 0x00000001008560be LLDB`lldb_private::Thread::GetStatus(this=0x000000011a525358, strm=0x00007ffeefbfe988, start_frame=0, num_frames=4294967295, num_frames_with_source=0, stop_format=, only_stacks=) at Thread.cpp:1814:45 [opt]

frame #16: 0x0000000100d0f8d6 LLDB`CommandObjectThreadBacktrace::HandleOneThread(this=0x0000000118234800, tid=1645774, result=0x00007ffeefbfe988) at CommandObjectThread.cpp:361:18 [opt]

frame #17: 0x0000000100d0f4b8 LLDB`CommandObjectIterateOverThreads::DoExecute(this=0x0000000118234800, command=0x00007ffeefbfe4a8, result=0x00007ffeefbfe988) at CommandObjectThread.cpp:85:23 [opt]

frame #18: 0x00000001006a98fa LLDB`lldb_private::CommandObjectParsed::Execute(this=, args_string=, result=0x00007ffeefbfe988) at CommandObject.cpp:993:19 [opt]

frame #19: 0x00000001006a0e88 LLDB`lldb_private::CommandInterpreter::HandleCommand(this=0x000000011860fa10, command_line=, lazy_add_to_history=eLazyBoolNo, result=0x00007ffeefbfe988, override_context=0x000000011860fbf0, repeat_on_empty_command=, no_context_switching=) at CommandInterpreter.cpp:1812:14 [opt]

frame #20: 0x00000001006ab115 LLDB`lldb_private::CommandObjectRegexCommand::DoExecute(this=, command=(Data = , Length = 0), result=0x00007ffeefbfe988) at CommandObjectRegexCommand.cpp:57:28 [opt]

frame #21: 0x00000001006a9ae2 LLDB`lldb_private::CommandObjectRaw::Execute(this=0x0000000118253e00, args_string="”, result=0x00007ffeefbfe988) at CommandObject.cpp:1015:17 [opt]

frame #22: 0x00000001006a0e88 LLDB`lldb_private::CommandInterpreter::HandleCommand(this=0x000000011860fa10, command_line=, lazy_add_to_history=eLazyBoolNo, result=0x00007ffeefbfe988, override_context=0x000000011860fbf0, repeat_on_empty_command=, no_context_switching=) at CommandInterpreter.cpp:1812:14 [opt]

frame #23: 0x00000001006a4252 LLDB`lldb_private::CommandInterpreter::IOHandlerInputComplete(this=0x000000011860fa10, io_handler=0x000000011a526cf8, line=) at CommandInterpreter.cpp:2850:3 [opt]

frame #24: 0x00000001005e2a92 LLDB`lldb_private::IOHandlerEditline::Run(this=0x000000011a526cf8) at IOHandler.cpp:562:22 [opt]

frame #25: 0x00000001005c860f LLDB`lldb_private::Debugger::RunIOHandlers(this=0x000000011860eec0) at Debugger.cpp:866:16 [opt]

frame #26: 0x00000001006a54ee LLDB`lldb_private::CommandInterpreter::RunCommandInterpreter(this=0x000000011860fa10, options=0x00007ffeefbfecc0) at CommandInterpreter.cpp:3089:16 [opt]

frame #27: 0x0000000100398c79 LLDB`lldb::SBDebugger::RunCommandInterpreter(this=0x00007ffeefbff188, auto_handle_events=, spawn_thread=) at SBDebugger.cpp:1178:42 [opt]

frame #28: 0x000000010000568e lldb`Driver::MainLoop(this=) at Driver.cpp:675:18 [opt]

frame #29: 0x0000000100006fb0 lldb`main(argc=, argv=) at Driver.cpp:932:26 [opt]

frame #30: 0x00007fff7066bcc9 libdyld.dylib`start + 1

frame #31: 0x00007fff7066bcc9 libdyld.dylib`start + 1

graph TD
    
        main
        
        subgraph Driver
            MainLoop
    end

    subgraph LLDB
        subgraph lldb::SBDebugger
          RunCommandInterpreter
        end
        
        subgraph CommandObjectIterateOverThreads
            DoExecute2["DoExecute"]
        end
        
        subgraph lldb_private
          subgraph CommandInterpreter
            RunCommandInterpreter2["RunCommandInterpreter"]
            IOHandlerInputComplete
            HandleCommand
          end

          subgraph Debugger
            RunIOHandlers
          end
          subgraph IOHandlerEditline::Run
            Run
          end
          
          subgraph CommandObjectRaw
              Execute
          end
          
          subgraph CommandObjectRegexCommand
              DoExecute
          end
          
          subgraph CommandObjectParsed
              Execute2["Execute"]
          end
          
          subgraph Thread
              GetStatus
          end
          
          subgraph StackFrameList 
              GetStatus2[GetStatus]-->
              GetFrameAtIndex-->
              GetFramesUpTo
          end
          
          subgraph unwind
              GetFrameInfoAtIndex
          end
          
          subgraph UnwindLLDB
              DoGetFrameInfoAtIndex-->
              AddOneMoreFrame-->
              GetOneMoreFrame
          end
          
          subgraph RegisterContextUnwind
              RegisterContextUnwind1[RegisterContextUnwind]-->
              InitializeNonZerothFrame-->
              GetFullUnwindPlanForFrame
          end
          
          subgraph FuncUnwinders
              GetUnwindPlanAtCallSite-->GetEHFrameUnwindPlan
              GetUnwindPlanAtCallSite-->GetCompactUnwindUnwindPlan
          end
          
          subgraph CompactUnwindInfo
              GetUnwindPlan-->
              IsValid-->
              ScanIndex
          end
          
          subgraph DWARFCallFrameInfo
              GetUnwindPlan-->GetFirstFDEEntryInRange-->GetFDEIndex-->GetCFIData
              
          end
        end
        
        subgraph CommandObjectThreadBacktrace
            HandleOneThread
        end
        
        DoExecute2-->HandleOneThread-->GetStatus-->GetStatus2
        
        GetFramesUpTo--2.开始解析帧信息-->GetFrameInfoAtIndex-->DoGetFrameInfoAtIndex
        GetOneMoreFrame-->RegisterContextUnwind1
        GetFullUnwindPlanForFrame-->GetUnwindPlanAtCallSite
        GetEHFrameUnwindPlan-->GetUnwindPlan
        GetCompactUnwindUnwindPlan-->GetUnwindPlan
    end
    
        main-->MainLoop--开始处理交互式命令-->RunCommandInterpreter-->RunCommandInterpreter2
        -->RunIOHandlers-->Run-->IOHandlerInputComplete-->HandleCommand
        -->Execute-->DoExecute["DoExecute(bt 会被转为 thread backtrace)"]-->HandleCommand-->Execute2-->DoExecute2


  • Debugger Provides a global root objects for the debugger core.

https://lldb.llvm.org/cpp_reference/classlldb__private_1_1IOHandlerEditline.html https://lldb.llvm.org/cpp_reference/classlldb__private_1_1CommandInterpreter.html

  • 文章目录
  • 站点概览
酷酷的哀殿

酷酷的哀殿

单身狗

45 日志
54 标签
友情链接
  • 麋鹿
  • 平凡的你我
  • 崩溃日志的栈帧缺失
  • 问题背景
  • 崩溃捕获 Backtrace(函数调用栈) 的原理
    • 什么是 Fast unwind?
    • 什么是 Backtrace(函数调用栈)
    • Fast unwind 测试
    • Fast unwind 实现原理
      • Fast unwind 机制演示
    • 栈帧 lowering
      • prolog(序章)
      • epilog(尾声)
    • bl 指令 与 编译器优化
      • bl 指令
      • 编译器优化
    • FastUnwind 机制原理小结
  • Xcode 的 unwind 机制
    • Xcode 与 lldb
  • lldb
    • 参考文章
© 2020 酷酷的哀殿
Powered by - Hugo v0.79.0
Theme by - NexT
0%