AIX:栈溢出

$cat memset.c(根据实际代码简化)

$xlc -g memset.c
$a.out
Illegal instruction(coredump)
$dbx a.out
Type 'help' for help.
[using memory image in core]
reading symbolic information ...

Illegal instruction (illegal opcode) in . at 0x0
warning: Unable to access address 0x0 from core

 

查看代码一时没看出什么问题。

用汇编调试了。

tracei: 0x1000038c (main+0x34) 4e800020        blr
[4] stopped in main at line 7

(dbx) registers
  $r0:0x00000000  $stkp:0x2ff229d0   $toc:0x20000710    $r3:0x00000000 
  $r4:0x00000017    $r5:0x00000000    $r6:0x00000000    $r7:0x00000000 
  $r8:0x00000000    $r9:0x00000000   $r10:0x2ff228d0   $r11:0x2ff22ccf 
 $r12:0x00000000   $r13:0xdeadbeef   $r14:0x00000001   $r15:0x2ff22a50 
 $r16:0x2ff22a58   $r17:0x00000000   $r18:0xdeadbeef   $r19:0xdeadbeef 
 $r20:0xdeadbeef   $r21:0xdeadbeef   $r22:0xdeadbeef   $r23:0xdeadbeef 
 $r24:0xdeadbeef   $r25:0xdeadbeef   $r26:0xdeadbeef   $r27:0xdeadbeef 
 $r28:0xdeadbeef   $r29:0xdeadbeef   $r30:0xdeadbeef   $r31:0xdeadbeef 
 $iar:0x1000038c   $msr:0x0002d0b2    $cr:0x44224804  $link:0x00000000 
 $ctr:0x00000000   $xer:0x20000020    $mq:0xdeadbeef 
          Condition status = 0:g 1:g 2:e 3:e 4:g 5:l 7:g
        [unset $noflregs to view floating point registers]
in main at line 7

 

 

lr寄存器里面地址是0x0000000,导致blr返回到一个错误的地址了。

为什么会这样,那得了解一下POWER平台的,函数调原理了。

 

当程序进入main函数是首先把lr寄存地址记录在r0里

tracei: 0x10000358 (main)    7c0802a6       mflr   r0
 

再将r0里面的地址写到函数栈里地址是,r1+0x148
tracei: 0x10000360 (main+0x8) 90010148        stw   r0,0x148(r1)

 

当函数退出的时候

将r1+0x148的值取得r0寄存器中,

tracei: 0x10000380 (main+0x28) 80010148        lwz   r0,0x148(r1)

然后将r0寄存器的值存到lr寄存中
tracei: 0x10000384 (main+0x2c) 7c0803a6       mtlr   r0
 然后根据lr寄存器的址进行跳转。
tracei: 0x1000038c (main+0x34) 4e800020        blr

 

 

如果看了以上流程大家应该明白问题出在哪里了。

memset的时候把保存栈里的返回地址给至成0了,导致最后报

这个错了错误了。

Illegal instruction in . at 0x0
0x00000000 00000000       Invalid opcode.

还没明白的话我们用tracei,监控保持地址的内存。就是r1+0x128;0x2ff229d0 +0x128=  0x2ff229d8;

(dbx) tracei  0x2ff229d8
[8] tracei 0x2ff229d8

tracei: 0x10000358 (main)    7c0802a6       mflr   r0
tracei: 0x1000035c (main+0x4) 9421fec0       stwu   r1,-320(r1)
tracei: 0x10000360 (main+0x8) 90010148        stw   r0,0x148(r1)
tracei: 0x10000364 (main+0xc) 38610040       addi   r3,0x40(r1)
after instruction 0x10000360:   0x2ff229d8 = 0x100001dc
[6] stopped in main at line 6
    6   memset(path,0,PATH_MAX);
(dbx) c
tracei: 0x10000368 (main+0x10) 38800000         li   r4,0x0
tracei: 0x1000036c (main+0x14) 38a003ff         li   r5,0x3ff
tracei: 0x10000370 (main+0x18) 48000051         bl   0x100003c0 (memset)   
tracei: 0x100003c0 (memset)    4800e00a         ba   0x0000e008
tracei: 0x10000374 (main+0x1c) 60000000        ori   r0,r0,0x0
after instruction 0x100003c0:   0x2ff229d8 = (nil)

 

#memset后地址变成nil,0x00000000了,

tracei: 0x10000378 (main+0x20) 38600000         li   r3,0x0
tracei: 0x1000037c (main+0x24) 48000004          b   0x10000380 (main+0x28)
tracei: 0x10000380 (main+0x28) 80010148        lwz   r0,0x148(r1)
tracei: 0x10000384 (main+0x2c) 7c0803a6       mtlr   r0
tracei: 0x10000388 (main+0x30) 38210140       addi   r1,0x140(r1)
tracei: 0x1000038c (main+0x34) 4e800020        blr
[4] stopped in main at line 7
    7   }

 

查看limits.h里面PATH_MAX,的值是1023。

 

总结上文。

1.栈上内存的错误实在比较难发现.xlc有提供编译选项,-qheapdebug,很令人失望,只能提供检查堆上面的错误

如果代码如下,是就能发现错

path= (char*)calloc(1, 256);

memset(path, 0, PATH_MAX);

 

2.令我想起久违的堆栈溢出,呵呵。0day.年纪大了已经很久没接触了,想不到今天在aix遇上了。

 

3.0x86汇编已经忘了差不多了,感觉在函数压栈这一块和power 差不多。那天有空在好好学习。

 

4.看来machine级别的调试还是要掌握的。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值