首页 > 解决方案 > 修复异常原因后 GDB 恢复执行

问题描述

假设我有一个程序,在第 5 行有一个语句,它创建了一个算术异常:除以零。

当我run在 GDB 中执行程序时,我得到如下信息:

Program received signal SIGFPE, Arithmetic exception.
0x... in ... at prog.c:5

那时,我将除数变量更改为非零值 set var b=1,然后尝试从出现异常的同一语句中“恢复”。

使用该命令continue给出以下信息:

Program terminated with signal SIGFPE, Arithmetic exception.
The program no longer exists.

所以正确的方法是使用(而不是continue命令)一个像jump 5预期一样工作的命令。

是否有任何其他更简单的 GDB 命令来执行此操作而无需指定程序出现异常的行号?一行中可能有多个语句,因此使用行号寻址并非总是可行的。

我在 GDB 文档中找不到与此相关的任何内容。

标签: cdebugginggdb

解决方案


这种方法在一般情况下不起作用,特别是在优化开启的情况下

您所做的恰好适用于您的特定线路/案例。我们不能说太多,因为您没有发布代码。

变量b在内存中开始(在堆栈上或在全局内存中)。

在某些时候,它可能会出现在一个 FP 寄存器中(例如对于 x86,xmm*)。

所以,当你这样做时:set var b = 1你是在设置内存位置还是xmm寄存器?

即使假设每行只有一个语句,当你jump重新启动语句时(它可以包含多个 asm指令)。

我们还需要做些什么来确保所有其他值(寄存器、内存等)都处于语句前/指令前状态?

通过优化, 的值b可能已由先前xmm的语句缓存在寄存器中,而您正在执行的操作可能不会重新加载它 [从内存]jump

您要做的是重新启动指令。此时,指令的第二个参数可能是xmm寄存器或内存位置。我们怎么知道是哪一个?

此外,如果您有(例如):

a = get_a_value();
// several more statements ...
a /= b;  // line 5

然后,我们假设ais in (eg) xmm0[and bis in xmm1]。以下是伪asm:

fdiv %xmm0,%xmm1 // a /= b

[pseudo]fdiv指令对ain的值有什么作用%xmm0?指令之后的值a仍然是完整的还是%xmm0现在有一个部分/垃圾值?%xmm0失败指令之后的值取决于体系结构。如果值被丢弃,我们如何确定要放回的原始/正确值%xmm0

必须执行多少先前a的语句才能恢复 的正确值?

您可能必须反汇编“违规”指令并更改第二个参数的值。如果它是一个内存位置,请更改它。如果它是一个xmm*寄存器,你将不得不改变它。

而且,您必须确定必须做什么才能恢复a价值(无论它位于何处)。

您想要进行的修复需要在指令级别进行处理。语句级别太粗粒度。

您找不到有关此文档的原因是,您所做的在一般情况下不会很好地工作并且正在扭曲gdb

gdb旨在让您可以捕获此类异常,确定程序中的错误是什么,修复代码,重新构建并重新运行。

C [和/或机器代码] 的设计不允许像 Java/Perl/Python 之类的解释语言那样,允许从之前的点 [在调试器控制台中] 进行动态补丁和重新启动。


推荐阅读