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

来源:互联网 发布:微商领袖软件 编辑:程序博客网 时间:2024/04/29 23:31

定位一个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.4.7-11.el6.i686 libstdc++-4.4.7-11.el6.i686(gdb) bt#0  0x00000000 in ?? ()#1  0x08048bd0 in main ()(gdb) i r eax            0x55ecx            0x00edx            0x00ebx            0x66esp            0xbfd3de7c0xbfd3de7cebp            0xbfd3dee80xbfd3dee8esi            0x00edi            0x00eip            0x00eflags         0x210296[ PF AF SF IF RF ID ]cs             0x73115ss             0x7b123ds             0x7b123es             0x7b123fs             0x00gs             0x3351

由于栈顶的指令地址为0x0,而eip的值也是0x0,可以知道是调用了函数指针,且函数指针的值为空.而这个函数指针是由main函数调用

看一下main函数的汇编:

(gdb) disassemble Dump of assembler code for function main:   0x0804898f <+0>:push   %ebp   0x08048990 <+1>:mov    %esp,%ebp   0x08048992 <+3>:and    $0xfffffff0,%esp   0x08048995 <+6>:push   %esi   0x08048996 <+7>:push   %ebx   0x08048997 <+8>:sub    $0x58,%esp   0x0804899a <+11>:cmpl   $0x3,0x8(%ebp)   0x0804899e <+15>:jg     0x80489b6 <main+39>   0x080489a0 <+17>:movl   $0x8049ce4,(%esp)   0x080489a7 <+24>:call   0x804883c <puts@plt>   0x080489ac <+29>:mov    $0xffffffff,%ebx   0x080489b1 <+34>:jmp    0x8048c42 <main+691>   0x080489b6 <+39>:lea    0x18(%esp),%eax   0x080489ba <+43>:mov    %eax,(%esp)   0x080489bd <+46>:call   0x8048c6e <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEC2Ev>   0x080489c2 <+51>:lea    0x37(%esp),%eax   0x080489c6 <+55>:mov    %eax,(%esp)   0x080489c9 <+58>:call   0x804887c <_ZNSaIcEC1Ev@plt>   0x080489ce <+63>:lea    0x37(%esp),%eax   0x080489d2 <+67>:mov    %eax,0x8(%esp)   0x080489d6 <+71>:movl   $0x8049cfa,0x4(%esp)---Type <return> to continue, or q <return> to quit---   0x080489de <+79>:lea    0x30(%esp),%eax   0x080489e2 <+83>:mov    %eax,(%esp)   0x080489e5 <+86>:call   0x80487ec <_ZNSsC1EPKcRKSaIcE@plt>   0x080489ea <+91>:lea    0x30(%esp),%eax   0x080489ee <+95>:mov    %eax,0x4(%esp)   0x080489f2 <+99>:lea    0x18(%esp),%eax   0x080489f6 <+103>:mov    %eax,(%esp)   0x080489f9 <+106>:call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>   0x080489fe <+111>:movl   $0x8048964,(%eax)   0x08048a04 <+117>:lea    0x30(%esp),%eax   0x08048a08 <+121>:mov    %eax,(%esp)   0x08048a0b <+124>:call   0x80487cc <_ZNSsD1Ev@plt>   0x08048a10 <+129>:jmp    0x8048a41 <main+178>   0x08048a12 <+131>:mov    %edx,%ebx   0x08048a14 <+133>:mov    %eax,%esi   0x08048a16 <+135>:lea    0x30(%esp),%eax   0x08048a1a <+139>:mov    %eax,(%esp)   0x08048a1d <+142>:call   0x80487cc <_ZNSsD1Ev@plt>   0x08048a22 <+147>:mov    %esi,%eax   0x08048a24 <+149>:mov    %ebx,%edx   0x08048a26 <+151>:jmp    0x8048a28 <main+153>   0x08048a28 <+153>:mov    %edx,%ebx---Type <return> to continue, or q <return> to quit---   0x08048a2a <+155>:mov    %eax,%esi   0x08048a2c <+157>:lea    0x37(%esp),%eax   0x08048a30 <+161>:mov    %eax,(%esp)   0x08048a33 <+164>:call   0x804882c <_ZNSaIcED1Ev@plt>   0x08048a38 <+169>:mov    %esi,%eax   0x08048a3a <+171>:mov    %ebx,%edx   0x08048a3c <+173>:jmp    0x8048c26 <main+663>   0x08048a41 <+178>:lea    0x37(%esp),%eax   0x08048a45 <+182>:mov    %eax,(%esp)   0x08048a48 <+185>:call   0x804882c <_ZNSaIcED1Ev@plt>   0x08048a4d <+190>:lea    0x3f(%esp),%eax   0x08048a51 <+194>:mov    %eax,(%esp)   0x08048a54 <+197>:call   0x804887c <_ZNSaIcEC1Ev@plt>   0x08048a59 <+202>:lea    0x3f(%esp),%eax   0x08048a5d <+206>:mov    %eax,0x8(%esp)   0x08048a61 <+210>:movl   $0x8049cfc,0x4(%esp)   0x08048a69 <+218>:lea    0x38(%esp),%eax   0x08048a6d <+222>:mov    %eax,(%esp)   0x08048a70 <+225>:call   0x80487ec <_ZNSsC1EPKcRKSaIcE@plt>   0x08048a75 <+230>:lea    0x38(%esp),%eax   0x08048a79 <+234>:mov    %eax,0x4(%esp)   0x08048a7d <+238>:lea    0x18(%esp),%eax   0x08048a81 <+242>:mov    %eax,(%esp)---Type <return> to continue, or q <return> to quit---   0x08048a84 <+245>:call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>   0x08048a89 <+250>:movl   $0x8048972,(%eax)   0x08048a8f <+256>:lea    0x38(%esp),%eax   0x08048a93 <+260>:mov    %eax,(%esp)   0x08048a96 <+263>:call   0x80487cc <_ZNSsD1Ev@plt>   0x08048a9b <+268>:jmp    0x8048acc <main+317>   0x08048a9d <+270>:mov    %edx,%ebx   0x08048a9f <+272>:mov    %eax,%esi   0x08048aa1 <+274>:lea    0x38(%esp),%eax   0x08048aa5 <+278>:mov    %eax,(%esp)   0x08048aa8 <+281>:call   0x80487cc <_ZNSsD1Ev@plt>   0x08048aad <+286>:mov    %esi,%eax   0x08048aaf <+288>:mov    %ebx,%edx   0x08048ab1 <+290>:jmp    0x8048ab3 <main+292>   0x08048ab3 <+292>:mov    %edx,%ebx   0x08048ab5 <+294>:mov    %eax,%esi   0x08048ab7 <+296>:lea    0x3f(%esp),%eax   0x08048abb <+300>:mov    %eax,(%esp)   0x08048abe <+303>:call   0x804882c <_ZNSaIcED1Ev@plt>   0x08048ac3 <+308>:mov    %esi,%eax   0x08048ac5 <+310>:mov    %ebx,%edx   0x08048ac7 <+312>:jmp    0x8048c26 <main+663>---Type <return> to continue, or q <return> to quit---   0x08048acc <+317>:lea    0x3f(%esp),%eax   0x08048ad0 <+321>:mov    %eax,(%esp)   0x08048ad3 <+324>:call   0x804882c <_ZNSaIcED1Ev@plt>   0x08048ad8 <+329>:lea    0x47(%esp),%eax   0x08048adc <+333>:mov    %eax,(%esp)   0x08048adf <+336>:call   0x804887c <_ZNSaIcEC1Ev@plt>   0x08048ae4 <+341>:lea    0x47(%esp),%eax   0x08048ae8 <+345>:mov    %eax,0x8(%esp)   0x08048aec <+349>:movl   $0x8049cfe,0x4(%esp)   0x08048af4 <+357>:lea    0x40(%esp),%eax   0x08048af8 <+361>:mov    %eax,(%esp)   0x08048afb <+364>:call   0x80487ec <_ZNSsC1EPKcRKSaIcE@plt>   0x08048b00 <+369>:lea    0x40(%esp),%eax   0x08048b04 <+373>:mov    %eax,0x4(%esp)   0x08048b08 <+377>:lea    0x18(%esp),%eax   0x08048b0c <+381>:mov    %eax,(%esp)   0x08048b0f <+384>:call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>   0x08048b14 <+389>:movl   $0x8048983,(%eax)   0x08048b1a <+395>:lea    0x40(%esp),%eax   0x08048b1e <+399>:mov    %eax,(%esp)   0x08048b21 <+402>:call   0x80487cc <_ZNSsD1Ev@plt>   0x08048b26 <+407>:jmp    0x8048b57 <main+456>---Type <return> to continue, or q <return> to quit---   0x08048b28 <+409>:mov    %edx,%ebx   0x08048b2a <+411>:mov    %eax,%esi   0x08048b2c <+413>:lea    0x40(%esp),%eax   0x08048b30 <+417>:mov    %eax,(%esp)   0x08048b33 <+420>:call   0x80487cc <_ZNSsD1Ev@plt>   0x08048b38 <+425>:mov    %esi,%eax   0x08048b3a <+427>:mov    %ebx,%edx   0x08048b3c <+429>:jmp    0x8048b3e <main+431>   0x08048b3e <+431>:mov    %edx,%ebx   0x08048b40 <+433>:mov    %eax,%esi   0x08048b42 <+435>:lea    0x47(%esp),%eax   0x08048b46 <+439>:mov    %eax,(%esp)   0x08048b49 <+442>:call   0x804882c <_ZNSaIcED1Ev@plt>   0x08048b4e <+447>:mov    %esi,%eax   0x08048b50 <+449>:mov    %ebx,%edx   0x08048b52 <+451>:jmp    0x8048c26 <main+663>   0x08048b57 <+456>:lea    0x47(%esp),%eax   0x08048b5b <+460>:mov    %eax,(%esp)   0x08048b5e <+463>:call   0x804882c <_ZNSaIcED1Ev@plt>   0x08048b63 <+468>:lea    0x4f(%esp),%eax   0x08048b67 <+472>:mov    %eax,(%esp)   0x08048b6a <+475>:call   0x804887c <_ZNSaIcEC1Ev@plt>   0x08048b6f <+480>:mov    0xc(%ebp),%eax---Type <return> to continue, or q <return> to quit---   0x08048b72 <+483>:add    $0x8,%eax   0x08048b75 <+486>:mov    (%eax),%eax   0x08048b77 <+488>:lea    0x4f(%esp),%edx   0x08048b7b <+492>:mov    %edx,0x8(%esp)   0x08048b7f <+496>:mov    %eax,0x4(%esp)   0x08048b83 <+500>:lea    0x48(%esp),%eax   0x08048b87 <+504>:mov    %eax,(%esp)   0x08048b8a <+507>:call   0x80487ec <_ZNSsC1EPKcRKSaIcE@plt>   0x08048b8f <+512>:lea    0x48(%esp),%eax   0x08048b93 <+516>:mov    %eax,0x4(%esp)   0x08048b97 <+520>:lea    0x18(%esp),%eax   0x08048b9b <+524>:mov    %eax,(%esp)   0x08048b9e <+527>:call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>   0x08048ba3 <+532>:mov    (%eax),%esi   0x08048ba5 <+534>:mov    0xc(%ebp),%eax   0x08048ba8 <+537>:add    $0xc,%eax   0x08048bab <+540>:mov    (%eax),%eax   0x08048bad <+542>:mov    %eax,(%esp)   0x08048bb0 <+545>:call   0x80487fc <atoi@plt>   0x08048bb5 <+550>:mov    %eax,%ebx   0x08048bb7 <+552>:mov    0xc(%ebp),%eax   0x08048bba <+555>:add    $0x4,%eax---Type <return> to continue, or q <return> to quit---   0x08048bbd <+558>:mov    (%eax),%eax   0x08048bbf <+560>:mov    %eax,(%esp)   0x08048bc2 <+563>:call   0x80487fc <atoi@plt>   0x08048bc7 <+568>:mov    %ebx,0x4(%esp)   0x08048bcb <+572>:mov    %eax,(%esp)   0x08048bce <+575>:call   *%esi=> 0x08048bd0 <+577>:mov    %eax,%ebx   0x08048bd2 <+579>:lea    0x48(%esp),%eax   0x08048bd6 <+583>:mov    %eax,(%esp)   0x08048bd9 <+586>:call   0x80487cc <_ZNSsD1Ev@plt>   0x08048bde <+591>:jmp    0x8048c0c <main+637>   0x08048be0 <+593>:mov    %edx,%ebx   0x08048be2 <+595>:mov    %eax,%esi   0x08048be4 <+597>:lea    0x48(%esp),%eax   0x08048be8 <+601>:mov    %eax,(%esp)   0x08048beb <+604>:call   0x80487cc <_ZNSsD1Ev@plt>   0x08048bf0 <+609>:mov    %esi,%eax   0x08048bf2 <+611>:mov    %ebx,%edx   0x08048bf4 <+613>:jmp    0x8048bf6 <main+615>   0x08048bf6 <+615>:mov    %edx,%ebx   0x08048bf8 <+617>:mov    %eax,%esi   0x08048bfa <+619>:lea    0x4f(%esp),%eax   0x08048bfe <+623>:mov    %eax,(%esp)   0x08048c01 <+626>:call   0x804882c <_ZNSaIcED1Ev@plt>   0x08048c06 <+631>:mov    %esi,%eax   0x08048c08 <+633>:mov    %ebx,%edx   0x08048c0a <+635>:jmp    0x8048c26 <main+663>   0x08048c0c <+637>:lea    0x4f(%esp),%eax   0x08048c10 <+641>:mov    %eax,(%esp)   0x08048c13 <+644>:call   0x804882c <_ZNSaIcED1Ev@plt>   0x08048c18 <+649>:lea    0x18(%esp),%eax   0x08048c1c <+653>:mov    %eax,(%esp)   0x08048c1f <+656>:call   0x8048c5a <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEED2Ev>   0x08048c24 <+661>:jmp    0x8048c42 <main+691>   0x08048c26 <+663>:mov    %edx,%ebx   0x08048c28 <+665>:mov    %eax,%esi   0x08048c2a <+667>:lea    0x18(%esp),%eax   0x08048c2e <+671>:mov    %eax,(%esp)   0x08048c31 <+674>:call   0x8048c5a <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEED2Ev>   0x08048c36 <+679>:mov    %esi,%eax   0x08048c38 <+681>:mov    %ebx,%edx   0x08048c3a <+683>:mov    %eax,(%esp)   0x08048c3d <+686>:call   0x804889c <_Unwind_Resume@plt>   0x08048c42 <+691>:mov    %ebx,%eax   0x08048c44 <+693>:add    $0x58,%esp   0x08048c47 <+696>:pop    %ebx   0x08048c48 <+697>:pop    %esi   0x08048c49 <+698>:mov    %ebp,%esp   0x08048c4b <+700>:pop    %ebp   0x08048c4c <+701>:ret    End of assembler dump.

