文章标题

抛开JOS不谈,一个函数在调用时,肯定要压入参数给函数体传值,然后要压入函数结束后的下一条指令的地址,以便函数可以正确的返回,其次因为公用一个堆栈所以要压入BP也就是基址寄存器的值,和在函数体中使用到的寄存器的值,以便返回时可以恢复现场。但是这些值压入的顺序和规则目前还是不知道的,需要一些额外的资料。
这里写图片描述
esp的含义是“这个地址以下的空间是未被使用的堆栈控件”,
ebp的含义是“这个地址以下至esp的空间是属于目前所执行函数的堆栈空间”,所以图中saved%ebp和 ret%eip就是属于调用此函数的函数的ebp和eip。
通过阅读汇编代码我们可以发现,一个函数在调用之前,其调用者会将参数压栈(顺序没深究,和编译器有关),也就是压入arg2 和arg1,
然后调用call,call的动作会把ret%eip压栈,同时转到函数体执行,在函数体执行的开头有一段预处理代码,也就是图中的prologue,会将ebp寄存器(call指令不改变ebp的值,此时的ebp还是上一个函数的)内容压栈,
然后将当前esp赋值给ebp,随后进行现场保存的工作,存储在local variables空间里,值得注意的是,在预处理时会一下申请足够的空间,包括保存现场所需空间,局部变量所需空间(这大概也就是标准C的变量声明需要放在函数开头的原因吧,为了方便编译器),调用其它函数所压入变量的空间,换句话说图中arg1,arg2是属于上一个函数的local variables空间,这也就是backtrace不能准确的判断出函数所传参数个数而统一要求打印出5个参数的原因。


int mon_backtrace(int argc,char** argv,struct Trapframe*tf)
{                 
  uint32_t *ebp,*eip;
   uint32_t   arg0,arg1,arg2,arg3,arg4;
 ebp=(uint32_t*)read_ebp();
 eip=(uint32_t*)ebp[1];
 arg0=ebp[2];
 arg1=ebp[3];
 arg2=ebp[4];
 arg3=ebp[5];
 arg4=ebp[6]; 
 cprintf("Stackbacktrace:\n");
 while(ebp!=0){    
 cprintf("ebp %08x eip %08x args %08x %08x %08x %08x %08x\n",ebp,eip ,arg0,arg1,arg2,arg3,arg4);
 ebp=(uint32_t*)ebp[0];
eip=(uint32_t*)ebp[1];
arg0=ebp[2];
arg1=ebp[3];
arg2=ebp[4];
arg3=ebp[5];
arg4=ebp[6];
}
return 0;
 }
int mon_backtrace(int argc,char** argv,struct Trapframe*tf)
{                 

 uint32_t *ebp;
 ebp=(uint32_t*)read_ebp();
 cprintf("Stackbacktrace:\n");
 while(ebp!=0x0){    
 cprintf("ebp %08x eip %08x args %08x %08x %08x %08x %08x\n",ebp,ebp[1],ebp[2],ebp[3],ebp[4],ebp[5],ebp[6]);
 ebp=(uint32_t*)ebp[0];
struct Eipdebuginfo info;
debuginfo_eip(ebp[1],&info);
cprintf("%s,%d,%.*s+%d\n",info.eip_file,
                           info.eip_line,
                           info.eip_fn_namelen,
                           info.eip_fn_name,
                           ebp[1]-info.eip_fn_addr      );
           ebp=(uint32_t*)ebp[0];
                           }
return 0;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值