Я работаю над кодом, чтобы попытаться отслеживать трассировку стека и попытался использовать регистры отладки и векторную обработку исключений (для x86). Я сделал пример программы, которая будет выводить адрес любого доступа к текущему адресу возврата. Это работает, если в вызываемой функции встречается трассировка стека. Если это не так (закомментируйте код, который читает обратный адрес), триггеры исключения в команде возврата. Отсюда мой обработчик исключений не вызывается, и программа выдает другое исключение, а затем завершается ошибкой stackhash. Есть ли способ сделать этот захват трассировкой стека, если он встречается, но также не сбой при возврате, если трассировка стека не происходит?Ловушка Stacktraces с отладочным регистром Точки останова и векторная обработка исключений
Вот код моей тестовой программы, написанные для Visual Studio 2012 (C, x86)
#include <Windows.h>
#include <stdio.h>
DWORD WINAPI myFunction(void);
void myFunction2(void);
DWORD WINAPI ExceptionHandler(EXCEPTION_POINTERS *pExceptionInfo);
int main()
{
HANDLE thread = GetCurrentThread();
static CONTEXT context;
AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)ExceptionHandler);
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
GetThreadContext(thread, &context);
context.Dr6 = 0;
context.Dr7 = 0;
context.Dr7 |= (3 << 16); //set bits 16-17 to 1 - break read/write
context.Dr7 |= (3 << 18); //set bits 18-19 to 1 - size = 4
context.Dr7 |= 0x101; //enable local hardware breakpoint on dr0
context.Dr7 |= 1 << 13;
_asm {
push offset label //push return address
lea eax, [esp]
mov context.Dr0, esp
}
SetThreadContext(thread, &context);
__asm
{
jmp myFunction // "call" myFunction
label:
}
printf("Return from my function\n");
getchar();
return 0;
}
// try windows api stack trace
DWORD WINAPI myFunction(void)
{
PVOID out[10];
CaptureStackBackTrace(0, 10, out, 0);
return 0;
}
// simple pull return address from esp
void __declspec(naked) myFunction2(void)
{
__asm{
mov eax, [esp]
ret
}
}
DWORD WINAPI ExceptionHandler(EXCEPTION_POINTERS *pExceptionInfo)
{
//Handle hwbp
if(pExceptionInfo->ExceptionRecord->ExceptionCode==EXCEPTION_SINGLE_STEP && //hardware breakpoints are SINGLE_STEP
(pExceptionInfo->ContextRecord->Dr6 & 1)) //check to see that instruction occured on Dr0
{
pExceptionInfo->ContextRecord->Dr7 &= 0xfffffffe; // disable Dr0
printf("Hardware breakpoint triggered at %08Xh\n", pExceptionInfo->ExceptionRecord->ExceptionAddress);
return EXCEPTION_CONTINUE_EXECUTION;
}
printf("Other exception\n");
return EXCEPTION_CONTINUE_SEARCH;
}
сначала вы должны установить 'pExceptionInfo-> ContextRecord-> ContextFlags | = CONTEXT_DEBUG_REGISTERS;' в 'ExceptionHandler' без этого все ваши изменения потеряны – RbMm