2016-03-05 93 views
1
> 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() 

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

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

回答

0

只知道帧指针会帮助你。在XORL %EAX, %EAX之前和之后,EBP将是相同的。然后,碰巧x86指令集本身并不与任何特定的ABI绑定。这意味着任何尝试这样做都需要你知道EIP,EBP(从那里你可以得到每隔一帧的EBP和EIP)和ABI,即使如此,一些(或全部)值也不可能检索,这取决于ABI。 EBP本身是一个通用寄存器,因此帧甚至不是强制性的(参见)!

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

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

+0

在'gdb'中,您可以使用'finish'命令('f')单步执行,直到当前函数返回。除非你知道'ESP'当前指向正确的位置,否则一般不能返回该函数的其余部分。然后你可以在函数结尾的开头继续执行。另外,gdb有一些记录历史的方法,让你及时退后一步。我忘记了它是什么;我发现它来自Jester的评论之一,但从那时起我就不再需要它了,所以我还没有自己尝试过。 –

+0

我错过了之前提到它,这是为了进行内核崩溃转储分析。 – Iceman

+0

@Iceman:这是更糟糕的情况!我的意思是,调试内核有时可能是一个非常不同的过程。然后,它发生,因为你有一个崩溃转储,而不是一个正在运行的进程,你没有办法从崩溃的功能返回。 – 3442

相关问题