Почему не работает SymGetSymFromAddr64? Возвращает код ошибки 126

Я пытаюсь захватить трассировку стека исключений, используя следующий код:

#include "stdafx.h"#include <process.h>
#include <iostream>
#include <Windows.h>
#include "dbghelp.h"
using namespace std;

#define TRACE_MAX_FUNCTION_NAME_LENGTH 1024

void function2()
{
int a = 0;
int b = 0;
throw new exception;
}

void function1()
{
int a = 0;
function2();
}

void function0()
{
function1();
}

LONG WINAPI FatalExceptionFilter(EXCEPTION_POINTERS* exception, DWORD exceptionCode)
{
CONTEXT *context = exception->ContextRecord;
HANDLE thread = GetCurrentThread();
HANDLE process = GetCurrentProcess();
STACKFRAME64 frame;
DWORD image;
#ifdef _M_IX86
image = IMAGE_FILE_MACHINE_I386;
frame.AddrPC.Offset = context->Eip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context->Ebp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrStack.Offset = context->Esp;
frame.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
image = IMAGE_FILE_MACHINE_AMD64;
frame.AddrPC.Offset = context->Rip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context->Rsp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrStack.Offset = context->Rsp;
frame.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
image = IMAGE_FILE_MACHINE_IA64;
frame.AddrPC.Offset = context->StIIP;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context->IntSp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrBStore.Offset = context->RsBSP;
frame.AddrBStore.Mode = AddrModeFlat;
frame.AddrStack.Offset = context->IntSp;
frame.AddrStack.Mode = AddrModeFlat;
#else
#error "This platform is not supported."#endif
IMAGEHLP_SYMBOL64 *symbol = (IMAGEHLP_SYMBOL64 *)malloc(sizeof(IMAGEHLP_SYMBOL64)+(TRACE_MAX_FUNCTION_NAME_LENGTH - 1) * sizeof(TCHAR));
symbol->MaxNameLength = TRACE_MAX_FUNCTION_NAME_LENGTH;
symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
IMAGEHLP_LINE64 *line = (IMAGEHLP_LINE64 *)malloc(sizeof(IMAGEHLP_LINE64));
line->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
while (StackWalk64(image, process, thread, &frame, context, NULL, NULL, NULL, NULL))
{
DWORD64 displacement64;
if (SymGetSymFromAddr64(process, frame.AddrPC.Offset, &displacement64, symbol))
{
DWORD displacement;
if (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &displacement, line))
{
printf("\tat %s in %s: line: %lu: address: 0x%0X\n", symbol->Name, line->FileName, line->LineNumber, symbol->Address);
}
else
{
printf("Error from SymGetLineFromAddr64: %lu.\n", GetLastError());
}
}
else
{
printf("Error from SymGetSymFromAddr64: %lu.\n", GetLastError());
}
}
return EXCEPTION_EXECUTE_HANDLER;
}

static void threadFunction(void *param)
{
__try
{
function0();
}
__except (FatalExceptionFilter(GetExceptionInformation(), GetExceptionCode()))
{ }
}

int _tmain(int argc, _TCHAR* argv[])
{
_beginthread(threadFunction, 0, NULL);
printf("Press any key to exit.\n");
cin.get();
return 0;
}

Выход:

Press any key to exit.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.
Error from SymGetSymFromAddr64: 126.

Я немного сбит с толку относительно того, почему SymGetSymFromAddr64 терпит неудачу. Есть идеи?

126 должно быть отсутствующей зависимостью, но у меня есть DLL в соответствующей папке … Я запускаю все это в консольном приложении MSVC ++ на ПК с Windows 8.1 x64 с использованием отладочной сборки платформы Win32. Так что может быть причиной проблемы?

Обновить: Обходчик зависимостей говорит мне, что не может найти API-MS-WIN-SERVICE-PRIVATE-L1-1-1.DLL

2

Решение

Была такая же проблема с вашим кодом.

Исправлено с помощью:

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

Примечание: теперь SymGetLineFromAddr64 не удается для большого адреса с ошибкой 487 (ERROR_INVALID_ADDRESS)

Используйте следующее для отслеживания:

printf("Error from SymGetLineFromAddr64: %lu for address 0x%I64x.\n",
GetLastError(),
frame.AddrPC.Offset);

РЕДАКТИРОВАТЬ: когда я использую Перейти к разборке в моей Visual Studio и введите первый адрес, который делает SymGetLineFromAddr64 потерпеть неудачу (здесь это 0x000000005a03da08), он показывает исходный код для:

F: \ дд \ vctools \ crt_bld \ self_x86 \ элт \ prebuild \ а \ throw.cpp

2

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

Других решений пока нет …

По вопросам рекламы [email protected]