20

我知道 E&C 是一个有争议的主题,有人说它鼓励错误的调试方法,但仍然 - 我认为我们可以同意在很多情况下它明显有用 - 尝试一些常量的不同值,重新设计 GUI 参数即时找到好看的外观...您的名字。

我的问题是:我们会在 GDB 上进行 E&C 吗?我知道这是一个特定于平台的功能,需要与编译器、调试器和操作系统进行认真的合作(MSVC 很容易做到这一点,因为编译器和调试器总是放在一个包中),但是......它仍然应该是可行的。我什至听说过苹果在他们的 GCC 版本中实现了它[需要引用]。我想说这确实是可行的。

知道所有关于 MSVC 的 E&C 的炒作(我的经验表明这是 MSVC 用户在被问到“为什么不切换到 Eclipse 和 gcc/gdb”时首先提到的),我很惊讶在多年之后 GCC/GDB 仍然没有有这样的特点。有什么好的理由吗?我们说话的时候有人在研究它吗?

4

3 回答 3

18

这是一个令人惊讶的非平凡工作量,包含许多设计决策和功能权衡。考虑:您正在调试。被调试者被挂起。它在内存中的图像包含源的目标代码,以及对象的二进制布局、堆、堆栈。调试器正在检查其内存映像。它已将有关符号、类型、地址映射、pc (ip) 的调试信息加载到源对应关系。它显示调用堆栈、数据值。

现在,您希望允许对代码和/或数据进行一组特定的可能编辑,而无需停止调试器并重新启动。最简单的可能是将一行代码更改为另一行。也许你重新编译那个文件或者只是那个函数或者只是那个行。现在,您必须修补被调试对象映像,以便在您下次跨过它或以其他方式运行它时执行该新代码行。这在引擎盖下是如何工作的?如果代码大于它替换的代码行会发生什么?它如何与编译器优化交互?也许您只能在专门为 EnC 调试目标编译的上执行此操作。也许您会限制可能的站点,它对 EnC 是合法的。考虑一下:如果您在调用堆栈中暂停的函数中编辑一行代码会发生什么。当代码返回那里时,它是运行函数的原始版本还是运行您的行更改的版本?如果是原始版本,该来源来自哪里?

您可以添加或删除本地人吗?这对挂起帧的调用堆栈有什么影响?目前的功能?

你能改变函数签名吗?向对象添加字段/从对象中删除字段?现有的实例呢?挂起的析构函数或终结器呢?等等。

要使任何类型的可用 EnC 工作,需要注意很多很多功能细节。然后有许多跨工具集成问题需要提供基础设施来为 EnC 供电。特别是,它有助于拥有某种调试信息存储库,可以将编辑前和编辑后的调试信息和目标代码提供给调试器。对于 C++,PDB 中可增量更新的调试信息会有所帮助。增量链接也可能有所帮助。

从 MS 生态系统到 GCC 生态系统,很容易想象 GDB/GCC/binutils 之间的复杂性和集成问题、无数的目标、一些需要的特定于 EnC 的目标抽象,以及“很好但无关紧要”的性质EnC,这就是为什么它还没有出现在 GDB/GCC 中的原因。

快乐黑客!

(ps 看看 Smalltalk-80 交互式编程环境可以做什么是很有启发性和启发性的。在 St80 中没有“重新启动”的概念——如果您编辑了图像的任何方面,图像及其对象内存始终是活动的。类你仍然必须继续运行。在这样的环境中,对象版本控制不是假设的。)

于 2010-12-14T15:31:52.967 回答
11

我不熟悉 MSVC 的 E&C,但 GDB 有你提到的一些东西:

http://sourceware.org/gdb/current/onlinedocs/gdb/Altering.html#Altering

17. 改变执行

一旦你认为你在你的程序中发现了一个错误,你可能想确定纠正明显的错误是否会导致在其余的运行中得到正确的结果。您可以通过实验找到答案,使用 gdb 功能更改程序的执行。

例如,您可以将新值存储到变量或内存位置,给程序一个信号,在不同的地址重新启动它,甚至从函数中提前返回。

赋值:给变量赋值
跳转:在不同的地址继续
信号:给你的程序一个信号
返回:从一个函数返回
调用:调用你程序的函数
补丁:给你的程序打补丁
编译和注入代码:在 GDB 中编译和注入代码

于 2010-11-29T12:33:27.670 回答
3

这是对“修复并继续”的旧 Apple 实现的一个很好的参考。它还引用了其他工作实现。

http://sources.redhat.com/ml/gdb/2003-06/msg00500.html

这是一个片段:

Fix and continue 是许多其他调试器实现的功能,我们在此版本的 gdb 中添加了该功能。Sun Workshop、SGI ProDev WorkShop、Microsoft 的 Visual Studio、HP 的 wdb 和 Sun 的 Hotspot Java VM 都以一种或另一种方式提供此功能。我的实现基于他们几年前添加的 HP wdb Fix and Continue 功能。尽管我的最终实现遵循了他们采用的方法的大致轮廓,但它们之间几乎没有共享代码。其中一些是由于架构差异(处理器和 ABI),但更多是由于实现设计差异。

请注意,此功能可能已在其工具链的更高版本中删除。

更新:2012 年 12 月 21 日有一个GDB 路线图PDF 演示文稿,其中包括描述“修复并继续”的幻灯片以及其他要点。该演示文稿的日期为 2012 年 7 月 9 日,因此也许有希望在某个时候添加此内容。该演示文稿是GNU Tools Cauldron 2012的一部分。

另外,我知道将 E&C 添加到 GDB 或 Linux 领域的任何地方对于所有不同的组件都是一项艰巨的工作。

但我不认为 E&C 有争议。我记得在 VB5 和 VB6 中使用过它,它可能在那之前就已经存在了。从很久以前开始,它就一直在 Office VBA 中。自 VS2005 以来,它一直在 Visual Studio 中。VS2003 是唯一一个没有它的,我记得开发人员为此大喊大叫。无论如何,他们打算将其添加回来,并且他们使用 VS2005 并且从那以后它就一直存在。它适用于 C#、VB 以及 C 和 C++。它在 MS 核心工具中已经存在 20 多年了,几乎是连续的(在独立时算上 VB),并减去了 VS2003。但是您仍然可以说他们在 VS2003 期间在 Office VBA 中拥有它;)

Jetbrains 最近也在他们的 C# 工具 Rider 中添加了它。他们在他们的 Rider 博客中吹嘘它(这是正确的 imo)。

于 2012-08-24T20:40:01.730 回答