2

这个问题类似于 打印虚拟成员函数的地址

我想使用成员函数指针检索函数的内存位置(在运行时)。目标是记录它们,并进行事后分析,使用 WinDbg 中的“ln”来检索它是哪个函数,使用 PDB 符号。

我不能使用堆栈遍历,因为我还没有进入我想要记录的功能。(而且我不想修改数十亿个函数来返回他们的地址......)。

短样本:

class AClass
{
public :
   virtual AFunction(){;}

};

typedef void (AClass::*FxPtr)( void );


[...]
    AClass oAClass;

    AClass*  pSelf = &oAClass;
    FxPtr    pf    = &AClass::AFunction;

    DWORD nFctAddress = ???

任何人都知道如何检索地址?

&(pSelf->*pf)

给出 'error C2298: '&' : 对指向成员函数表达式的指针的非法操作'

我知道成员函数指针是“奇怪”的结构,但由于我知道“this”,有没有办法从 vtable 中查找潜在的虚函数?

问候,

参考:

4

2 回答 2

1
#include <stdio.h>

struct Class {
  virtual void AFunction( void ) { printf("1"); }
};

struct AClass : public Class {
  virtual void AFunction( void ) { printf("2"); }
};

typedef void (AClass::*FxPtr)(void);


int main( void ) {

  union {
    FxPtr pf;
    int rf[2];
  };

  pf = &AClass::AFunction;

  printf( "sizeof(pf)=%i\n", sizeof(pf) );

  printf( "%08X\n", pf );

  printf( "%08X %08X\n", rf[0], rf[1] );

/*
error: ISO C++ forbids taking the address of a bound member function
to form a pointer to member function.  Say '&AClass::AFunction'

  AClass a;
  FxPtr qf = &a.AFunction;
  printf( "sizeof(qf)=%i\n", sizeof(qf) );
*/

};

它很容易访问 vtable,但通过地址来识别函数并不那么简单。
一些选项:
1) 解析 .map 文件,加载并通过 typeid(或通过 map 中的 VMT 实例)查找类名,然后通过其名称查找函数地址。
2) 为给定对象编写一个调用给定虚方法的静态函数,查看它在 asm 中的样子,并从其代码中检索函数在 vtable 中的偏移量,然后读取地址

?adr_CFunction@Class@@SIXPAU1@@Z PROC           ; Class::adr_CFunction, COMDAT
; _This$ = ecx
; 8    :   static void adr_CFunction( Class* This ) { This->CFunction(); }
    mov eax, DWORD PTR [ecx]
    mov edx, DWORD PTR [eax+8]
    jmp edx
?adr_CFunction@Class@@SIXPAU1@@Z ENDP           ; Class::adr_CFunction

3) 有一些不错的选项,例如“/Gh enable _penter function call”,它允许在调用之后检索所有函数的地址,但在函数实际执行任何操作之前。然后 .map 可用于通过跟踪识别功能。

于 2011-02-15T00:04:09.860 回答
0

这一切都在地图文件中。打开地图文件生成并享受。

于 2011-02-14T23:07:59.880 回答