调用跟踪包含这样的条目:
[<deadbeef>] FunctionName+0xAB/0xCD [module_name]
[<f00fface>] ? AnotherFunctionName+0x12/0x40 [module_name]
[<deaffeed>] ClearFunctionName+0x88/0x88 [module_name]
“?”的含义是什么?在 AnotherFunctionName 之前标记?
最佳答案
'?'意味着有关此堆栈条目的信息可能不可靠。
堆栈输出机制(参见 dump_trace() function 的实现)无法证明它找到的地址是调用堆栈中的有效返回地址。
'?'本身由 printk_stack_address() 输出.
堆栈条目可能有效也可能无效。有时人们可能会跳过它。
调查相关模块的反汇编以查看在 ClearFunctionName+0x88
(或者,在 x86 上,紧接在该位置之前)调用了哪个函数可能会有所帮助。
关于可靠性
在 x86 上,当调用 dump_stack() 时,实际检查堆栈的函数是 print_context_stack()在 arch/x86/kernel/dumpstack.c
中定义。看看它的代码,我将在下面尝试解释它。
我假设 DWARF2 堆栈展开工具在您的 Linux 系统中不可用(如果不是 OpenSUSE 或 SLES,它们很可能不可用)。在这种情况下,print_context_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()
并将值输出为可靠的调用堆栈条目。否则该地址将被认为是不可靠的。它无论如何都会输出,但带有'?'前置。
[注意] 如果帧指针信息不可用(例如,默认情况下就像在 Debian 6 中一样),所有调用堆栈条目都将因此标记为不可靠。
具有 DWARF2 展开支持(并设置了 CONFIG_STACK_UNWIND)的系统完全是另一回事。
关于linux - Linux kernel panic call traces中的问号 '?'是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13113384/