Call Trace包含以下条目:
[<deadbeef>] FunctionName+0xAB/0xCD [module_name]
[<f00fface>] ? AnotherFunctionName+0x12/0x40 [module_name]
[<deaffeed>] ClearFunctionName+0x88/0x88 [module_name]
'?'是什么意思?在AnotherFunctionName之前标记?
答案 0 :(得分:30)
'?'表示有关此堆栈条目的信息可能不可靠。
堆栈输出机制(参见dump_trace() function的实现)无法证明它找到的地址是调用堆栈中的有效返回地址。
'?'本身由printk_stack_address()输出。
堆栈条目可能有效或无效。有时人们可能会跳过它。
调查所涉及模块的反汇编可能会有所帮助,以查看在ClearFunctionName+0x88
(或在x86上,紧接该位置之前)调用哪个函数。
关于可靠性
在x86上,当调用dump_stack()时,实际检查堆栈的函数是arch/x86/kernel/dumpstack.c
中定义的print_context_stack()。看看它的代码,我将尝试在下面解释它。
我认为您的Linux系统中没有DWARF2堆栈展开功能(如果不是OpenSUSE或SLES,则很可能不是这样)。在这种情况下,print_context_stack()
似乎执行以下操作。
它从地址(代码中的'stack'变量)开始,保证是堆栈位置的地址。它实际上是dump_stack()
中局部变量的地址。
该函数重复递增该地址(while (valid_stack_ptr ...) { ... stack++}
)并检查它指向的内容是否也可以是内核代码中的地址(if (__kernel_text_address(addr)) ...
)。这样,当调用这些函数时,它会尝试查找函数的返回地址。
当然,并非每个看起来像返回地址的unsigned long值实际上都是返回地址。所以函数试图检查它。如果在内核代码中使用了帧指针(如果设置了CONFIG_FRAME_POINTER,则使用%ebp /%rbp寄存器),它们可用于遍历函数的堆栈帧。函数的返回地址位于帧指针的正上方(即%ebp/%rbp + sizeof(unsigned long)
)。 print_context_stack检查确切。
如果堆栈帧的值'stack'指向的是返回地址,则该值被视为可靠的堆栈条目。将使用ops->address
为reliable == 1
调用printk_stack_address()
,它最终将调用{{1}},并且该值将作为可靠的调用堆栈条目输出。否则该地址将被视为不可靠。无论如何它会输出但是'?'前缀。
[NB]如果帧指针信息不可用(例如,默认情况下就像在Debian 6中那样),由于这个原因,所有调用堆栈条目都将被标记为不可靠。
具有DWARF2展开支持(以及设置为CONFIG_STACK_UNWIND)的系统是另一个故事。