visual studio — получить начальный адрес функции из конечного адреса / получить размер функции

Я использую / Gh и / GH опцию компилятора Visual Studio для профилирования группы кода. Используются два метода: _penter и _pexit, которые вызываются при входе или выходе функции в профилируемом коде. Поскольку мне нужно профилировать / отлаживать определенные функции, я использую уже определенный массив FuncTable который содержит адреса функций, которые мне нужны для инструмента с их именами в виде строки. Поэтому, когда функция введена, pStack [0], который в основном содержит содержимое регистра, содержит адрес текущей строки исполняемого кода. Точно так же, когда выход из функции, pStack [0] содержит адрес последней строки кода.

ПРОБЛЕМА: Когда функция введена (вызывается _penter), я получаю адрес первой строки функции в pStack [0], и, следовательно, я могу получить адрес функции, вычитая константу (-5), и сохранить ее в своем списке, чтобы быть найденным позже в функции _pexit. Но поскольку в _pexit я получаю адрес до последней строки функции, мне нужно найти размер функции, чтобы вычесть этот размер из адреса в pStack [0], чтобы получить начальный адрес функции, а затем сравнить этот адрес для тех, которые сохранены в моем списке. Ниже приведен код.

void _stdcall EnterFunc0(unsigned * pStack)
{
void      * pCaller;
pCaller = (void *)(pStack[0] - 5); // pStack[0] is first line, -5 for function address
Signature * funct = FuncTable;

while (funct->function)
{
const BYTE * func = (const BYTE *)funct->function;
if ((func == (const BYTE *)pCaller) || ((*func == 0xE9) && ((func + *(DWORD *)(func + 1) + 5) == (const BYTE *)pCaller)))
{
Stack_Push(funct->name, funct->returnType, true, pCaller);
}
funct++;
}

}

extern "C" __declspec(naked) void __cdecl _penter()
{
_asm
{
pushad              // save all general purpose registers
mov    eax, esp     // current stack pointer
add    eax, 32      // stack pointer before pushad
push   eax          // push pointer to return address as parameter to EnterFunc0

call   EnterFunc0

popad               // restore general purpose registers
ret                 // start executing original function
}
}
void _stdcall ExitFunc0(unsigned * pStack)
{
if (startRecording)
{
StackEntry * start = top;
while (start != NULL)
{
//**HERE I NEED TO COMPARE THE ADDRESS OF THE FUNCTION WITH THE ONE ALREADY IN MY STACK**
if ((void *)(pStack[0] - sizeOfTheFunction) == start->Address)
{
OutputDebugString("Function Found\n");
}
start = start->next;
}
}

}
extern "C" __declspec(naked) void __cdecl _pexit()
{
_asm
{
pushad              // save all general purpose registers
mov    eax, esp     // current stack pointer
add    eax, 32      // stack pointer before pushad
push   eax          // push pointer to return address as parameter to EnterFunc0

call   ExitFunc0

popad               // restore general purpose registers
ret                 // start executing original function
}
}

2

Решение

Вы уже знаете адрес в своей функции _pexit (), он был передан вам в функции _penter (). Все, что вам нужно сделать, это поддерживать вызовы вложенных функций. Std :: stack<> Это хорошо для этого. Используйте push (), чтобы сохранить адрес в _penter, получить его с помощью top () в функции _pexit и вызвать pop ().

Больше не нужно знать размер тела функции.

2

Другие решения

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

(Это должно быть верно, если вы не вызываете одну из функций вручную, чего не следует делать, или не имеете многопоточной программы. В последнем случае вам следует создать частный стек для каждого потока. Конечно, у вас также будет добавить Stack_Pop обращение к _pexit, но я предполагаю, что вы все равно планировали это сделать.)

0

Оказывается, я смотрел на проблему неправильно. Я решил проблему, получив информацию о символах с помощью SymFromAddress метод, из dbghelp.lib. Получив название метода, я смог сравнить его с информацией, хранящейся в _penter.

SYMBOL_INFO  * mysymbol;
HANDLE         process;
char           temp[MAX_TEMP_LENGTH] = "                                                                       ";

process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE);

mysymbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
mysymbol->MaxNameLen = 255;
mysymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
SymFromAddr(process, (DWORD64)((void *)pStack[0]), 0, mysymbol);
OutputDebugString(mysymbol->Name);
OutputDebugString("\n");
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector