首页
学习
活动
专区
圈层
工具
发布
21 篇文章
1
《coredump问题原理探究》Linux x86版6.3节有成员变量的类coredump例子
2
《coredump问题原理探究》Linux x86版6.5节虚函数的coredump例子
3
《coredump问题原理探究》Linux x86版6.8节多继承coredump例子
4
《coredump问题原理探究》Linux x86版7.2节vector coredump例子
5
《coredump问题原理探究》Linux x86版7.4节List coredump例子
6
《coredump问题原理探究》Linux x86版7.6节 Map coredump例子
7
《coredump问题原理探究》Linux x86版5.9节C风格数据结构内存布局之联合体
8
《coredump问题原理探究》Linux x86版6.1节C++风格数据结构内存布局之无成员变量的类
9
《coredump问题原理探究》Linux x86版6.2节C++风格数据结构内存布局之有成员变量的类
10
《coredump问题原理探究》Linux x86版4.5节函数的逆向之coredump例子
11
《coredump问题原理探究》Linux x86版5.1节C风格数据结构内存布局之引言
12
《coredump问题原理探究》Linux x86版5.2节C风格数据结构内存布局之基本数据类型
13
《coredump问题原理探究》Linux x86版5.3节C风格数据结构内存布局之数组
14
《coredump问题原理探究》Linux x86版5.4节C风格数据结构内存布局之数组coredump例子
15
《coredump问题原理探究》Linux x86版5.5节C风格数据结构内存布局之基本数据类型构成的结构体
16
《coredump问题原理探究》Linux x86版5.6节C风格数据结构内存布局之复合类型构成的结构体
17
《coredump问题原理探究》Linux x86版5.7节C风格数据结构内存布局之结构体数组
18
《coredump问题原理探究》Linux x86版5.8节C风格数据结构内存布局之结构体数组结构体coredump
19
《coredump问题原理探究》Linux x86版3.5节栈布局之-fomit-frame-pointer编译选项
20
《coredump问题原理探究》Linux x86版3.6节栈布局之gcc内嵌关键字
21
《coredump问题原理探究》Linux x86版3.8节栈布局之栈溢出coredump例子

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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1344510

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

堆栈:

代码语言:javascript
复制
(gdb) bt
#0  0x43756109 in __memset_sse2 () from /lib/libc.so.6
#1  0x08048643 in main ()

汇编:

代码语言:javascript
复制
(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是在这一条指令下出错:

代码语言:javascript
复制
0x08048643 <+131>:   addb   $0x1,0x2b(%esp)

由memset的原型:

代码语言:javascript
复制
       void *memset(void *s, int c, size_t n);

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

先看一下s是哪个,由

代码语言:javascript
复制
   0x08048626 <+102>:   movsbl 0x2b(%esp),%eax
   0x0804862b <+107>:   mov    0x18(%esp,%eax,4),%eax

代码语言:javascript
复制
   0x0804863b <+123>:   mov    %eax,(%esp)

可知,

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

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

代码语言:javascript
复制
(gdb) x /c $esp+0x2b
0xbf88c15b:     1 '\001'

  由

代码语言:javascript
复制
   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+0x2b存放着索引值,也就是说,在崩溃的时候,它正指向数组第二个元素。而数组的基地址是esp+0x18。而且由于

代码语言:javascript
复制
   0x0804862b <+107>:   mov    0x18(%esp,%eax,4),%eax

可知,它的步长是4,那么,这个数组的元素类型有可能是int,long(32-bit),指针(32-bit)。其中上面没有浮点操作的指令,所以,float可以排除。

由于,这个数组的元素是用于memset的第一个参数,所以,它应该是指针类型,且是在32-bit机器上。

看一下这个数组的第二个元素的值:

代码语言:javascript
复制
(gdb) x /wx $esp+0x18+4
0xbf88c14c:     0x00000000

也就是说,第二个元素为空指针,所以才会在memset里coredump。

看一下这个coredump的源代码:

代码语言:javascript
复制
  #include <stdlib.h>
  #include <string.h>
  int main()
  {
      int* ptrArray[4] = { NULL, };
 
      for ( int i = 0; i < 4; i += 2 )
      {
          ptrArray[i] = new int[8];
      }
  
      for ( char c = 0; c < 4; c++ )
      {
          memset( ptrArray[c], c, 8*sizeof(int) );
      }
  
      return 0;
  }

就可以知道ptrArray1由于第一个循环,确实没有分配到内存,仍然为空。

下一篇
举报
领券