获得函数指针和虚表序号

在使用C语言进行编程时,我们经常会使用函数指针,但是我们拿到的函数指针真的就是函数的代码体么?
答案当然是不是,如果我们直接拿到函数的代码体的指针的话,程序就没有办法进行代码的重定位了。
进行函数体的重新定位在函数实现在一个DLL中时尤其重要,因为函数一般总是会被重新定位到以一个位置。当然如果在Vista和更新的系统中,启用了地址随机,连EXE的每次加载都不能保证代码在相同的位置上。
所以编译器通过转向表的方式实现函数指针。
转向表就是一堆jmp指令组成的表,而所有的jmp指令都是使用相对寻址方式。编译器通过这种实现方式来保证,无论函数是导入函数还是普通函数,都能保证函数重新定位时的正确性。
那么我们怎么拿到真正的函数地址呢?
那就要从函数的汇编代码入手。
32位相对寻址jmp指令的op码是E9,代码的格式为 E9 0xXXXXXXXX,也就是E9之后的立即数就是函数的相对地址。所以我们只要在获得到的函数转向表指针上加上这个立即数,再加上这个指令的长度5(执行jmp时是相对于jmp指令之后的指令的)。
8位相对寻址jmp指令的op码是EB,代码格式为EB 0xXX,而实际中8位相对寻址jmp指令一般不会被用到。

 

 

函数的虚表在你拿不到对象的时候基本上是不能找到来进行访问的

但是,通过一个类虚函数指针就可以轻松的获得这个函数是在虚表中的第几项

这也是编译器处理虚函数调用的方式带来的好处。

虚函数调用时会通过表的偏移寻址转向来进行,所以这时代码中一定可以计算出虚表的序号

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值