搜索
bottom↓
回复: 9

关于MIPS调用栈的打印问题,请教FFXX及各位高手

[复制链接]

出0入0汤圆

发表于 2011-2-20 14:21:05 | 显示全部楼层 |阅读模式
看了一篇关于MIPS调用栈的文章觉得不错,主要是讲对于GCC 的O2级别优化的时候会不使用mips的FP寄存器,在这种情况下应该怎么打印调用栈。

文章出处:
http://blog.csdn.net/jerryutscn/archive/2010/03/10/5365263.aspx

我对不优化的时候怎么打印调用栈还有一些问题,但是没办法给博主留言,放到这里请教一下大家,希望高手能帮忙解释一下。


就算用了O0的优化级别,下面的程序

   400e0c: 3c1c0fc0 lui  gp,0xfc0

  400e10: 279c79b4 addiu    gp,gp,31156

  400e14: 0399e021 addu gp,gp,t9

  400e18: 27bdffd8 addiu    sp,sp,-40

  400e1c: afbc0010 sw   gp,16(sp)

  400e20: afbf0020 sw   ra,32(sp)

  400e24: afbe001c sw   s8,28(sp)

  400e28: afbc0018 sw   gp,24(sp)

  400e2c: 03a0f021 move s8,sp

  400e30: afc40028 sw   a0,40(s8)

  400e34: afc5002c sw   a1,44(s8)

我想问当在这个函数里面想查看调用栈的时候,所有寄存器的信息都是放在 栈底 固定位置的,而SP和FP都指向了 栈顶 位置,我们怎么知道从哪里去取那些上一级函数的寄存器的值呢?或者说我们怎么知道开始那个移动sp的立即数是多少呢(addiu sp,sp,-40)?

我一直按照x86的ebp esp来理解 fp和sp的,但是现在觉得不对。

请帮忙讲讲我哪里理解错了,谢谢

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2011-2-20 16:01:48 | 显示全部楼层
楼主链接里面的文章不错,有空细看.

但对楼主的问题,没有明白,楼主需要做什么?

出0入0汤圆

 楼主| 发表于 2011-2-20 16:16:43 | 显示全部楼层
感谢 回复

问题是怎么在mips架构下面打印调用栈,就是在程序出现异常的时候,或者在打断言的时候希望把出错误程序的调用关系打印出来。

引用那篇文章主要讲的就是mips结构下面怎么得到调用栈的问题

这是里面的一个问题
How to traceback call stack on MIPS arch?
Gcc saves the frame pointer to fp(s8) register at the beginning of each function if compiling source with -O0. But  it won't do so if compiling source with -O2. Without frame pointers, can I trace back call stacks in current function context? Or is there any option which forces gcc to save frame pointers for MIPS arch?
大概意思是如果采用O2优化,编译完成的程序会不使用FP(S8),这样该如何traceback 的问题 。



可是我想问的问题是就算用了O0优化,也就是就算用了FP,我也没弄清楚怎么才能得到调用栈(也就是怎么才能traceback)。主要的问题就在上面的帖子里面。

出0入0汤圆

发表于 2011-2-21 21:29:10 | 显示全部楼层
有了FP就可以做栈回溯了,这个需要看相关指令构架的过程调用标准。类似于ARM指令,它也有一个这样的东西。

但是用了FP,那么栈就会需要更多,所以当做优化时(或为了体积考虑时,例如thumb/thumb2),这个时候FP就不再使用了,这样的话要做栈回溯就比较困难了。

出0入0汤圆

 楼主| 发表于 2011-2-21 22:40:52 | 显示全部楼层
文章也是这个意思,我也觉得应该是这个意思。但是您看这个程序

400e18: 27bdffd8 addiu    sp,sp,-40

  400e1c: afbc0010 sw   gp,16(sp)

  400e20: afbf0020 sw   ra,32(sp)

  400e24: afbe001c sw   s8,28(sp)


每个函数开头的移动SP的立即数都是不一样的(比如这里面的-40),而存储FP的地址都是相对于移动以后的SP的地址(这里面是28)

看了几个函数,相对固定的是距离SP移动前的值的位置(估计这也是规范规定的),也就是说所有函数的FP都存在这个新开辟的内存空

间里面距离顶端12个字节的位置。

但是我想问,在程序中想打印调用栈的时候,无论是FP还是SP都已经移动了一个立即数了,这个数的大小肯定是没有规律的,你也就没

办法知道新开辟的堆栈空间的顶端在哪个位置,那你怎么能找到FP的值呢?

出0入0汤圆

