C ++: Получение виртуального «адреса» функции с указателем на функцию-член - PullRequest
1 голос
/ 15 февраля 2011

Этот вопрос похож на Адрес для печати виртуальной функции-члена

Я хотел бы получить место в памяти функции (во время выполнения), используя указатель на функцию-член.Цель состоит в том, чтобы зарегистрировать их и выполнить посмертный анализ, используя 'ln' в WinDbg, чтобы узнать, какая это была функция, используя символы PDB.

Я не могу использовать стековый обход, поскольку я еще нев функцию, которую я хочу войти.(и я не хочу изменять миллиарды функций, чтобы они возвращали мне свой адрес ...).

Краткий пример:

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

};

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


[...]
    AClass oAClass;

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

    DWORD nFctAddress = ???

У кого-нибудь есть идеи, как я могу получить адрес?

&(pSelf->*pf)

выдает 'ошибку C2298:' & ': недопустимая операция с указателем на выражение функции-члена'

Я знаю, что указатели на функции-члены являются "странными" структурами, но, поскольку я знаю,'this', есть ли способ поиска потенциально виртуальной функции из vtable?

С уважением,

refs:

Ответы [ 2 ]

1 голос
/ 15 февраля 2011
#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 (или по экземпляру 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 можно использовать для идентификации функции по трассе.

0 голосов
/ 15 февраля 2011

Это все в файле карты. Включите генерацию файла карты и наслаждайтесь.

...