【问题标题】:Edit and Continue on GDB在 GDB 上编辑并继续
【发布时间】:2010-11-29 12:16:02
【问题描述】:

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

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

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

【问题讨论】:

  • 这里不可能有真正的答案,这将是巨大的火焰和投反对票的诱饵。试试programmers.se,询问foss世界中的领导角色。
  • 汉斯,我真的不明白你的话。我相信我的问题结构合理:这是一个关于流行工具链和众所周知的调试器功能的具体问题;我想知道是否有任何重要的技术障碍阻止人们在 gcc/gdb 中实施 E&C,以及是否已经有任何已知的实施工作。
  • 嘿。我从不使用 E&C,但我仍然发现 Visual Studio 比 Eclipse 或任何其他基于 GCC/GDB 的组合好得多。这完全是由于编辑器和调试器之间的紧密集成,我更喜欢界面非常轻量级的方式(除非您选择使用更重的功能)。在我看来,没有其他 IDE 像这样易于使用或界面简洁。因此,我使用 VStudio 来开发 WITH GCC 和其他各种平台。
  • @Goz,这是品味和要求的问题。我更喜欢“强大”而不是“轻量级”,VC++ EE 与我上次使用它时的习惯相比缺乏很多。但是,我们不要在这里开始讨论。
  • 绝对我不反对......我只是指出 E&C 不是全部和结束:)

标签: c++ debugging gcc gdb edit-and-continue


【解决方案1】:

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

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

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

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

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

从 MS 生态系统到 GCC 生态系统,很容易想象 GDB/GCC/binutils 之间的复杂性和集成问题、无数的目标、一些所需的 EnC 特定目标抽象以及“很高兴拥有但EnC 的“无关紧要”性质,是它尚未出现在 GDB/GCC 中的原因。

黑客愉快!

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

【讨论】:

    【解决方案2】:

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

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

    17.改变执行

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

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

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

    【讨论】:

    • 如果我理解正确的话,E&C 是关于 gcc/g++ 和 gdb 的“修补”功能的便捷集成。如果 gdb 已经支持修补等功能,我很惊讶 E&C 在 gcc/gdb 工具链上并不常见。
    • 用 GDB 的说法,“修补”是相当有限的。它基本上允许在运行时重写可执行内核的部分内容,同时不提供 Jan Gray 在其出色答案中指出的真正重新编译所需的任何安全措施。
    【解决方案3】:

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

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

    这是一个sn-p:

    修复并继续是许多其他调试器实现的功能, 我们为此版本添加到我们的 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 Roadmap 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 博客中吹嘘它(这是正确的)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-28
      • 1970-01-01
      • 2012-12-03
      • 1970-01-01
      • 2017-02-15
      • 1970-01-01
      • 1970-01-01
      • 2017-10-02
      相关资源
      最近更新 更多