30

呼叫跟踪包含这样的条目:

 [<deadbeef>] FunctionName+0xAB/0xCD [module_name]
 [<f00fface>] ? AnotherFunctionName+0x12/0x40 [module_name]
 [<deaffeed>] ClearFunctionName+0x88/0x88 [module_name]

“?”是什么意思?在 AnotherFunctionName 之前标记?

4

1 回答 1

37

“?” 意味着有关此堆栈条目的信息可能不可靠。

堆栈输出机制(参见dump_trace() 函数的实现)无法证明它找到的地址是调用堆栈中的有效返回地址。

“?” 本身由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 寄存器),它们可用于遍历函数的堆栈帧。函数的返回地址位于帧指针的正上方(即 at %ebp/%rbp + sizeof(unsigned long))。print_context_stack 正是检查这一点。

If there is a stack frame for which the value 'stack' points to is the return address, the value is considered a reliable stack entry. ops->address will be called for it with reliable == 1, it will eventually call printk_stack_address() and the value will be output as a reliable call stack entry. Otherwise the address will be considered unreliable. It will be output anyway but with '?' prepended.

[NB] If frame pointer information is not available (e.g. like it was in Debian 6 by default), all call stack entries will be marked as unreliable for this reason.

The systems with DWARF2 unwinding support (and with CONFIG_STACK_UNWIND set) is a whole another story.

于 2012-10-29T07:18:33.353 回答