出现coredump可能是因为这一条指令

   0x08048bce <+575>:call   *%esi

看一下esi的值:

(gdb) i r esiesi            0x00

可见esi为0,确实是由于那一条指令引起的.

那么为什么esi的值是从哪里来的?

   0x08048b8f <+512>:lea    0x48(%esp),%eax   0x08048b93 <+516>:mov    %eax,0x4(%esp)   0x08048b97 <+520>:lea    0x18(%esp),%eax   0x08048b9b <+524>:mov    %eax,(%esp)   0x08048b9e <+527>:call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>   0x08048ba3 <+532>:mov    (%eax),%esi

可见esi是0x08048b9e处所调用的函数,

_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_的返回值

而_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_的实际名称:

[xuzhina@localhost s3_ex]$ c++filt _ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int (*)(int, int), std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int (*)(int, int)> > >::operator[](std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)

由于map的operater[]有一个参数,由上面看,可知map对象的地址是esp+0x18,那个参数是放在esp+0x48,而这个刚好是一个string对象的this指针.见0x08048b8a调用了构造函数

   0x08048b6f <+480>:mov    0xc(%ebp),%eax   0x08048b72 <+483>:add    $0x8,%eax   0x08048b75 <+486>:mov    (%eax),%eax   0x08048b77 <+488>:lea    0x4f(%esp),%edx   0x08048b7b <+492>:mov    %edx,0x8(%esp)   0x08048b7f <+496>:mov    %eax,0x4(%esp)   0x08048b83 <+500>:lea    0x48(%esp),%eax   0x08048b87 <+504>:mov    %eax,(%esp)   0x08048b8a <+507>:call   0x80487ec <_ZNSsC1EPKcRKSaIcE@plt>[xuzhina@localhost s3_ex]$ c++filt _ZNSsC1EPKcRKSaIcEstd::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)

