《coredump问题原理探究》Linux x86版7.4节List coredump例子

看一个coredump例子:


看一个coredump例子:
Core was generated by `./xuzhina_dump_c07_s2_ex'.
Program terminated with signal 11, Segmentation fault.
#0  0x0285b9b7 in std::_List_node_base::hook(std::_List_node_base*) ()
   from /usr/lib/libstdc++.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6_6.4.i686 libgcc-4.4.7-11.el6.i686 libstdc++-4.4.7-11.el6.i686
(gdb) bt
#0  0x0285b9b7 in std::_List_node_base::hook(std::_List_node_base*) ()
   from /usr/lib/libstdc++.so.6
#1  0x080488fd in std::list<int, std::allocator<int> >::_M_insert(std::_List_iterator<int>, int const&) ()
#2  0x08048784 in std::list<int, std::allocator<int> >::push_back(int const&)
    ()
#3  0x08048676 in main ()

查看一下崩溃函数的汇编:

0  0x0285b9b7 in std::_List_node_base::hook(std::_List_node_base*) ()
   from /usr/lib/libstdc++.so.6
(gdb) disassemble 
Dump of assembler code for function _ZNSt15_List_node_base4hookEPS_:
   0x0285b9a0 <+0>:	push   %ebp
   0x0285b9a1 <+1>:	mov    %esp,%ebp
   0x0285b9a3 <+3>:	mov    0xc(%ebp),%eax
   0x0285b9a6 <+6>:	mov    0x8(%ebp),%edx
   0x0285b9a9 <+9>:	mov    0x4(%eax),%ecx
   0x0285b9ac <+12>:	mov    %eax,(%edx)
   0x0285b9ae <+14>:	mov    %ecx,0x4(%edx)
   0x0285b9b1 <+17>:	mov    0x4(%eax),%ecx
   0x0285b9b4 <+20>:	mov    %edx,0x4(%eax)
=> 0x0285b9b7 <+23>:	mov    %edx,(%ecx)
   0x0285b9b9 <+25>:	pop    %ebp
   0x0285b9ba <+26>:	ret    
End of assembler dump.


看一下寄存器的值:

(gdb) i r
eax            0xbfedc248	-1074937272
ecx            0x0	0
edx            0x9309028	154177576
ebx            0x9faff4	10465268
esp            0xbfedc1c8	0xbfedc1c8
ebp            0xbfedc1c8	0xbfedc1c8
esi            0x0	0
edi            0x0	0
eip            0x285b9b7	0x285b9b7 <std::_List_node_base::hook(std::_List_node_base*)+23>
eflags         0x10282	[ SF IF RF ]
cs             0x73	115
ss             0x7b	123
ds             0x7b	123
es             0x7b	123
fs             0x0	0
gs             0x33	51

可见,是由于ecx的值为0所导致的。而ecx的值是由eax得来的,而eax的值则是从ebp+0xc上得来的。由于this指针放在ebp+0x8上,所以,ebp+0xc放置第一个参数。

由bits/stl_list.h:

   void  hook(_List_node_base * const  __position);

可知,是__position的_Prev的值为0.那么__position是从哪里来的?

根据堆栈和stl_list.h里的函数:

    void 
      _M_insert(iterator __position, const value_type& __x) 
      {    
        _Node* __tmp = _M_create_node(__x);
        __tmp->hook(__position._M_node);
      }    

void
      push_back(const value_type& __x)
      { this->_M_insert(end(), __x); }

可知,这个__position是end()的返回值,结合list的定义,可知,__position实际上是链表的尾部。

那么尾部的元素怎么可能是0呢?

看一下main函数:

(gdb) disassemble 
Dump of assembler code for function main:
   0x080485e4 <+0>:	push   %ebp
   0x080485e5 <+1>:	mov    %esp,%ebp
   0x080485e7 <+3>:	and    $0xfffffff0,%esp
   0x080485ea <+6>:	push   %esi
   0x080485eb <+7>:	push   %ebx
   0x080485ec <+8>:	sub    $0x38,%esp
   0x080485ef <+11>:	lea    0x18(%esp),%eax
   0x080485f3 <+15>:	mov    %eax,(%esp)
   0x080485f6 <+18>:	call   0x80486e6 <_ZNSt4listIiSaIiEEC2Ev>
   0x080485fb <+23>:	movl   $0x5,0x20(%esp)
   0x08048603 <+31>:	lea    0x20(%esp),%eax
   0x08048607 <+35>:	mov    %eax,0x4(%esp)
   0x0804860b <+39>:	lea    0x18(%esp),%eax
   0x0804860f <+43>:	mov    %eax,(%esp)
   0x08048612 <+46>:	call   0x8048750 <_ZNSt4listIiSaIiEE9push_backERKi>
   0x08048617 <+51>:	movl   $0x3,0x24(%esp)
   0x0804861f <+59>:	lea    0x24(%esp),%eax
   0x08048623 <+63>:	mov    %eax,0x4(%esp)
   0x08048627 <+67>:	lea    0x18(%esp),%eax
   0x0804862b <+71>:	mov    %eax,(%esp)
   0x0804862e <+74>:	call   0x8048786 <_ZNSt4listIiSaIiEE10push_frontERKi>
   0x08048633 <+79>:	lea    0x18(%esp),%eax
---Type <return> to continue, or q <return> to quit---
   0x08048637 <+83>:	mov    %eax,(%esp)
   0x0804863a <+86>:	call   0x80487bc <_ZNKSt4listIiSaIiEE4sizeEv>
   0x0804863f <+91>:	shl    $0x2,%eax
   0x08048642 <+94>:	mov    %eax,0x8(%esp)
   0x08048646 <+98>:	movl   $0x0,0x4(%esp)
   0x0804864e <+106>:	lea    0x18(%esp),%eax
   0x08048652 <+110>:	mov    %eax,(%esp)
   0x08048655 <+113>:	call   0x80484b8 <memset@plt>
   0x0804865a <+118>:	movl   $0x8,0x28(%esp)
   0x08048662 <+126>:	lea    0x28(%esp),%eax
   0x08048666 <+130>:	mov    %eax,0x4(%esp)
   0x0804866a <+134>:	lea    0x18(%esp),%eax
   0x0804866e <+138>:	mov    %eax,(%esp)
   0x08048671 <+141>:	call   0x8048750 <_ZNSt4listIiSaIiEE9push_backERKi>
=> 0x08048676 <+146>:	movl   $0xc,0x2c(%esp)
   0x0804867e <+154>:	lea    0x2c(%esp),%eax
   0x08048682 <+158>:	mov    %eax,0x4(%esp)
   0x08048686 <+162>:	lea    0x18(%esp),%eax
   0x0804868a <+166>:	mov    %eax,(%esp)
   0x0804868d <+169>:	call   0x8048750 <_ZNSt4listIiSaIiEE9push_backERKi>
   0x08048692 <+174>:	mov    $0x0,%ebx
   0x08048697 <+179>:	lea    0x18(%esp),%eax
   0x0804869b <+183>:	mov    %eax,(%esp)
---Type <return> to continue, or q <return> to quit---
   0x0804869e <+186>:	call   0x80486d2 <_ZNSt4listIiSaIiEED2Ev>
   0x080486a3 <+191>:	mov    %ebx,%eax
   0x080486a5 <+193>:	add    $0x38,%esp
   0x080486a8 <+196>:	pop    %ebx
   0x080486a9 <+197>:	pop    %esi
   0x080486aa <+198>:	mov    %ebp,%esp
   0x080486ac <+200>:	pop    %ebp
   0x080486ad <+201>:	ret    
   0x080486ae <+202>:	mov    %edx,%ebx
   0x080486b0 <+204>:	mov    %eax,%esi
   0x080486b2 <+206>:	lea    0x18(%esp),%eax
   0x080486b6 <+210>:	mov    %eax,(%esp)
   0x080486b9 <+213>:	call   0x80486d2 <_ZNSt4listIiSaIiEED2Ev>
   0x080486be <+218>:	mov    %esi,%eax
   0x080486c0 <+220>:	mov    %ebx,%edx
   0x080486c2 <+222>:	mov    %eax,(%esp)
   0x080486c5 <+225>:	call   0x8048518 <_Unwind_Resume@plt>
End of assembler dump.


   0x08048642 <+94>:	mov    %eax,0x8(%esp)
   0x08048646 <+98>:	movl   $0x0,0x4(%esp)
   0x0804864e <+106>:	lea    0x18(%esp),%eax
   0x08048652 <+110>:	mov    %eax,(%esp)
   0x08048655 <+113>:	call   0x80484b8 <memset@plt>
   0x0804865a <+118>:	movl   $0x8,0x28(%esp)
   0x08048662 <+126>:	lea    0x28(%esp),%eax
   0x08048666 <+130>:	mov    %eax,0x4(%esp)
   0x0804866a <+134>:	lea    0x18(%esp),%eax
   0x0804866e <+138>:	mov    %eax,(%esp)
   0x08048671 <+141>:	call   0x8048750 <_ZNSt4listIiSaIiEE9push_backERKi>
=> 0x08048676 <+146>:	movl   $0xc,0x2c(%esp)


可知,链表是放在esp+0x18的位置,并且用memset把链表两个值初始化为0.

 

源代码:

  1 #include <list>
  2 #include <string.h>
  3 
  4 int main()
  5 {
  6     std::list<int> list;
  7 
  8     list.push_back( 5 );
  9     list.push_front( 3 );
 10 
 11     memset( &list, 0, list.size()*sizeof( int ) );
 12 
 13     list.push_back( 8 );
 14     list.push_back( 12 );
 15 
 16     return 0;
 17 }





郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。