发表于 2011-2-22 12:52:22 | 显示全部楼层
MIPS的帧回溯还真没研究过,

说说ARM的,ARM的仅指ARM指令部分,THUMB指令部分没这个东西。

ARM上把几个寄存器重命名了:
R14         lr
R13         sp
R11         fp

这三个寄存器在每次做标准过程调用时都需要最后压栈,即压入栈的最底端。每次标准过程调用时,压入栈的部分称为一帧。一帧的最底端就是上面的三个寄存器。

然后当前运行时,fp寄存器要么是0(当前过程无被调用),要么指向最后的一个帧。通过这样,将在栈上面建立一个帧的链表,而链表的表头则是当前的fp寄存器指向。ARM指令的在RT-Thread的arm\common目录下有实现相应的栈回溯代码,可以配合参考一起看。

出0入0汤圆

 楼主| 发表于 2011-2-22 23:03:49 | 显示全部楼层
感谢ffxx 详细的解释 !!!

还有以下问题

不知道thumb2指令集和arm的一样不一样。

随便找了一个cortex-m3 函数调用的例子(thumb2和arm不一样么? 我没看见保存sp和FP的值啊,而且我已经是O0优化了)。

0x00002320 E92D4FF7  PUSH     {r0-r2,r4-r11,lr}    //这里怎么没保存SP的值啊?而却也没看到保存FP的值,这样可怎么traceback呀
0x00002324 B082      SUB      sp,sp,#0x08
0x00002326 4604      MOV      r4,r0
0x00002328 460D      MOV      r5,r1
   553:          unsigned short cnt,total_cnt=0,xtra,alloced=0;
   554:          BYTE i;
   555:          char ret;
   556:          dir_entry* entry;
0x0000232A 2700      MOVS     r7,#0x00
0x0000232C 2000      MOVS     r0,#0x00
0x0000232E 9000      STR      r0,[sp,#0x00]
   557:         if(!f->isopen || !count) return 0;        // 文件没打开或数据量为0
0x00002330 7F20      LDRB     r0,[r4,#0x1C]
0x00002332 B108      CBZ      r0,0x00002338
0x00002334 9804      LDR      r0,[sp,#0x10]
0x00002336 B918      CBNZ     r0,0x00002340
0x00002338 2000      MOVS     r0,#0x00

【引用】这三个寄存器在每次做标准过程调用时都需要最后压栈,即压入栈的最底端。每次标准过程调用时,压入栈的部分称为一帧。一帧的最底端就是上面的三个寄存器。

有以下问题想请教

1 请问到底什么是帧,从上面的程序看,是说PUSH     {r0-r2,r4-r11,lr} 压入的 r0-r2,r4-r11,lr叫一帧还是说整个为这个函数开辟的堆栈空间(r0-r2,r4-r11,lr加上后面为局部变量开辟的8个字节)叫一帧。(应该是前面的叫一帧吧)

2 根据理解和您上面讲的,应该有一个帧指针指向PUSH     {r0-r2,r4-r11,lr}以后SP的值(我这种理解对么?)但为什么从程序里面看不到呢?thumb2 怎么traceback呢?

3 您能提供一个类似上面的例子么 ,可以看到保存SP和FP的?

问题有点基础,希望ffxx能不吝赐教。感谢

出0入0汤圆

发表于 2011-2-23 06:54:06 | 显示全部楼层
我上面也说了,thumb是没有这个东西的,所以在thumb下搞这个东西比较困难。当然thumb也有它的特点,即压入栈的函数调用(或回溯地址)是奇地址,那么奇地址 + 在代码段内,能够近似的获得回溯调用关系。

你可以找个ARM模式的看看,例如AT91SAM7、s3c2440等。

BTW, my name is ffxz.

出0入0汤圆

 楼主| 发表于 2011-2-23 22:12:55 | 显示全部楼层
真不好意思哈 ffxz。



我用的是MDK3.8 没找到相关的例子,

我这里有一个svn的分支http://rt-thread.googlecode.com/svn/branches/rtt_0_3_1 取下来的代码,看bsp目录里面有一个mini2440,但是打不开工程啊,现在这个分支也更新不了了。

请问现在最新分支的地址是多少呢? 看了一下置顶的帖子没找到。


感谢

出0入0汤圆

发表于 2011-2-24 09:12:29 | 显示全部楼层
是这个地址:http://rt-thread.googlecode.com/svn/trunk

不过mini2440都无配套的工程文件(不知道现在svn上自动生成的工程文件是否能够编译通过),用mini2440还是使用命令行编译吧
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 08:33

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表