A study on the principle of Coredump, Linux version x86 6.4 section virtual function

Source: Internet
Author: User

In the previous section, you have explored the arrangement of the member variables of a class, and now look at the arrangement of virtual function tables and member variables and the arrangement between virtual functions.

Let's look at an example:

  1 #include <stdio.h>  2 class Xuzhina_dump_c06_s3  3 {  4     private:  5         int m_a;  6 Public     :  7         xuzhina_dump_c06_s3 () {m_a = 0;}  8         Virtual Void Inc () {m_a++;}  9         virtual void Dec () {m_a--;}         virtual void print () One         {             printf ("%d\n", m_a);         14}; A  . int main (), {     xuzhina_dump_c06_s3* test = new Xuzhina_dump_c06_s3; n     if (test! = NULL) 20
   {         test->inc ();         test->inc ();         test->print (); +     0; 26}

Assembly Code:

(GDB) disassemble maindump of assembler code for function main:0x08048560 <+0>: Push%EBP 0x08048561 <    +1&GT: mov%esp,%ebp 0x08048563 <+3>: Push%ebx 0x08048564 <+4>: and $0xfffffff0,%esp    0x08048567 <+7>: Sub $0x20,%esp 0x0804856a <+10>: Movl $0x8, (%ESP) 0x08048571 <+17>:     Call 0x8048450 <[email protected]> 0x08048576 <+22>: mov%eax,%ebx 0x08048578 <+24>: mov%ebx, (%ESP) 0x0804857b <+27>: Call 0x80485cc <_ZN19xuzhina_dump_c06_s3C2Ev> 0x08048580 &lt     ; +32&GT: mov%ebx,0x1c (%ESP) 0x08048584 <+36>: Cmpl $0x0,0x1c (%ESP) 0x08048589 <+41>: je 0X80485C1 <main+97> 0x0804858b <+43>: mov 0x1c (%ESP),%eax 0x0804858f <+47>: mov (%EAX) ,%eax 0x08048591 <+49>: mov (%EAX),%eax 0x08048593 <+51>: mov 0x1c (%ESP),%edx 0x08048597 &lt ; +55>: mov%edx, (%ESP) 0x0804859a <+58>: Call *%eax 0x0804859c <+60>: mov 0x1c (%ESP),%eax 0x080485a0 <+64 : mov (%EAX),%eax 0x080485a2 <+66>: mov (%EAX),%eax 0x080485a4 <+68>: mov 0x1c (%ESP)    ,%edx 0x080485a8 <+72>: mov%edx, (%ESP) 0x080485ab <+75>: Call *%eax 0X080485AD <+77>:   mov 0x1c (%ESP),%eax 0x080485b1 <+81>: mov (%EAX),%eax 0x080485b3 <+83>: Add $0x8,%eax 0x080485b6 <+86>: mov (%EAX),%eax 0x080485b8 <+88>: mov 0x1c (%ESP),%edx 0X080485BC <+92> : mov%edx, (%ESP) 0X080485BF <+95>: Call *%eax 0x080485c1 <+97>: mov $0x0,%eax 0x080485 C6 <+102>: mov-0x4 (%EBP),%ebx 0x080485c9 <+105>: Leave 0x080485ca <+106>: ret End of Assembler dump.

The above code shows that, after executing the constructor, the value of the m_a of Test will become 0. And by the above assembly you can see that the this pointer is placed in the EBX register before and after the constructor is called.

At 0x08048578,0x08048580, take a look at the address that the this pointer points to is not the result.

(GDB) Tbreak *0x08048578temporary Breakpoint 1 at 0x8048578 (GDB) tbreak *0x08048580temporary Breakpoint 2 at 0x8048580 (gdb ) rstarting Program:/HOME/BUCKXU/WORK/6/3/XUZHINA_DUMP_C6_S3 temporary breakpoint 1, 0x08048578 in Main () (GDB) x/4x $eb x0x804a008:      0x00000000 0x00000000 0x00000000      0x00020ff1 (gdb) ccontinuing.temporary Breakpoint 2, 0x08048580 in Main () (GDB) x/4x $ebx 0x804a008:      0x080486d0      0x00000000      0x00000000      0x00020ff1

