C++ 实现中的异常处理:什么是展开库输入的用于破坏本地对象的“替代函数入口点”?

Exception Handling in C++ Implementation: What is the "alternative function entry point", entered by the unwinding library to destruct local objects?

提问人:alex35833 提问时间:7/16/2023 最后编辑:alex35833 更新时间:7/17/2023 访问量:147

问:

这是一个非常简单的 c++ 文件

class C {
public:
    C(){}
    ~C(){}
};

void g()
{
    throw std::exception();
}

void f()
{
    C c;
    g();
}

int main()
{
    return 0;
}

LLVM 生成以下内容(请注意我添加的评论,解释我的查询)。

00000000004044e0 <f()>:

  4044e0: 48 83 ec 18                   subq    $24, %rsp
  4044e4: 48 8d 7c 24 10                leaq    16(%rsp), %rdi
  4044e9: e8 52 00 00 00                callq   0x404540 <C::C()>
  4044ee: e8 6d 00 00 00                callq   0x404560 <g()>
  4044f3: e9 00 00 00 00                jmp 0x4044f8 <f()+0x18>
  4044f8: 48 8d 7c 24 10                leaq    16(%rsp), %rdi
  4044fd: e8 4e 00 00 00                callq   0x404550 <C::~C()>
  404502: 48 83 c4 18                   addq    $24, %rsp
  404506: c3                            retq


; Is this the alternative entry point? How does the unwiding mechanism (__cxa_throw()) reach here?
; Also, when reached here by __cxa_throw, %rax seems to point to an instant of struct _Unwind_Exception,
;which is saved on the stack, and later used as the 1st argument to _Unwind_resume?
; And what is %edx (presumably an int, set by the unwinding mechanism), which is unused here in this frame?
  404507: 48 89 c1                      movq    %rax, %rcx
  40450a: 89 d0                         movl    %edx, %eax
  40450c: 48 89 4c 24 08                movq    %rcx, 8(%rsp)
  404511: 89 44 24 04                   movl    %eax, 4(%rsp)
  404515: 48 8d 7c 24 10                leaq    16(%rsp), %rdi
  40451a: e8 31 00 00 00                callq   0x404550 <C::~C()>
  40451f: 48 8b 7c 24 08                movq    8(%rsp), %rdi
  404524: e8 37 51 0a 00                callq   0x4a9660 <_Unwind_Resume>
  404529: 0f 1f 80 00 00 00 00          nopl    (%rax)

引用自 llvm-documentaion

用于定义异常后继续调用的位置的术语称为登陆垫。LLVM 登陆垫在概念上是替代函数入口点(强调后加),其中异常结构引用和类型信息索引作为参数传入。登陆板保存异常结构引用,然后继续选择与异常对象的类型信息对应的 catch 块。

LLVM“着陆垫”指令用于将有关着陆垫的信息传达到后端。对于 C++,登陆板指令返回一个指针和整数对,分别对应于指向异常结构的指针和选择器值。

Landingpad 指令在父函数的属性列表中查找对要用于此 try/catch 序列的个性函数的引用。该指令包含 cleanup、catch 和 filter 子句的列表。

对上述内容的任何解释将不胜感激。

谢谢

C++ 异常 llvm 堆栈展开 libunwind

评论

0赞 Hans Passant 7/16/2023
llvm.org/docs/ExceptionHandling.html#asm-table-formats
0赞 alex35833 7/16/2023
@HansPassant 是否有任何指向源代码的链接可以“跳转到”替代函数入口点“?该地址存储在哪里?是在矮人调试信息中吗?哪个领域?谢谢

答: 暂无答案