为什么缺少一些调试符号以及如何跟踪它们?

时间:2013-06-03 13:12:43

标签: c debugging gdb

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

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

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

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

编辑:根据Tom的回答,我尝试使用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来检查发生了什么(效果很好)。

2 个答案:

答案 0 :(得分:2)

您没有说出您正在使用的gdb版本。

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

然后有一些版本的gdb支持内联函数的断点,但只使用"文件:line"句法。那么你要做的就是在编辑器中查找函数,找到它的行号并输入,例如:

(gdb) break myfile.c:777

更新版本的gdb,从7.4或7.5(我忘记)开始将处理" break函数"如果"功能"就好了被内联了。

所有这一切只有在您拥有debuginfo时才有效。所以如果你试过这个,但它失败了,要么你有一个旧的gdb,要么你忘了使用-g。

在gdb中没有好办法看到编译中的哪些对象丢失了-g。但是,你可以通过运行" readelf -WS"来轻松地从shell中看到它。在.o文件上,并查找没有.debug_info部分的文件。

答案 1 :(得分:0)

将断点设置为函数的签名行不起作用。但是将一个设置为内联函数的指令行解决了我的问题。例如,考虑 myfile.c 中的以下函数inline_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处理。 由于该技术与Tom先前描述的技术相同,我接受他的回答。