【问题标题】:How can I output a C + Assembly program trace using GDB?如何使用 GDB 输出 C + 汇编程序跟踪?
【发布时间】:2011-02-04 13:03:17
【问题描述】:

我正在调试一个讨厌的问题,其中#includeing 一个文件(不是我写的任何东西,为了记录)导致我的程序崩溃。这意味着,我有 workingbroken,只有一个 C(++) 包含语句已更改。我使用的一些库没有调试信息。

我想做的是让 GDB 输出为程序运行而执行的每一行 C++,以及 x86 指令在文本文件中不可用的格式,我可以区分这两个输出并希望弄清楚发生了什么错了。

这在 GDB 中很容易吗?

【问题讨论】:

    标签: c++ gdb


    【解决方案1】:

    您可以检查每个版本中预处理输出之间的差异。例如:

    gcc -dD -E a.cc -o a.pre
    gcc -dD -E b.cc -o b.pre
    diff -u a.pre b.pre
    

    您可以尝试不同的“-d”设置以使其更加详细/简洁。也许列表差异中的某些东西会很明显。它通常类似于结构,根据包含文件改变大小。

    否则,如果您真的想弄乱每个指令或行跟踪,您可能可以使用 valgrind 并查看路径分歧的地方,但我认为您可能会陷入痛苦的世界。实际上,您可能会发现 valgrind 找到了您的错误,然后发现了 100 个您不知道的错误:) 我认为问题只是结构或其他数据大小的差异,您无需费心。

    您可以让 gdb 自动进行线路跟踪。会很痛苦。基本上,您需要编写脚本以重复运行“n”(下一行)直到崩溃,然后检查日志。如果你可以编写“b main”脚本,然后是“run”,然后是无限的“n”就可以了。可能有一个内置命令可以执行此操作,但我不知道。

    【讨论】:

    • 以及#if/#else 结构等的变化,可能有一些静态初始化是错误的。如果存在一些依赖关系,#include 可能会更改它包含的其他内容的顺序,从而导致崩溃。或者,#include 文件可能会添加一个初始化失败的静态对象。 gcc -E 输出也是开始调查这些问题的好方法。如果将失败的#include 放在最后(因此其他包含的顺序不会更改),它可能会最大限度地减少差异噪声,然后查看它是否仍然中断。
    • 刚刚使用了一些组合来减少差异垃圾邮件。这可能会更好: gcc -E a.cc -o a.pre; ...; diff -uw -I'^#' a.pre b.pre
    • 感谢您的建议。问题最终是头文件(两级深!)有#pragma pack(1),最后没有相应的#pragma pack(pop),导致STL库被打包,显然GCC不喜欢.删除 pragma 并为受影响的结构切换到 __attribute__((packed)) 解决了这个问题。我最终通过删除一些东西直到我的程序没有崩溃,然后在我知道这是一个头问题后对每个级别包含的头文件进行 BFS 搜索来找到这个。
    • STL 不会喜欢它,因为静态/共享库将在没有打包结构的情况下进行编译。因此,您的代码将使用打包的结构,与预编译的 STL 库认为的大小和偏移量不匹配。遗憾的是 GNU binutils/gcc 中没有检测到这种情况的机制 - 你只需要注意所有头文件在所有编译单元中都以相同的方式解释。
    【解决方案2】:

    我不认为 GDB 可以做到这一点;不过,也许个人资料会有所帮助?你是用 gcc 编译的吗?看看 -p 和 -pf 命令,我认为它们可能有用。

    【讨论】:

      【解决方案3】:

      gdb提示符下的disassemble命令会反汇编你停止在的当前函数,但是我觉得输出整个执行路径不可行。

      你包括什么图书馆?如果它是开源的,您可以在启用调试符号的情况下重新编译它。此外,如果您使用的是 Linux,大多数发行版都有用于公共库的 -dbg 版本的软件包。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-22
        • 2015-12-15
        • 2013-05-26
        • 1970-01-01
        • 1970-01-01
        • 2011-11-02
        • 1970-01-01
        相关资源
        最近更新 更多