《coredump问题原理探究》Linux x86版7.5节 Map对象

先看一个例子:

  1 #include <map>
  2
  3 int main()
  4 {
  5     std::map<int,int> iMap;
  6
  7     iMap[5] = 6;
  8     iMap[8] = 20;
  9     iMap[2] = 80;
 10
 11     return 0;
 12 }

看一下汇编:

(gdb) disassemble main
Dump of assembler code for function main:
   0x080486e4 <+0>:	push   %ebp
   0x080486e5 <+1>:	mov    %esp,%ebp
   0x080486e7 <+3>:	and    $0xfffffff0,%esp
   0x080486ea <+6>:	push   %esi
   0x080486eb <+7>:	push   %ebx
   0x080486ec <+8>:	sub    $0x48,%esp
   0x080486ef <+11>:	lea    0x1c(%esp),%eax
   0x080486f3 <+15>:	mov    %eax,(%esp)
   0x080486f6 <+18>:	call   0x80487b6 <_ZNSt3mapIiiSt4lessIiESaISt4pairIKiiEEEC2Ev>
   0x080486fb <+23>:	movl   $0x5,0x34(%esp)
   0x08048703 <+31>:	lea    0x34(%esp),%eax
   0x08048707 <+35>:	mov    %eax,0x4(%esp)
   0x0804870b <+39>:	lea    0x1c(%esp),%eax
   0x0804870f <+43>:	mov    %eax,(%esp)
   0x08048712 <+46>:	call   0x8048830 <_ZNSt3mapIiiSt4lessIiESaISt4pairIKiiEEEixERS3_>
   0x08048717 <+51>:	movl   $0x6,(%eax)
   0x0804871d <+57>:	movl   $0x8,0x38(%esp)
   0x08048725 <+65>:	lea    0x38(%esp),%eax
   0x08048729 <+69>:	mov    %eax,0x4(%esp)
   0x0804872d <+73>:	lea    0x1c(%esp),%eax
   0x08048731 <+77>:	mov    %eax,(%esp)
   0x08048734 <+80>:	call   0x8048830 <_ZNSt3mapIiiSt4lessIiESaISt4pairIKiiEEEixERS3_>
   0x08048739 <+85>:	movl   $0x14,(%eax)
   0x0804873f <+91>:	movl   $0x2,0x3c(%esp)
   0x08048747 <+99>:	lea    0x3c(%esp),%eax
   0x0804874b <+103>:	mov    %eax,0x4(%esp)
   0x0804874f <+107>:	lea    0x1c(%esp),%eax
   0x08048753 <+111>:	mov    %eax,(%esp)
   0x08048756 <+114>:	call   0x8048830 <_ZNSt3mapIiiSt4lessIiESaISt4pairIKiiEEEixERS3_>
   0x0804875b <+119>:	movl   $0x50,(%eax)
   0x08048761 <+125>:	mov    $0x0,%ebx
   0x08048766 <+130>:	lea    0x1c(%esp),%eax
   0x0804876a <+134>:	mov    %eax,(%esp)
   0x0804876d <+137>:	call   0x80487a2 <_ZNSt3mapIiiSt4lessIiESaISt4pairIKiiEEED2Ev>
   0x08048772 <+142>:	mov    %ebx,%eax
   0x08048774 <+144>:	add    $0x48,%esp
   0x08048777 <+147>:	pop    %ebx
   0x08048778 <+148>:	pop    %esi
   0x08048779 <+149>:	mov    %ebp,%esp
   0x0804877b <+151>:	pop    %ebp
   0x0804877c <+152>:	ret
   0x0804877d <+153>:	mov    %edx,%ebx
   0x0804877f <+155>:	mov    %eax,%esi
   0x08048781 <+157>:	lea    0x1c(%esp),%eax
   0x08048785 <+161>:	mov    %eax,(%esp)
   0x08048788 <+164>:	call   0x80487a2 <_ZNSt3mapIiiSt4lessIiESaISt4pairIKiiEEED2Ev>
   0x0804878d <+169>:	mov    %esi,%eax
   0x0804878f <+171>:	mov    %ebx,%edx
   0x08048791 <+173>:	mov    %eax,(%esp)
   0x08048794 <+176>:	call   0x804861c <[email protected]>
