Несовместимый адрес указателя функции с тем, что показывает отладчик - PullRequest
2 голосов
/ 14 февраля 2012

Прежде всего - я прошу прощения, если этот вопрос показывает невежество или я чего-то не знаю. Я пытаюсь сделать что-то, что включает чтение инструкций под адресом функции, и мне уже удалось получить размер сгенерированного кода функции, изучив файл .pdb, сгенерированный компилятором.

Но что-то меня смущает, посмотрите на следующий пример:

int function(int a, int b)
{
    return a + b;
}

int main(int argc, char* argv[])
{
    // (...)
    void* address = &function;
    function(10, 20);
    // (...)
}

Для определенного запуска под отладчиком у меня есть 0x00c011f4, сохраненный в адресе void *, и окно дизассемблирования VS показывало соответственно:

int main(int argc, char* argv[])
{
00C04B00  push        ebp  
00C04B01  mov         ebp,esp  
00C04B03  sub         esp,178h  
00C04B09  push        ebx  
00C04B0A  push        esi  
00C04B0B  push        edi  
00C04B0C  lea         edi,[ebp-178h]  
00C04B12  mov         ecx,5Eh  
00C04B17  mov         eax,0CCCCCCCCh  
00C04B1C  rep stos    dword ptr es:[edi]  
    void* address = &function;
00C04B1E  mov         dword ptr [address],offset function (0C011F4h)  
    function(10, 20);
00C04B25  push        14h  
00C04B27  push        0Ah  
00C04B29  call        function (0C011F4h)  
00C04B2E  add         esp,8  

В соответствии с инструкцией под 00C04B1E адрес, который соответствует началу function, находится под 0C011F4 - это именно то, что сохраняется в void * address.

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

int function(int a, int b)
{
00C019C0  push        ebp  
00C019C1  mov         ebp,esp  
00C019C3  sub         esp,0C0h  
00C019C9  push        ebx  
00C019CA  push        esi  
00C019CB  push        edi  
00C019CC  lea         edi,[ebp-0C0h]  
00C019D2  mov         ecx,30h  
00C019D7  mov         eax,0CCCCCCCCh  
00C019DC  rep stos    dword ptr es:[edi]  
    return a + b;
00C019DE  mov         eax,dword ptr [a]  
00C019E1  add         eax,dword ptr [b]  
}
00C019E4  pop         edi  
00C019E5  pop         esi  
00C019E6  pop         ebx  
00C019E7  mov         esp,ebp  
00C019E9  pop         ebp  
00C019EA  ret  

Здесь начало функции (int, int) меньше 0x00C019C0. Это почему? это 1996 байт друг от друга. Я пытался найти какую-либо корреляцию, но я думаю, что мне здесь не хватает чего-то фундаментального. Может кто-нибудь сказать мне, почему эти два адреса разные?

Также, когда я копирую область, указанную адресом void * (0C011F4), я не получаю машинный код, который соответствует инструкциям asm, которые находятся под функцией (int, int).

Заранее спасибо!

Конвертер: Windows x64, VC10

1 Ответ

4 голосов
/ 14 февраля 2012

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

Вы можете удалить это, используя режим выпуска или отключив Edit & Continue.В качестве альтернативы вы можете взять длинный маршрут и просто разобрать прыжок (это должен быть 32-разрядный относительный переход), и отрегулировать адрес, используя относительное смещение прыжка.

...