如何获取特定帧的寄存器值?

时间:2016-03-05 07:34:20

标签: x86 solaris

> ffffff00bbcc8c40::findstack -v
stack pointer for thread ffffff00bbcc8c40: ffffff00bbcc86b0
[ ffffff00bbcc86b0 _resume_from_idle+0xf4() ]
  ffffff00bbcc86e0 swtch+0x145()
  ffffff00bbcc8710 cv_wait+0x61(ffffff1a4e538bb8, ffffff1a4e538a80)
  ffffff00bbcc8770 cv_wait_sig+0x26e(ffffff1a4e538bb8, ffffff1a4e538a80)
  ffffff00bbcc8850 so_dequeue_msg+0x2a4(ffffff1a4e538a60, ffffff00bbcc88b8, ffffff00bbcc8980, ffffff00bbcc88c0, 40)
  ffffff00bbcc8920 so_recvmsg+0x1af(ffffff1a4e538a60, ffffff00bbcc89b0, ffffff00bbcc8980, ffffff198dc34db0)
  ffffff00bbcc8960 socket_recvmsg+0x3d(ffffff1a4e538a60, ffffff00bbcc89b0, ffffff00bbcc8980, ffffff198dc34db0)
  ffffff00bbcc8a40 ksocket_recv+0x124(ffffff1a4e538a60, ffffff00bbcc8aac, 4, 40, ffffff00bbcc8a58, ffffff198dc34db0)
  ffffff00bbcc8a90 smb_sorecv+0x4e(ffffff1a4e538a60, ffffff00bbcc8aac, 4)
  ffffff00bbcc8ad0 smb_session_xprt_gethdr+0x35(ffffff23b1784c38, ffffff00bbcc8ae8)
  ffffff00bbcc8b20 smb_session_message+0x214(ffffff23b1784c38)
  ffffff00bbcc8b60 smb_session_receiver+0x8c(ffffff23b1784c38)
  ffffff00bbcc8b90 smb_server_receiver+0x28(ffffff23d5ff1ce8)
  ffffff00bbcc8c20 taskq_d_thread+0xb1(ffffff19f34ec258)
  ffffff00bbcc8c30 thread_start+8()

如何在每次函数调用时获取寄存器值? 我想我们可以使用框架指针,但我不知道如何。

更新:这不是实时分析。这是针对内核崩溃转储分析。

1 个答案:

答案 0 :(得分:0)

只知道帧指针会帮助你。 EBP在XORL %EAX, %EAX之前和之后是相同的。然后,碰巧x86指令集本身不依赖于任何特定的ABI。这意味着任何尝试这样做都需要你知道EIP,EBP(从那里你可以获得每个其他帧的EBP和EIP)和ABI,即使这样,一些(或所有)值也无法检索,取决于ABI。 EBP本身是一个通用寄存器,因此框架甚至不是强制性的(参见-fomit-frame-pointer)!

为此,我们假设cdecl ABI(大多数C编译器用于大多数C代码)。要研究当前函数的寄存器,只需查看它们即可。它们不可能有任何不同。然后,您需要能够从该功能返回。如果你的程序崩溃而且你不能这样做,那么你就搞砸了。在函数返回后,您可以查看除EAX,ECX和EDX之外的所有寄存器。这三个是“调用者保存”,也就是说,刚返回的函数可能已经修改而没有恢复它们。他们的内容很可能丢失。

然后,您可以继续,返回并调查除EAX,ECX和EDX之外的所有内容,一直到您想要的地方。无论如何,通过步进和类似的东西进行调试是个更好的主意。我认为你甚至不能从函数中返回(GDB不能,AFAIK)。