可知,这个string的构造函数只是接收了一个参数,而这个参数是由ebp+c所指向内存地址偏移+8所得来的.

而ebp+0xc是main函数的第二个参数,由main函数的原型

int main( int argc, char* argv[] );

可知

这个参数应该是argv[2],而argv[2]是字符串。它的值是多少呢?

(gdb) x /wx $ebp+0xc0xbfd3def4:0xbfd3df94(gdb) x /8wx 0xbfd3df940xbfd3df94:0xbfd3f5430xbfd3f55c0xbfd3f55e0xbfd3f5600xbfd3dfa4:0x000000000xbfd3f5620xbfd3f5850xbfd3f5a4(gdb) x /s 0xbfd3f55e0xbfd3f55e: "/"

再看一下map的内容有哪些。由上面已经知道map对象的地址是esp+0x18。且由于上面参数的类型可以知道,这个map对象的key是string类型,而val是函数指针

(gdb) x /8wx $esp+0x180xbfd3de98:0x000000010x000000000x089a70200x089a70900xbfd3dea8:0x089a70c80x000000040x089a70140x0804bb84(gdb) x /8wx 0x089a70200x89a7020:0x000000010xbfd3de9c0x089a70900x089a70580x89a7030:0x089a70140x080489640x000000000x00000019(gdb) x /8wx 0x089a70140x89a7014:0x0000002b0x000000000x000000210x000000010x89a7024:0xbfd3de9c0x089a70900x089a70580x089a7014(gdb) x /s 0x089a70140x89a7014: "+"(gdb) info symbol 0x08048964add(int, int) in section .text of /home/xuzhina/code/s3_ex/xuzhina_dump_c07_s3_ex(gdb) x /8wx 0x089a70900x89a7090:0x000000010x089a70200x000000000x000000000x89a70a0:0x089a70840x080489830x000000000x00000019(gdb) x /8wx 0x089a70840x89a7084:0x0000002a0x000000000x000000210x000000010x89a7094:0x089a70200x000000000x000000000x089a7084(gdb) x /s 0x089a70840x89a7084: "*"(gdb) info symbol 0x08048983mul(int, int) in section .text of /home/xuzhina/code/s3_ex/xuzhina_dump_c07_s3_ex(gdb) x /8wx 0x089a70580x89a7058:0x000000010x089a70200x000000000x089a70c80x89a7068:0x089a704c0x080489720x000000000x00000019(gdb) x /8wx 0x089a704c0x89a704c:0x0000002d0x000000000x000000210x000000010x89a705c:0x089a70200x000000000x089a70c80x089a704c(gdb) x /s 0x089a704c0x89a704c: "-"(gdb) info symbol 0x08048972sub(int, int) in section .text of /home/xuzhina/code/s3_ex/xuzhina_dump_c07_s3_ex(gdb) x /8wx 0x089a70c80x89a70c8:0x000000000x089a70580x000000000x000000000x89a70d8:0x089a70bc0x000000000x000000000x00020f21(gdb) x /8wx 0x089a70bc0x89a70bc:0x0000002f0x000000000x000000210x000000000x89a70cc:0x089a70580x000000000x000000000x089a70bc(gdb) x /s 0x089a70bc0x89a70bc: "/"

