linux - Linux kernel panic call tr​​aces中的问号 '?'是什么意思?

标签 linux linux-kernel kernel backtrace panic

调用跟踪包含这样的条目:

 [<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 tr​​aces中的问号 '?'是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13113384/

相关文章:

c - 内核编译但不会与 unistd.h 引用链接

linux - Linux 中存储的文本文件的字符编码在哪里?

c - 非root用户的setuid等效项

c++ - 使用 MapViewOfFile 发送结构并读取未知值

linux - 为什么内核需要虚拟寻址?

c - linux内核aio功能

time - clock_getres和内核2.6

linux - 终端 - 删除所有不包含 .mp3 文件的文件夹

使等待线程返回用户空间

c - 向设备发送数据时 UNIX read()/write() 的原子性