Very strange, according to the previous section of the content, address 0x804a008 should be stored m_a, will be initialized to 0. What exactly is the constructor of class Xuzhina_dump_c06_s3 doing? And what is 0X080486D0?

Take a look at the constructor of class Xuzhina_dump_c06_s3:

(GDB) disassemble _zn19xuzhina_dump_c06_s3c2evdump of assembler code for function _zn19xuzhina_dump_c06_s3c2ev:   0x080485cc <+0>:     push   %ebp   0x080485cd <+1>:     mov    %esp,%ebp   0x080485cf <+3 :     mov    0x8 (%EBP),%eax   0x080485d2 <+6>:     movl   $0x80486d0, (%eax)   0x080485d8 <+12>:    mov    0x8 (%EBP),%eax   0x080485db <+15>:    movl   $0x0,0x4 (%eax)   0x080485e2 <+22>:    pop    %ebp   0x080485e3 <+23>:    ret    End of assembler dump.

The Assembly of the constructor shows that the value of 0x80486d0 is set in the constructor, but it is unclear what it is. and

   0x080485d8 <+12>:    mov    0x8 (%EBP),%eax   0x080485db <+15>:    movl $0x0,0x4   (%EAX)

It just corresponds.

  7         Xuzhina_dump_c06_s3 () {m_a = 0;}

That is, the first member variable of the class Xuzhina_dump_c06_s3 M_a placed where the this pointer is offset, so what is 0x80486d0, the position of the m_a?

Look again at the assembly of the main function:

(GDB) disassemble maindump of assembler code for function main:0x08048560 <+0>: Push%EBP 0x08048561 <    +1&GT: mov%esp,%ebp 0x08048563 <+3>: Push%ebx 0x08048564 <+4>: and $0xfffffff0,%esp    0x08048567 <+7>: Sub $0x20,%esp 0x0804856a <+10>: Movl $0x8, (%ESP) 0x08048571 <+17>:     Call 0x8048450 <[email protected]> 0x08048576 <+22>: mov%eax,%ebx 0x08048578 <+24>: mov%ebx, (%ESP) 0x0804857b <+27>: Call 0x80485cc <_ZN19xuzhina_dump_c06_s3C2Ev>=> 0x08048580      &LT;+32&GT: mov%ebx,0x1c (%ESP) 0x08048584 <+36>: Cmpl $0x0,0x1c (%ESP) 0x08048589 <+41>: je 0X80485C1 <main+97> 0x0804858b <+43>: mov 0x1c (%ESP),%eax 0x0804858f <+47>: mov (%e AX),%eax 0x08048591 <+49>: mov (%EAX),%eax 0x08048593 <+51>: mov 0x1c (%ESP),%edx 0x08048597 <+55>: mov%edx, (%ESP) 0x0804859a <+58>: Call *%eax 0x0804859c <+60>: mov 0x1c (%ESP),%eax 0x080485a0 < +64&GT: mov (%eax),%eax 0x080485a2 <+66>: mov (%EAX),%eax 0x080485a4 <+68>: mov 0x1c (%e SP),%edx 0x080485a8 <+72>: mov%edx, (%ESP) 0x080485ab <+75>: Call *%eax 0X080485AD <+77&gt    ;: mov 0x1c (%ESP),%eax 0x080485b1 <+81>: mov (%EAX),%eax 0x080485b3 <+83>: Add $0x8,%eax 0x080485b6 <+86>: mov (%EAX),%eax 0x080485b8 <+88>: mov 0x1c (%ESP),%edx 0X080485BC <+92& GT: mov%edx, (%ESP) 0X080485BF <+95>: Call *%eax 0x080485c1 <+97>: mov $0x0,%eax 0x080 485c6 <+102>: mov-0x4 (%EBP),%ebx 0x080485c9 <+105>: Leave 0x080485ca <+106>: ret End of assembler dump.

