0

我目前正在调试一个内核模块,为此,我使用调试信息构建了整个内核(产生 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来检查发生了什么(效果很好)。

4

2 回答 2

2

你没有说你使用的是什么版本的 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 中看到它。

于 2013-06-03T14:27:37.060 回答
0

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

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 很好地处理了断点。由于该技术与汤姆先前描述的技术相同,因此我将接受他的回答。

于 2013-06-11T07:44:53.567 回答