End of assembler dump.

由0x080486f6可以看到,esp+0x1c是map的this指针.

在0x080486f6, 0x08048712,0x08048734, 0x08048756, 0x0804876d 打断点:

(gdb) b *0x080486f6
Breakpoint 1 at 0x80486f6
(gdb) b *0x08048712
Breakpoint 2 at 0x8048712
(gdb) b *0x08048734
Breakpoint 3 at 0x8048734
(gdb) b *0x08048756
Breakpoint 4 at 0x8048756
(gdb) b *0x0804876d
Breakpoint 5 at 0x804876d

先看一下map在调用构造函数前后的变化:

(gdb) r
Starting program: /home/xuzhina/code/s3/xuzhina_dump_c07_s3 

Breakpoint 1, 0x080486f6 in main ()
(gdb) x /8x $esp+0x1c
0xbffff2bc:	0x08048568	0x008702b8	0x0804b3c4	0xbffff2f8
0xbffff2cc:	0x08049659	0x028ea550	0x08048412	0x00000000
(gdb) ni
0x080486fb in main ()
(gdb) x /8x $esp+0x1c
0xbffff2bc:	0x08048568	0x00000000	0x00000000	0xbffff2c0
0xbffff2cc:	0xbffff2c0	0x00000000	0x08048412	0x00000000

参照bits/stl_map.h, bits/stl_tree.h里面的_Rb_tree_node_base, _Rb_tree_node, _Rb_tree, _Rb_tree_impl, map

的定义可知,头节点被初始化为

{

_M_key_compare = 0x08048568,

_M_color = 0x00000000,

_M_parent = 0x00000000,

_M_left = 0xbffff2c0,

_M_right = 0xbffff2c0,

_M_node_count = 0x00000000,

}

再看一下,当map放入第一个元素时,会变成什么样.

(gdb) c
Continuing.

Breakpoint 2, 0x08048712 in main ()
(gdb) ni
0x08048717 in main ()
(gdb) ni
0x0804871d in main ()
(gdb) x /8x $esp+0x1c
0xbffff2bc:	0x08048568	0x00000000	0x0804c008	0x0804c008
0xbffff2cc:	0x0804c008	0x00000001	0x00000005	0x00000000
(gdb) x /8x 0x0804c008
0x804c008:	0x00000001	0xbffff2c0	0x00000000	0x00000000
0x804c018:	0x00000005	0x00000006	0x00000000	0x00020fe1

可以看到头节点和第一个节点的值如下:


头节点


第一个节点


{

_M_key_compare = 0x08048568,

_M_color = 0x00000000,

_M_parent = 0x0804c008,

_M_left = 0x0804c008,

_M_right = 0x0804c008,

_M_node_count = 0x00000001,

}


{

_M_color = 0x00000001,

_M_parent = 0xbffff2c0,

_M_left = 0x00000000,

_M_right = 0x00000000,

_M_value_field.first = 0x00000005,

_M_value_field.second =0x00000006

}

继续进行探究,可以得出一堆这样的数据

(gdb) x /8x $esp+0x1c
0xbffff2bc:	0x08048568	0x00000000	0x0804c008	0x0804c048
0xbffff2cc:	0x0804c028	0x00000003	0x00000005	0x00000008
(gdb) x /8x 0x0804c008
0x804c008:	0x00000001	0xbffff2c0	0x0804c048	0x0804c028
0x804c018:	0x00000005	0x00000006	0x00000000	0x00000021
(gdb) x /8x 0x0804c048
0x804c048:	0x00000000	0x0804c008	0x00000000	0x00000000
0x804c058:	0x00000002	0x00000050	0x00000000	0x00020fa1
(gdb) x /8x 0x0804c028
0x804c028:	0x00000000	0x0804c008	0x00000000	0x00000000
0x804c038:	0x00000008	0x00000014	0x00000000	0x00000021

用图来表示则如下

由上面可以得出map的特征:

1.     map对象有五个成员_M_node_count标明map有多少个元素,三个指针分别指向树中最左的节点,树的根节点,树的最右节点,_M_color表明是红树还是黑树,_M_key_compare指向比较函数

