问题标签 [stack-unwinding]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
234 浏览

c - 操作 x64 展开信息以匹配装配钩子

编辑:我似乎弄错了,回溯在 Linux 上的任何地方都能很好地工作——只有当从 ubuntu 上的 gdb 远程调试到远程窗口时,在 msvcrt 中输入内存分配函数之一后,stacktrace 才会被完全破坏。 . 该死的微软。

这发生在 64 位和 32 位窗口上,所以我不确定这与展开信息有关......

编辑:似乎添加 -g3 和 -Og 有助于解决某些程序中的部分问题,但问题仍然存在于其他程序中,无法在此处发布它们的源代码,因为它是我公司的 IP - 抱歉!

背景

我使用 gcc 编译 ubuntu->ubuntu 和 mingw 编译 ubuntu->windows。

我创建了一个跨平台(linux + windows)内存跟踪和泄漏检测库,它在第一条指令(不是 IAT/PLT 挂钩)上使用程序集字节补丁挂钩 malloc/calloc/realloc/free。

钩子重定向到一个门,该门检查钩子是否在当前线程中启用,如果是,则重定向到内存跟踪钩子函数,否则它只是重定向到实际函数的蹦床,如果它们被该线程禁用。

该库运行良好,可以检测 linux/windows 上的泄漏(可能适用于 mac,但我没有)。

我使用该库以编程方式检测代码中的泄漏,我可以在内存分配例程上安装回调并以编程方式引发断点(通过循环并等待调试器附加然后在回调中执行 asm("int3")),以便我可以在我的程序处于泄漏内存的调用中时附加到它。

一切正常,直到我尝试从回调中查看回溯,我知道这可能是因为展开信息可能不再与我的堆栈匹配,因为我通过插入的钩子例程插入了新的帧和数据。

编辑:如果我误认为展开信息与堆栈不匹配是回溯不正确的原因,请纠正我!

问题

我可以做一些小技巧来欺骗 GDB 从我的钩子回调中正确重建回溯吗?

我知道我可以使用 libdwarf 或其他东西手动行走和编辑展开信息,但我想这会非常麻烦和庞大。

所以我想知道是否有可能我可以做的黑客或作弊来欺骗 GDB 正确重建回溯?

如果没有简单的技巧或技巧,那么我解决此问题的所有选择是什么?

编辑:只是为了清除所有内容的确切调用顺序:

这是我要捕获回溯的“用户定义的回调”

0 投票
1 回答
234 浏览

gcc - 是否可以在目标文件上生成展开表

背景是我们有一个没有展开表的预构建目标文件,但不知何故 gcc unwind 在对象上回溯有问题。是否可以在没有源代码的情况下生成展开表?考虑到展开表是基于堆栈静态的,即使没有源代码也可以使用。

0 投票
1 回答
240 浏览

c++ - _Unwind_ 和 unw_ 函数(LLVM 的 libunwind)

我是 LLVM 的 libunwind 库的新手。能否请您告诉我libunwind提供的两组功能的目的和区别是什么:

  1. 带有前缀 _Unwind_ 的函数
  2. 带有前缀 unw_ 的函数
0 投票
0 回答
71 浏览

c++ - 为什么程序突然终止?

执行上述代码时,程序突然终止。

  1. 为什么会突然结束?
  2. 如何处理这种异常?

注意:这是在线测试中提出的。

0 投票
0 回答
905 浏览

rust - 在 `#![no_std]` 模式下是否可以解除恐慌?

是否可以在模式下解除恐慌#![no_std],例如使用自定义#[panic_handler]

0 投票
0 回答
104 浏览

c++ - 在异常期间 C++ 堆栈展开期间,本地异常值存储在哪里

我熟悉 C++ 异常的心理模型,以及如何以编程方式控制它。例如,此答案中的所有内容:SO Question on topic

