如何反向debugging工作?

GDB有一个支持反向debugging的新版本(参见http://www.gnu.org/software/gdb/news/reversible.html )。 我不知道这是如何工作。

为了反向debugging工作,在我看来,你需要存储整个机器状态,包括每一步的内存。 这会使性能变得难以置信,更不用说使用大量的内存。 这些问题如何解决?

我是gdb维护者,也是新的反向debugging的作者之一。 我很乐意谈谈它是如何工作的。 正如几个人所猜测的,你需要保存足够的机器状态,以便以后恢复。 有许多scheme,其中之一是简单地保存由每条机器指令修改的寄存器或存储单元。 然后,要“撤销”该指令,只需将这些寄存器或存储单元中的数据还原即可。

是的,这是昂贵的,但现代的cpus是如此之快,当你无论如何是互动(做步或断点),你并没有真正注意到这一点。

现在有一个教程可以帮助您开始使用gdb-7.0反向debugging: http : //www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial祝您好运!

请注意,您不能忘记使用模拟器,虚拟机和硬件录像机来执行反向执行。

另一个解决scheme是在物理硬件上跟踪执行,例如GreenHills和Lauterbach在其基于硬件的debugging器中完成的。 基于这条固定的每条指令的动作轨迹,可以通过依次移除每条指令的影响来移动到轨迹中的任意点。 请注意,这假定您可以跟踪影响debugging器中可见状态的所有内容。

另一种方法是使用Vmware Workstation 6.5和Virtutech Simics 3.0(及更高版本)使用的检查点+重新执行方法,这似乎是随Visual Studio 2010提供的。在这里,您使用虚拟机或模拟器在系统的执行上获得一个间接的等级。 您经常将整个状态转储到磁盘或内存,然后依靠模拟器能够确定性地重新执行完全相同的程序path。

简单来说,它是这样工作的:假设你正在执行一个系统的时间T。 要到时间T-1,从t <T点拿起一些检查点,然后执行(Tt-1)个周期,最后在你之前的一个周期结束。 这可以使工作得很好,甚至适用于执行磁盘IO的工作负载,由内核级代码组成,并执行设备驱动程序工作。 关键是要有一个模拟器,包含整个目标系统及其所有处理器,设备,存储器和IO。 有关更多详细信息,请参阅gdb邮件列表以及关于gdb邮件列表的讨论。 我经常使用这种方法来定期debugging棘手的代码,特别是在设备驱动程序和早期的操作系统启动中。

另一个信息来源是关于检查点的Virtutech白皮书 (我完全披露了这个白皮书 )。

在EclipseCon会话期间,我们还询问了他们如何使用Chronon Debugger for Java来做到这一点。 那个不允许你真正退后一步,但是可以播放一个录制的程序执行,这样的感觉就像是反向debugging。 (主要区别在于,您不能在Chronondebugging器中更改正在运行的程序,而在大多数其他Javadebugging器中则可以这样做)。

如果我正确地理解了它,它将操作正在运行的程序的字节码,以便logging程序内部状态的每一个变化。 外部状态不需要另外logging。 如果他们以某种方式影响你的程序,那么你必须有一个匹配该外部状态的内部variables(因此内部variables就足够了)。

在播放期间,他们基本上可以从logging的状态改变中重新创build正在运行的程序的每个状态。

有趣的是,国家的变化比人们期待的要小得多。 所以如果你有条件的“if”语句,你会认为你至less需要一个位来logging程序是否使用了then或else语句。 在许多情况下,甚至可以避免这种情况,就像那些不同的分支包含返回值一样。 那么仅logging返回值(无论如何将是需要的)并且从返回值本身重新计算关于执行的分支的决定就足够了。

尽pipe这个问题很老,大部分的答案也是如此,而且反向debugging仍然是一个有趣的话题,所以我发布了一个2015年的答案。 我的硕士论文的第1章和第2章, 在计算机编程中将反向debugging和实时编程结合起来进行视觉思维 ,涵盖了反向debugging的一些历史方法(尤其是关注快照(或检查点)和重放方法),以及解释它与全知debugging的区别:

计算机已经向前执行了程序,应该能够向我们提供关于它的信息。 这种改进是可能的,并且可以在所谓的全能debugging器中find。 它们通常被分类为反向debugging器,尽pipe它们可能更准确地被描述为“历史日志logging”debugging器,因为它们只是在执行期间logging信息以便稍后查看或查询,而不是允许程序员在执行程序中及时倒退。 “无所不知”来源于已logging的整个程序状态历史logging在执行后可供debugging器使用。 那么不需要重新运行程序,也不需要手动代码检测。

基于软件的全知debugging始于1969年的EXDAMS系统,称为“debugging时间历史回放”。 自2009年以来,GNUdebugging器GDB支持无所不知的debugging,具有“过程logging和重放”function。 TotalView,UndoDB和Chronon似乎是目前可用的最好的全能debugging器,但都是商业系统。 对于Java而言,TOD似乎是最好的开源替代scheme,它利用部分确定性重放,以及部分跟踪捕获和分布式数据库,以便logging所涉及的大量信息。

不仅允许导航logging,而且实际上能够在执行时间后退的debugging器也存在。 它们可以更准确地描述为准时,时间行程,双向或反向debugging器。

第一个这样的系统是1981年的COPE原型…

Nathan Fellman写道:

但是反向debugging只允许你回滚你input的下一步命令,还是允许你撤消任意数量的指令?

您可以撤消任何数量的指令。 举例来说,你并不仅限于在你前进的时候停下来的地方。 你可以设置一个新的断点并向后运行。

例如,如果我在一条指令上设置一个断点,并让它运行到那时,我可以回滚到前一条指令,即使我跳过了它?

是。 只要您在运行到断点之前打开录制模式。

以下是另一个称为ODB的反向debugging器的工作原理。 提取:

无所不知的debugging是在程序中的每个“兴趣点”(设置值,进行方法调用,抛出/捕获exception)中收集“时间戳”,然后允许程序员使用这些时间戳来探索该程序的历史运行。

ODB将代码插入到程序的类中,当程序运行时,事件被logging下来。

我猜gdb工作在同一种方式。

反向debugging意味着您可以向后运行程序,这对于追踪问题的原因非常有用。

您不需要为每个步骤存储整个机器状态,只需要更改。 这可能还是相当昂贵的。