日期:2014-05-16  浏览次数:20740 次

《coredump问题原理探究》Linux x86版5.4节C风格数据结构内存布局之数组coredump例子

试定位一个coredump的例子来验证一下。

堆栈:

(gdb) bt
#0  0x43756109 in __memset_sse2 () from /lib/libc.so.6
#1  0x08048643 in main ()

汇编:

(gdb) frame 1
#1  0x08048643 in main ()
(gdb) disassemble 
Dump of assembler code for function main:
   0x080485c0 <+0>:     push   %ebp
   0x080485c1 <+1>:     mov    %esp,%ebp
   0x080485c3 <+3>:     and    $0xfffffff0,%esp
   0x080485c6 <+6>:     sub    $0x30,%esp
   0x080485c9 <+9>:     movl   $0x0,0x18(%esp)
   0x080485d1 <+17>:    movl   $0x0,0x1c(%esp)
   0x080485d9 <+25>:    movl   $0x0,0x20(%esp)
   0x080485e1 <+33>:    movl   $0x0,0x24(%esp)
   0x080485e9 <+41>:    movl   $0x0,0x2c(%esp)
   0x080485f1 <+49>:    jmp    0x804860e <main+78>
   0x080485f3 <+51>:    movl   $0x20,(%esp)
   0x080485fa <+58>:    call   0x8048490 <_Znaj@plt>
   0x080485ff <+63>:    mov    %eax,%edx
   0x08048601 <+65>:    mov    0x2c(%esp),%eax
   0x08048605 <+69>:    mov    %edx,0x18(%esp,%eax,4)
   0x08048609 <+73>:    addl   $0x2,0x2c(%esp)
   0x0804860e <+78>:    cmpl   $0x3,0x2c(%esp)
   0x08048613 <+83>:    setle  %al
   0x08048616 <+86>:    test   %al,%al
   0x08048618 <+88>:    jne    0x80485f3 <main+51>
   0x0804861a <+90>:    movb   $0x0,0x2b(%esp)
   0x0804861f <+95>:    jmp    0x8048648 <main+136>
   0x08048621 <+97>:    movsbl 0x2b(%esp),%edx
   0x08048626 <+102>:   movsbl 0x2b(%esp),%eax
   0x0804862b <+107>:   mov    0x18(%esp,%eax,4),%eax
   0x0804862f <+111>:   movl   $0x20,0x8(%esp)
   0x08048637 <+119>:   mov    %edx,0x4(%esp)
   0x0804863b <+123>:   mov    %eax,(%esp)
   0x0804863e <+126>:   call   0x8048470 <memset@plt>

=> 0x08048643 <+131>:   addb   $0x1,0x2b(%esp)

   0x08048648 <+136>:   cmpb   $0x3,0x2b(%esp)
   0x0804864d <+141>:   setle  %al
   0x08048650 <+144>:   test   %al,%al
   0x08048652 <+146>:   jne    0x8048621 <main+97>
   0x08048654 <+148>:   mov    $0x0,%eax
   0x08048659 <+153>:   jmp    0x8048663 <main+163>
   0x0804865b <+155>:   mov    %eax,(%esp)
   0x0804865e <+158>:   call   0x80484b0 <_Unwind_Resume@plt>
   0x08048663 <+163>:   leave  
   0x08048664 <+164>:   ret    
End of assembler dump.

由于coredump是在这一条指令下出错:

0x08048643 <+131>:   addb   $0x1,0x2b(%esp)

由memset的原型:

       void *memset(void *s, int c, size_t n);

可知,会出现问题,要么,是第一个参数s非法,要么是n超出s的范围。

先看一下s是哪个,由

   0x08048626 <+102>:   movsbl 0x2b(%esp),%eax
   0x0804862b <+107>:   mov    0x18(%esp,%eax,4),%eax

   0x0804863b <+123>:   mov    %eax,(%esp)

可知,

s的值存放在esp+0x18+eax*4。而eax的值是由esp+0x2b得来的。

由movsbl可知,esp+0x2b存放着一个char型,所以,

(gdb) x /c $esp+0x2b
0xbf88c15b:     1 '\001'

  由

   0x08048621 <+97>:    movsbl 0x2b(%esp),%edx
   0x08048626 <+102>:   movsbl 0x2b(%esp),%eax
   0x0804862b <+107>:   mov    0x18(%esp,%eax,4),%eax
   0x0804862f <+111>:   movl   $0x20,0x8(%esp)
   0x08048637 <+119>:   mov    %edx,0x4(%esp)
   0x0804863b <+123>:   mov    %eax,(%esp)
   0x0804863e <+126>:   call   0x8048470 <memset@plt>

=> 0x08048643 <+131>:   addb   $0x1,0x2b(%esp)

   0x08048648 <+136>:   cmpb   $0x3,0x2b(%esp)
   0x0804864d <+141>:   setle  %al
   0x08048650 <+144>:   test   %al,%al
   0x08048652 <+146>:   jne    0x8048621 <main+97>

这个循环可知,esp+0x2