我目前正在调试内核模块,为此,我使用调试信息构建了整个内核(生成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
来检查发生了什么(效果很好)。
答案 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先前描述的技术相同,我接受他的回答。