2.     树的根节点的_M_parent指向头节点

3.     每一个节点的值都紧跟着_M_right

时间: 2024-08-05 21:40:04

《coredump问题原理探究》Linux x86版7.5节 Map对象的相关文章

《coredump问题原理探究》Linux x86版7.6节 Map coredump例子

定位一个map相关的coredump来熟悉一下: Core was generated by `./xuzhina_dump_c07_s3_ex 5 / 6'. Program terminated with signal 11, Segmentation fault. #0 0x00000000 in ?? () Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6_6.4.i686 libgcc-4.

《coredump问题原理探究》Linux x86版7.7节 set对象

看一下bits/stl_map和bits/stl_set可以看到map和set的定义如下: 84 template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>, 85 typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > 86 class map 87 { 88 public: 89 typedef

《coredump问题原理探究》Linux x86版7.3节List对象

先看一下例子: 1 #include <list> 2 3 int main() 4 { 5 std::list<int> lst; 6 7 lst.push_back( 0x12345678 ); 8 lst.push_front( 0xabcdef01 ); 9 lst.push_back( 0x24242522 ); 10 11 return 0; 12 } 再看一下汇编: (gdb) disassemble main Dump of assembler code for f

《coredump问题原理探究》Linux x86版7.1节vector对象

先看一下例子: 1 #include <vector> 2 3 int main() 4 { 5 std::vector<int> vec; 6 vec.push_back( 0xffeeffab ); 7 vec.push_back( 0xabcdef01 ); 8 vec.push_back( 0x12345678 ); 9 return 0; 10 } 看一下汇编: (gdb) b main Breakpoint 1 at 0x8048697 (gdb) r Starting

《coredump问题原理探究》Windows版 笔记

<coredump问题原理探究>Windows版 笔记 Debug 一.环境搭建 1.Win7捕获程序dump 2.Windbg符号表设置(Symbols Search Path) 二.WinDbg命令 三.函数栈帧 1.栈内存布局 2.栈溢出 3.栈的规律 4.定位栈溢出问题的经验方法 四.函数逆向 五.C内存布局 1.基本类型 2.数组类型 3.结构体 六.C++内存布局 1.类的内存布局 2.this指针 3.虚函数表及虚表指针 4.单继承 5.多继承(无公共基类) 七.STL容器内存布

《coredump问题原理探究》Linux x86版6.3节有成员变量的类coredump例子

在探究完类成员变量分布后,来定位一个coredump例子来实践一把: (gdb) bt #0 0x0804863c in xuzhina_dump_c06_s2_ex::print() () #1 0x08048713 in main () 看一下xuzhina_dump_c06_s2_ex::print的汇编: (gdb) disassemble 0x0804863c Dump of assembler code for function _ZN22xuzhina_dump_c06_s2_ex

《coredump问题原理探究》Linux x86版7.2节vector coredump例子

看一个coredump的例子: [[email protected] s1_ex]$ gdb xuzhina_dump_c07_s1_ex core.27776 GNU gdb (GDB) Red Hat Enterprise Linux (7.2-75.el6) Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses

《coredump问题原理探究》Linux x86版6.2节C++风格数据结构内存布局之有成员变量的类

上面一节已经探究出this指针的辨别,由this指针就可以看到类的内容.在这里,就由this指针来看一下类的成员变量是如何排列. 先看一个例子 1 #include <stdio.h> 2 class xuzhina_dump_c06_s2 3 { 4 private: 5 short m_c; 6 char m_d; 7 int m_e; 8 9 public: 10 xuzhina_dump_c06_s2( int a, int b ) 11 { 12 m_c = (short)(a +

《coredump问题原理探究》Linux x86版6.8节多继承coredump例子

下面看一个coredump的例子: (gdb) bt #0 0x08048662 in xuzhina_dump_c06_s5_ex_child::inheritFrom(char*, int) () #1 0x08048609 in main () 先看一下xuzhina_dump_c06_s5_ex_child::inheritFrom的汇编: (gdb) disassemble 0x08048662 Dump of assembler code for function _ZN28xuzh