【问题标题】:Why are some debug symbols missing and how to track them?为什么缺少一些调试符号以及如何跟踪它们?
【发布时间】:2013-06-03 13:12:43
【问题描述】:

我目前正在调试一个内核模块,为此,我使用调试信息构建了整个内核(生成 kallsyms 等...)。

当我尝试nm my_module.ko 时,我得到了我的模块中包含的符号列表。一切都很好,只是有些符号有点丢失,因为它们没有出现在符号列表中。我对此的感觉是相关函数正在自动内联。

无论如何,当使用 qemu-kgdb/gdb 运行内核时,我可以看到调用了“缺失”函数。这意味着编译器没有将其清除,因为它从未在任何代码路径中使用过(因此是我的“感觉”)。

由于符号没有出现,我无法在其上设置断点,gdb 也不会展开它,以便我可以看到正在运行的代码路径 - 了解 我不知道如何告诉 gdb展开它
不幸的是,我想看看这部分代码路径......我该怎么做?

编辑:正如汤姆的回答中所建议的,我尝试使用file:line 语法,如下所示:

我的代码文件如下所示:

int foo(int arg) // The function that I suspect to be inlined - here is line 1
{
    /* Blabla */
    return 42;
}

void foo2(void)
{
    foo(0); // Line 9
}

我试过b file.c:1,断点被命中,但foo()函数没有展开。 当然,我正在生成调试符号,因为我还在foo2 设置了一个断点来检查发生了什么(效果很好)。

【问题讨论】:

  • 您是否尝试在特定行而不是符号上设置断点?此外,您可以强制编译器不要内联代码。
  • 您是否使用了一些剥离选项??

标签: c debugging gdb


【解决方案1】:

你没有说你使用的是什么版本的gdb。

非常旧的 gdb 版本不支持内联函数。 6.8 甚至 7.0 都是如此——我不记得了。您可以查看您的 gdb 的 NEWS 文件。

然后有一些版本的 gdb 支持内联函数上的断点,但只使用“file:line”语法。所以你要做的是在你的编辑器中查找函数,找到它的行号并输入,例如:

(gdb) break myfile.c:777

从 7.4 或 7.5(我忘记了)开始的最新版本的 gdb 如果“函数”被内联,则可以很好地处理“中断函数”。

所有这些只有在您有可用的调试信息时才有效。所以如果你尝试了这个,但失败了,要么你有一个旧的 gdb,要么你忘了使用 -g。

在 gdb 中没有很好的方法来查看编译中缺少哪些对象 -g。不过,通过在 .o 文件上运行“readelf -WS”并查找没有 .debug_info 部分的文件,您可以很容易地从 shell 中看到它。

【讨论】:

  • gdb --version 告诉我GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04。我使用语法“file:line”尝试了您的建议。当代码路径到达断点时,断点被很好地注册并标记为命中,但指令永远不会“解包”。
  • 我不知道“展开”是什么意思,抱歉。
  • 我的意思是调试器没有显示内联函数的内部指令,如果我使用 stepi 运行,我只会一遍又一遍地显示foo(0); 行。
【解决方案2】:

在函数的签名行设置断点不起作用。但是将一个设置为内联函数的指令行为我解决了这个问题。例如,考虑以下函数 inline_foo,在 myfile.c 中找到:

inline int inline_foo(int arg) // l.1
{
    int a_var = 0;
    do_smth(&a_var);
    do_some_other_thing(); // l.5
    if (a_var) {
        a_var = blob();
    } else {
        a_var = blub();
    return a_var; // l.10
}

我正在尝试b myfile.c:1,但似乎没有用。但如果我改为尝试b myfile.c:3,GDB 可以很好地处理断点。 由于该技术与 Tom 之前描述的技术相同,因此我会接受他的回答。

【讨论】:

    猜你喜欢
    • 2017-12-05
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2010-10-10
    相关资源
    最近更新 更多