'?'意味着有关此堆栈条目的信息可能不可靠。
堆栈输出机制(参见dump_trace() function的实现)无法证明它找到的地址是调用堆栈中的有效返回地址。
'?'本身由printk_stack_address()输出。
堆栈条目可能有效或无效。有时可能会简单地跳过它。
调查相关模块的反汇编以查看在ClearFunctionName+0x88(或者,在 x86 上,紧邻该位置之前)调用了哪个函数可能会有所帮助。
关于可靠性
在 x86 上,当调用 dump_stack() 时,实际检查堆栈的函数是在 arch/x86/kernel/dumpstack.c 中定义的 print_context_stack()。看看它的代码,我会在下面尝试解释一下。
我假设 DWARF2 堆栈展开工具在您的 Linux 系统中不可用(如果不是 OpenSUSE 或 SLES,它们很可能不可用)。在这种情况下,print_context_stack() 似乎做了以下事情。
它从一个地址(代码中的“堆栈”变量)开始,该地址保证是堆栈位置的地址。它实际上是dump_stack() 中的一个局部变量的地址。
该函数重复增加该地址 (while (valid_stack_ptr ...) { ... stack++}) 并检查它指向的内容是否也可能是内核代码中的地址 (if (__kernel_text_address(addr)) ...)。这样,当调用这些函数时,它会尝试查找压入堆栈的函数的返回地址。
当然,并不是每个看起来像返回地址的无符号长整型值实际上都是返回地址。所以该函数试图检查它。如果内核代码中使用了帧指针(如果设置了 CONFIG_FRAME_POINTER,则使用 %ebp/%rbp 寄存器),它们可用于遍历函数的堆栈帧。函数的返回地址位于帧指针的正上方(即%ebp/%rbp + sizeof(unsigned long))。 print_context_stack 准确地检查了这一点。
如果存在一个堆栈帧,其值“stack”指向的堆栈帧是返回地址,则该值被认为是可靠的堆栈条目。 ops->address 将被reliable == 1 调用,它最终将调用printk_stack_address() 并且该值将作为可靠的调用堆栈条目输出。否则该地址将被视为不可靠。无论如何它都会输出,但带有'?前置。
[NB] 如果帧指针信息不可用(例如默认情况下在 Debian 6 中),所有调用堆栈条目都将因此被标记为不可靠。
具有 DWARF2 展开支持(并设置了 CONFIG_STACK_UNWIND)的系统完全是另一回事。