分类:
2009-03-15 23:33:23
简单介绍:什么是EIP、ESP、EBP
堆栈是一种简单的数据结构,是一种只允许在其一端进行插入或删除的线性表。
允许插入或删除操作的一端称为栈顶,另一端称为栈底,对堆栈的插入和删除操作被称入栈和出栈。
有一组CPU指令可以实现对进程的内存实现堆栈访问。其中,POP指令实现出栈操作,PUSH指令实现入栈操作。
CPU的ESP寄存器存放当前线程的栈顶指针,
EBP寄存器中保存当前线程的栈底指针。
CPU的EIP寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。
实现原理:C函数调用时,首先将参数push入栈,然后push返回地址,接着将原来的EBP push入栈,然后将ESP的值赋给EBP,令ESP指向新的栈顶。而函数返回时,会将EBP的值赋予ESP,然后pop出原来的EBP的值赋予EBP指针。 更详细准确的信息请参考《linux内核完全剖析》一书中的"3.4.1 C函数调用机制"。
详细实现:
int
mon_backtrace(int argc, char **argv, struct Trapframe *tf)
{
// Your code here.
unsigned int ebp;
unsigned int eip;
unsigned int args[5];
unsigned int i;
ebp = read_ebp();
cprintf("Stack backtrace:\n");
do {
eip = *((unsigned int*)(ebp + 4));
for(i=0; i<5; i++)
args[i] = *((unsigned int*) (ebp + 8 + 4*i));
cprintf(" ebp %08x eip %08x args %08x %08x %08x %08x %08x\n",
ebp, eip, args[0], args[1], args[2], args[3], args[4]);
ebp = *((unsigned int *)ebp);
} while(ebp != 0);
return 0;
}
将此功能添加到monitor中,只需修改文件kern/monitor.c, 添加以下代码到变量struct Command commands[]中既可:
{ "mon_backtrace", "Backtrace functions call chain", mon_backtrace },