而main函数调用_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_除了coredump的附近之外,还有三处调用了。

   0x080489ea <+91>:lea    0x30(%esp),%eax   0x080489ee <+95>:mov    %eax,0x4(%esp)   0x080489f2 <+99>:lea    0x18(%esp),%eax   0x080489f6 <+103>:mov    %eax,(%esp)   0x080489f9 <+106>:call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>   0x080489fe <+111>:movl   $0x8048964,(%eax)   0x08048a75 <+230>:lea    0x38(%esp),%eax   0x08048a79 <+234>:mov    %eax,0x4(%esp)   0x08048a7d <+238>:lea    0x18(%esp),%eax   0x08048a81 <+242>:mov    %eax,(%esp)---Type <return> to continue, or q <return> to quit---   0x08048a84 <+245>:call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>   0x08048a89 <+250>:movl   $0x8048972,(%eax)   0x08048b00 <+369>:lea    0x40(%esp),%eax   0x08048b04 <+373>:mov    %eax,0x4(%esp)   0x08048b08 <+377>:lea    0x18(%esp),%eax   0x08048b0c <+381>:mov    %eax,(%esp)   0x08048b0f <+384>:call   0x8048cfc <_ZNSt3mapISsPFiiiESt4lessISsESaISt4pairIKSsS1_EEEixERS5_>   0x08048b14 <+389>:movl   $0x8048983,(%eax)

其中0x8048964,0x8048972,0x8048983正好是那三个函数指针。可见,main函数并没有往map对象里面放入”/”的val。

 

看一下程序代码,

  1 #include <map>  2 #include <string>  3 #include <stdio.h>  4 #include <stdlib.h>  5   6 typedef int (*oper)(int a, int b );  7   8 int add( int a, int b )  9 { 10     return a + b; 11 } 12  13 int sub( int a, int b ) 14 { 15     return a - b; 16 } 17  18 int mul( int a, int b ) 19 { 20     return a * b; 21 } 22  23 int main( int argc, char* argv[] ) 24 { 25     if ( argc < 4 ) 26     { 27         printf( "parameter less than 4\n" ); 28         return -1; 29     } 30  31     std::map< std::string, oper> operMap; 32     operMap["+"] = &add; 33     operMap["-"] = ⊂ 34     operMap["*"] = &mul; 35  36     return operMap[argv[2]]( atoi( argv[1] ), atoi( argv[3] ) ); 37 }

 

可知,确实如上面所分析那样.所以,对于获取map里面的元素,用operator[]要慎重.


0 0