然而,让我感到困惑的是,如果异常对象是在抛出堆栈帧中实例化的值,并且当前帧和任意数量的先前帧被展开,那么如何保留异常对象(catch 能够拦截的内容)所有拥有的本地人都被破坏(如果用 RAII 编写)合规性。为了使事情变得不那么容易理解,建议的模式是按value抛出,并按const&捕获...一个堆栈已经消失的值?...在​​很久以前被破坏的帧上引用一个可能未命名的值?我显然错过了一些东西。引用 exited-local-function-objects 是一个典型的新手错误,但在这种情况下,建议这样做。我推测与用户代码混合的 throw catch 模式是一种错觉,其实现完全不同,但这让我仍然想知道,(隐式未分配堆)异常对象存储在哪里,因此可以在运行时捕获它-变量位置,考虑到它的值似乎存储在其中的堆栈帧注定要立即展开?

编辑:受@RichardCritten 的“实现细节响应”启发的一些切题问题:如果异常对象被实例化为左值而不是抛出怎么办?如果这样的左值被参数化和争论,然后被另一个函数抛出(它保证仍然知道抛出上下文)怎么办?如果对象是用 new 分配的,并且它的引用被用来抛出怎么办?您是否被迫“按照建议使用例外,并相信它们会按照标准要求行事”?

0 投票
1 回答
120 浏览

c++ - 未捕获 C++ 异常,程序以中止终止

该程序在异常处理程序被捕获之前终止

我想处理异常处理程序,但程序在堆栈展开期间终止。我该怎么做才能确保在堆栈展开期间加入线程?

0 投票
1 回答
152 浏览

c++ - 如果一个对象是在本地创建的并在 C++ 中作为异常抛出,那么本地对象如何在其范围之外有效。即在 catch 块中?

在 try 块中,调用了函数“fun()”。在“fun”内部创建了一个“abc”类的本地对象,并引发了异常。这个本地对象在“catch”块中被捕获,并且打印了一个正确的值。由于这个对象是在本地创建的,它不应该打印“0(默认值)”,因为调用 throw 时会发生堆栈展开。

输出: 在 abc
内的 fun()内尝试:10

我的期望:在 abc
中的 fun()中尝试
:0

0 投票
2 回答
376 浏览

debugging - 为什么我们需要编译器发出的 DWARF eh_frame?

在调试期间或我们的代码遇到异常时,我eh_frame需要使用红色。stack unwinding

现在我的问题是,调试器不能只是遍历堆栈并通过查找rbp被推送或弹出来找出帧之间的边界吗?为什么我们需要发出额外的调试信息?

0 投票
1 回答
645 浏览

c - 使用 libunwind 实现异常

在编译器上工作,需要一些帮助来理解和使用 libunwind。这是我到目前为止所拥有的:

好吧,这已经很混乱了,但是一些上下文可能有助于证明奇怪的选择是正确的。我想做的是在调用throw_exception后的任何时候调用调用堆栈set_tryfoo以便展开堆栈并将CPU状态恢复到调用之后set_try但条件之前的状态。虽然这目前只是一个小型 C 程序,但我打算在编译器中使用这些函数的一般结构,以生成必要的函数调用(类似于在 C++ 中使用 g++ 完成异常的方式),这就是为什么我有label+goto 作为一种快速模仿我将要生成的程序集的方法。我尝试过使用 libunwind 的 setjmp 实现,但它不太适合我的用例。

我遇到的问题与unw_resume展开调用堆栈后的恢复位置有关。printf("This should never run\n")无论如何,似乎每次都会运行。我的理解是它应该将堆栈和 CPU 状态恢复到调用时存储的任何状态unw_getcontext,并且我认为存储的状态是正确的,因为 IP 寄存器(或 PC 寄存器,因为这是 x86_64)的值当我调用set_tryand时,光标中的内容完全相同throw_exception。我什至在调用 set_try 之后和条件之前多次跳入 gdb 来查看 PC 寄存器,并且每次都匹配打印输出。

我的问题是:

  • 我误会了unw_resume吗?
  • 我是否需要修改 PC (UNW_REG_IP) 寄存器?
  • 是否有其他地方(除了 nongnu.org 文档)我可以寻求有关 libunwind 的帮助?

提前致谢!