Есть адрес виртуальной функции. Как вызвать функцию?

Тема в разделе "LANGS.C", создана пользователем Ezrah, 28 сен 2011.

  1. _Juicy

    _Juicy Active Member

    Публикаций:
    0
    Регистрация:
    12 авг 2003
    Сообщения:
    1.159
    Адрес:
    SPb
    Бустер, какие данные вам нужны в коротеньком примере на сях?
    Можно конечно фото Мишель Обамы в хекскоде захреначить туда, но нахрена?
     
  2. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Не мой типаж, я не мыщхъ.
     
  3. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    Всю тему не читал, но ИМО тут пишут бред.

    Для MSVC:

    допустим у вас есть *адрес функции* 0x2000ABDC для класса
    Код (Text):
    1. struct Foo
    2. {
    3.     virtual void __thiscall bar() = 0;
    4. };
    если у вас есть ее адрес - она для вас уже не виртуальная, а конкретная,
    так что вы просто объявляете прототип и вызываете ее
    Код (Text):
    1. typedef void __thiscall Foo_bar(void* this1);
    2.  
    3. auto Foo_bar_ptr = (Foo_bar*)0x2000ABDC;
    4. Foo_bar_ptr(someFooObj);
    -----

    Booster, спасибо за трюк со ссылкой, первый раз такое вижу %) как он работает?

    upd: да тут еще 2я страница есть)))
    я имел ввиду этот код
    Код (Text):
    1. typedef void (T::*p)();
    2. int main()
    3. {
    4.     int a = 9;
    5.     p p1 = (p&)a;
    6. }
     
  4. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    Вдогонку.

    Когда я тоже решал эту проблему, и начал с __single_inheritance которое гарантирует что размер указателя на член будет равен размеру void*

    Потом один человек заметил, что можно использовать __fastcall
    void __fastcall foo(void* this1, DWORD edx_unused, T1 arg1, ...)

    Потом я однажды узнал что __thiscall работает и для свободных функций

    А недавно мне надо было собирать код под C++\CLI, а там ни __fastcall ни __thiscall не работают, по этому я написал такие переходники:
    Код (Text):
    1. // ======[ thiscall variable, ... ]========
    2.  
    3. __declspec(naked) inline void __stdcall stdcall2thiscall_impl(/* callee, this [, arg1, ...] */)
    4. {__asm {
    5.     pop edx // return address
    6.     pop eax // callee
    7.     pop ecx // this
    8.     push edx // return address
    9.     jmp eax // callee
    10. }}
    11.  
    12. template<typename R> __declspec(naked) R __stdcall thiscall(void* /*callee*/, void* /*this*/) {__asm jmp stdcall2thiscall_impl}
    13.  
    14. #define TEMP_THISCALL_FUNCTION_DECL(z, nArgs, d) /*----------------------------------------------------------*/ \
    15.     template<typename R, BOOST_PP_ENUM_PARAMS(nArgs, typename T)>                                               \
    16.     __declspec(naked) R __stdcall thiscall(void* /*callee*/, void* /*this*/, BOOST_PP_ENUM_PARAMS(nArgs, T))    \
    17.     {__asm jmp stdcall2thiscall_impl}                                                                           \
    18.     /*---------------------------------------------------------------------------------------------------------*/
    19. BOOST_PP_REPEAT_FROM_TO(1, 12, TEMP_THISCALL_FUNCTION_DECL, ~)
    20. #undef TEMP_THISCALL_FUNCTION_DECL
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    GoldFinch
    А что там необычного? Объект произвольного типа можно привести к ссылке на другой тип, ну а дальше ссылка присваивается объекту, при этом происходит копирование значения.
    Если по этапам то так.
    Код (Text):
    1. p& p1 = (p&)a;
    2. p p2 = p1;
    Более многословный аналог - *((p*)(&a));
     
  6. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    Booster
    аа точно.. ступил
     
  7. Ezrah

    Ezrah Member

    Публикаций:
    0
    Регистрация:
    22 мар 2011
    Сообщения:
    411
    Это начиная с какой версии MSVCPP?
     
  8. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    тут я соврал, виноват.
    такой код не скомпилится, он выдает
    error C3865: '__thiscall' : can only be used on native member functions

    но тем не менее можно сделать typedef на указатель на __thiscall функцию, и потом его использовать
    Код (Text):
    1. #include <iostream>
    2.  
    3. struct Foo
    4. {
    5.     int x;
    6.  
    7.     int __thiscall func() { return x; }
    8. };
    9.  
    10. int main()
    11. {
    12.     typedef int (__thiscall* Foo_func_t)(Foo*);
    13.     Foo_func_t p;
    14.  
    15.     *(decltype(&Foo::func)*)&p = &Foo::func;
    16.  
    17.     Foo f;
    18.     f.x = 42;
    19.     std::cout << p(&f) << '\n';
    20. }
    > Это начиная с какой версии MSVCPP?
    хз, у меня MSVC2010, но думаю это начиная с той в которой появился __thiscall
     
  9. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ezrah
    Тебе просто "повезло", что ты юзаешь VC, который для простейших случаев выдает размер указателя T::*p равный 4, поэтому и "кажется", что это обычный указатель. А вот С++Builder выдал бы тебе sizeof(p) == 12 и ты бы чесал репу, что это значит и куда нужно вписывать твой адрес - по смещению 0, 4 или 8. Почитай наконец статейку по приведенной выше ссылке

    PS: Еще раз подчеркну, что я не против использования данного метода. Просто мне показалось, что тебе хочется найти "легальный"=документированный способ, а данный метод к таковым не относится, т.к. структура указателя на ф-ю член нигде не документирована и соотв-но приравнивания типа p p1 = (p&)a можно делать только "на свой страх и риск" (хотя это и будет работать)

    Squash
    Не, т.к. у тебя в качестве this в функцию передается не исходный объект, а твоя фишка\пустышка, поэтому если внутри функции есть обращение к полям или vtbl исходного объекта, то ес-но будет большой облом-с
     
  10. _Juicy

    _Juicy Active Member

    Публикаций:
    0
    Регистрация:
    12 авг 2003
    Сообщения:
    1.159
    Адрес:
    SPb
    См. условия задачи, метод никак не взаимодействует с экземпляром класса.
    Если бы взаимодействие было, пришлось бы искать и вызывать конструктор, либо имитировать те поля объекта, которые задействованы при вызове. Это, кстати, в мой пример добавить совсем несложно.
     
  11. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Squash
    Об этом только автор топа в курсе.
     
  12. Ezrah

    Ezrah Member

    Публикаций:
    0
    Регистрация:
    22 мар 2011
    Сообщения:
    411
    Это я погорячился, видимо подумал о чём-то другом.
     
  13. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
    Тогда этот метод ничем не отличается от обычной функции, и заморачиваться с передачей this не нужно.
     
  14. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Squash
    Не, опять не то. Раз речь идет о перехвате с последующим вызовом оригинальной функции, то передавать в нее нужно именно оригинальное значение this, а не какаую-то "имитацию".
    И если юзать vtbl, то самым "тупым" очевидным решением было бы восстановить перед вызовом указатель на функцию в vtbl, вызвать функцию, а затем снова изменить ук-ль в vtbl на адрес функции-перехватчика. Автор тут немного "темнит"\не_договаривает с механизмом установки перехвата через detours, но кроме адреса самой функции, ему по идее д.б. известен и адрес\смещение этого ук-ля в vtbl

    reverser
    Кстати, да. И это наталкивает на мысль о возможности еще одного "изврата" с неявной передачей ecx=this в обычную функцию - если завернуть вызов функции по указателю в простейший метод класса (который лишь вызывает ф-ю по указателю), то скорее всего на момент вызова в ecx будет сидеть именно this и функция отработает как положено по __thiscall
     
  15. Ezrah

    Ezrah Member

    Публикаций:
    0
    Регистрация:
    22 мар 2011
    Сообщения:
    411
    Не прокатит для многопоточного приложения.
    reverser
    #52