资源描述:
《浅析vxWorks系统中如何抓取任务的函数调用轨迹.doc》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、这几天连续查了几个关于死机、网口死的问题,情况基本上都是任务m死了,包括大家有时看到的串口和网口都不响应,也往往都是由于任务停止切换而造成的。对于这类问题,我们一般感觉比较棘手,因为一旦网口串口全都拒绝响应z后,報个系统对于我们来说就是—个黑盒了,稈序员坐在显示器前边,只能束手无策望洋兴叹。这里结合我白己的--些经验和所知,试图为大家寻找到一种处理类似问题的思路,希望能够对大家有所帮助。其实大家都曾经看到过操作系统模块里边os_exc.c这个文件,但许多人并不知道它能够完成的真正功能和工作原理,要弄清楚这些,我们必须先初步了解一下vxWorks系统在函数调用过稈中的一些
2、底层实现机制,看看我们如何抓到指定任务的函数调用轨迹的,因为吃透了这些,我们就可以在必要的时候,抓取指定任务的函数调用栈,从而基木可以定位处任务吊死在哪个函数内部了。首先,PPC有32个通用寄存器(GPRS)和7个专用寄存器(SPRS),这里,作为上层软件的开发人员,大家并不需要去深入了解过多的操作系统细节,也无需对CPU的每个寄存器每根线都了如指掌,而只需将注意力集屮在我们所关心的通用寄存器gprkgpr3以及专用寄存器If、pc。它们的重要性是因为:在函数调用过程中,gprl就是sp,也就是函数的堆栈指针,gpr3是函数调用过程屮传参的第一个寄存器(函数实参从gpr
3、3开始顺序存放,如果寄存器放不下了,就会压入堆栈,然示执行跳转指令进入被调用函数,被调用函数再从这些事先约定的寄存器屮取出实参进行后续处理,同样,函数的返冋值也是存放在卫屮的),lr是函数调用过稈屮的返冋指令地址(也就是函数调用点的下一条指令地址),而pc是当前指令地址。上边的说法可能比较抽彖,有些不便于理解,那么我们看下边这个例了代码的汇编结果:intmyfunc2(inti){intj;j=0;j+二i;returnj;}intmyfund(){inti;intj;i二4*5;j=myfunc2(i);returnj;}相应的汇编代码如下,莫为乱花迷了眼,我们只需关
4、注红色部分即可:intmyfund()0x16764myfunc1:stwurl,OxffeS(rl)0xl67b8+0x004:mfsprr0,LR0xl67bc+0x008:stwr31,0x14(rl)0xl67c0+0x00c:stwrO,Oxlc(rl)0xl67c4+0x010:orr31,rl,rlinti;intj;i=4*5;0xl67c8+0x014:lirO,0x14(20)0xl67cc+0x018:stwrO,0x8(r31)j=myfunc2(i);0xl67d0+0x01c:lwzr3,0x8(r31)Oxl67d4+0x020:blmyf
5、unc20xl67d8+0x024:orr0,r3,r30xl67dc+0x028:stwr0,Oxc(r31)returnj;0xl67e0+0x02c:lwzr3,Oxc(r31)0xl67e4+0x030:bmyfuncl+0x340xl67e8+0x034:lwzrll,OxO(rl)0xl67ec+0x038:lwzr0,0x4(r11)0xl67f0+0x03c:mtsprLR,rO0xl67f4+0x040:lwzrBl,Oxfffc(rll)0xl67f8+0x044:orrl,rll,rll0xl67fc+0x048:blr从屮我们可以看出,函数myf
6、und是在指令地址0x167(14调用函数myfunc2,而下一条指令地址为0xl67d8(因为PPC的指令集全部都是4字节),而myfund函数的起始地址是0xl67b4,myfunc2函数的起始地址是0x16774。记住了这么几个数字,就已经足够我们分析函数调用的过程了,现在我们开始进入函数myfund刚刚进入时的前儿条指令,试图揭开其屮的奥秘。函数myfuncl的第一条指令“stwurl,0xffe8(rl)”,把寄存器rl的内容放到rl+0xffe8所指的内存屮去,举个例了,假设讨现在存放的是myfuncl的栈指针0xc4f3e8,那么0xc4f3e8+0xff
7、e8=0xc4f3d0,也就是说在内存地址0xc4f3d0处存入0xc4f3e8(如果把函数myfunc2也同时汇编出来,我们会发现0xc4f3d0实际上是函数myfunc2的堆栈起始地址,这里需要注意的是vxWorks压栈是从高地址向低地址压);随后的第二条指令“mfsprr0,LR”,将It的内容存入r0,也就是将函数myfunc1的返冋地址(即函数返冋后的下一条指令地址)存入询,也就是0xl67d8;第三条指令我们不关心;第四条指令“stwr0,Oxlc(rl)”,将r0的内容存入rl+0xlc的内存位置中去,联系上下文各地址进行分