反汇编 之 gdb 找出普通 virtual 函数表

65 篇文章 1 订阅

#include <iostream>
#include <stdio.h>

class Base
{
    public:
        void function_1()
        {
            printf("function_1...\n");
        }

        virtual void function_2()
        {
            printf("function_2...\n");
        }
};

int main(int argc, char ** argv)
{
    Base base;

    base.function_1();
    base.function_2();
}

[xiaozhi@linux virtual]$ gdb
GNU gdb (GDB) Fedora 7.7.1-21.fc20
Copyright (C) 2014 Free Software Foundation, Inc.
(gdb) file r-virtual-01
Reading symbols from r-virtual-01...done.
(gdb) b *main
Breakpoint 1 at 0x8048640: file r-virtual-01.cpp, line 19.
(gdb) r
Starting program: /home/share/work/ac-code/study-c++/virtual/r-virtual-01

Breakpoint 1, main (argc=1, argv=0xbffff194) at r-virtual-01.cpp:19
19    {
Missing separate debuginfos, use: debuginfo-install libgcc-4.8.3-7.fc20.i686 libstdc++-4.8.3-7.fc20.i686
(gdb) disassemble /mr main
Dump of assembler code for function main(int, char**):
19    {
=> 0x08048640 <+0>:    55    push   %ebp
   0x08048641 <+1>:    89 e5    mov    %esp,%ebp
   0x08048643 <+3>:    83 e4 f0    and    $0xfffffff0,%esp
   0x08048646 <+6>:    83 ec 20    sub    $0x20,%esp

20        Base base;
   0x08048649 <+9>:    8d 44 24 1c    lea    0x1c(%esp),%eax
   0x0804864d <+13>:    89 04 24    mov    %eax,(%esp)
   0x08048650 <+16>:    e8 a3 00 00 00    call   0x80486f8 <Base::Base()>

21    
22        base.function_1();
   0x08048655 <+21>:    8d 44 24 1c    lea    0x1c(%esp),%eax
   0x08048659 <+25>:    89 04 24    mov    %eax,(%esp)
   0x0804865c <+28>:    e8 6f 00 00 00    call   0x80486d0 <Base::function_1()>

23        base.function_2();
   0x08048661 <+33>:    8d 44 24 1c    lea    0x1c(%esp),%eax
   0x08048665 <+37>:    89 04 24    mov    %eax,(%esp)
   0x08048668 <+40>:    e8 77 00 00 00    call   0x80486e4 <Base::function_2()>

24    }
   0x0804866d <+45>:    b8 00 00 00 00    mov    $0x0,%eax
   0x08048672 <+50>:    c9    leave  
   0x08048673 <+51>:    c3    ret    

End of assembler dump.
(gdb) n
20        Base base;
(gdb) n
22        base.function_1();
(gdb) n
function_1...
23        base.function_2();
(gdb) disassemble
Dump of assembler code for function main(int, char**):
   0x08048640 <+0>:    push   %ebp
   0x08048641 <+1>:    mov    %esp,%ebp
   0x08048643 <+3>:    and    $0xfffffff0,%esp
   0x08048646 <+6>:    sub    $0x20,%esp
   0x08048649 <+9>:    lea    0x1c(%esp),%eax
   0x0804864d <+13>:    mov    %eax,(%esp)
   0x08048650 <+16>:    call   0x80486f8 <Base::Base()>
   0x08048655 <+21>:    lea    0x1c(%esp),%eax
   0x08048659 <+25>:    mov    %eax,(%esp)
   0x0804865c <+28>:    call   0x80486d0 <Base::function_1()>
=> 0x08048661 <+33>:    lea    0x1c(%esp),%eax
   0x08048665 <+37>:    mov    %eax,(%esp)
   0x08048668 <+40>:    call   0x80486e4 <Base::function_2()>
   0x0804866d <+45>:    mov    $0x0,%eax
   0x08048672 <+50>:    leave  
   0x08048673 <+51>:    ret    
End of assembler dump.

/* 找出虚函数地址方法一 */
(gdb) p $esp
$1 = (void *) 0xbffff0d0

(gdb) p $esp+0x1c
$2 = (void *) 0xbffff0ec

(gdb) p base
$3 = {_vptr.Base = 0x80487c8 <vtable for Base+8>}

(gdb) x /xw 0xbffff0ec
0xbffff0ec:    0x080487c8

(gdb) x /xw 0x080487c8
0x80487c8 <_ZTV4Base+8>:    0x080486e4    # 虚函数地址

/* 找出虚函数地址方法二 */
(gdb) p base

$4 = {_vptr.Base = 0x80487c8 <vtable for Base+8>}

(gdb) i r $esp
esp            0xbffff0d0    0xbffff0d0

(gdb) p /x 0xbffff0d0+0x1c
$5 = 0xbffff0ec

(gdb) p /x 0xbffff0ec
$6 = 0xbffff0ec

(gdb) p /x *0xbffff0ec
$7 = 0x80487c8

(gdb) p /x *0x80487c8
$8 = 0x80486e4                    # 虚函数地址

(gdb) disassemble 0x80486e4            # 反汇编地址处代码
Dump of assembler code for function Base::function_2():
   0x080486e4 <+0>:    push   %ebp
   0x080486e5 <+1>:    mov    %esp,%ebp
   0x080486e7 <+3>:    sub    $0x18,%esp
   0x080486ea <+6>:    movl   $0x80487b2,(%esp)
   0x080486f1 <+13>:    call   0x8048520 <puts@plt>
   0x080486f6 <+18>:    leave  
   0x080486f7 <+19>:    ret    
End of assembler dump.
(gdb)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值