By

   0x0804857b <+27>:    call   0x80485cc <_ZN19xuzhina_dump_c06_s3C2Ev> 0x08048580 <+32>:    mov    %ebx,0x1c (%ESP)

The esp+0x1c is used to store this pointer.

Take a look at these instructions:

0x0804858b <+43>: mov 0x1c (%ESP),%eax 0x0804858f <+47>: mov (%EAX),%eax 0x08048591 <+49> : mov (%EAX),%eax 0x08048593 <+51>: mov 0x1c (%ESP),%edx 0x08048597 <+55>: mov%edx, (%esp    ) 0x0804859a <+58>: Call *%eax 0x0804859c <+60>: mov 0x1c (%ESP),%eax 0x080485a0 <+64>:   MOV (%EAX),%eax 0x080485a2 <+66>: mov (%EAX),%eax 0x080485a4 <+68>: mov 0x1c (%ESP),%edx     0x080485a8 <+72>: mov%edx, (%ESP) 0x080485ab <+75>: Call *%eax 0X080485AD <+77>: mov 0x1c (%ESP),%eax 0x080485b1 <+81>: mov (%EAX),%eax 0x080485b3 <+83>: Add $0x8,%eax 0x0804 85b6 <+86>: mov (%EAX),%eax 0x080485b8 <+88>: mov 0x1c (%ESP),%edx 0X080485BC <+92>: M OV%edx, (%ESP) 0X080485BF <+95>: Call *%eax

Because it is a sequential structure, we know that these three directives correspond exactly

         test->inc ();         test->inc ();         test->print ();

Analyze the third paragraph of the Assembly:

   0X080485AD <+77>:    mov    0x1c (%esp),%eax   0x080485b1 <+81>:    mov    (%eax),%eax   0X080485B3 <+83>:    add    $0x8,%eax   0x080485b6 <+86>:    mov    (%eax),%eax   0x080485b8 <+88>:    mov    0x1c (%esp),%edx   0X080485BC <+92>:    mov    %edx, (%ESP)   0X080485BF <+95>:    call   *%eax

The visible eax is just a pointer to the virtual function of the print. And this pointer is finally made by esp+0x1c. By

   0X080485AD <+77>:    mov    0x1c (%esp),%eax   0x080485b1 <+81>:    mov    (%eax),%eax

It is true that the first member of the this pointer is taken out, that is, the member is a virtual function table pointer. According to the above analysis, the value of this virtual function table pointer is 0x80486d0. To verify that it is not a virtual function table pointer.

(gdb) x/4x 0x80486d00x80486d0 <_ztv19xuzhina_dump_c06_s3+8>:        0x080485e4      0x080485f8 0x0804860c      0x75783931 (gdb) shell c++filt _ztv19xuzhina_dump_c06_s3vtable for XUZHINA_DUMP_C06_S3 (GDB) Info symbol 0x080485e4xuzhina_dump_c06_s3::inc () in section. Text OF/HOME/BUCKXU/WORK/6/3/XUZHINA_DUMP_C6_S3 (GDB) Info symbol 0X080485F8XUZHINA_DUMP_C06_S3::d EC () in section. Text OF/HOME/BUCKXU/WORK/6/3/XUZHINA_DUMP_C6_S3 (GDB) Info symbol 0X0804860CXUZHINA_DUMP_C06_S3::p rint () in section. Text Of/home/buckxu/work/6/3/xuzhina_dump_c6_s3

As you can see, 0x80486d0 points to the virtual function table, and the table entry order is exactly the same as the declaration order of the virtual function.

From the above analysis, the memory layout of the object pointed to by test is as follows:


Coredump Problem Theory Research "Linux version x86 6.4 section virtual function

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.