Why isn't SymGetSymFromAddr64 working? It returns error code 126
Asked Answered
T

1

4

I am trying to capture a stack trace on exceptions using the following code:

#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;
}

Output:

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.

I'm a little baffled as to why SymGetSymFromAddr64 is failing. Any ideas?

126 should be a missing dependency, but I have the DLL in the appropriate folder...I am running this all in a MSVC++ console application on a Windows 8.1 x64 PC using a Win32 platform Debug build. So what could be causing the problem?

Update: Dependency walker is telling me it can't find API-MS-WIN-SERVICE-PRIVATE-L1-1-1.DLL

Trump answered 18/3, 2014 at 13:38 Comment(0)
M
2

Had the same problem with your code.

Fixed it with:

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

Note: now, the SymGetLineFromAddr64 fails for some big address, with error 487 (ERROR_INVALID_ADDRESS)

Use the following for tracing:

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

EDIT: when I use the Go to Disassembly in my Visual Studio and enter the fist address which make SymGetLineFromAddr64 fail (here, it's 0x000000005a03da08), it shows the source code for:

f:\dd\vctools\crt_bld\self_x86\crt\prebuild\eh\throw.cpp

Mou answered 18/3, 2014 at 15:11 Comment(7)
You know whats funny, I just had the same realization when I went to check your post, cuz I was trying to backtrace it to what we did before and in the docs for SymGetLineFromAddr64 I read the following line: hProcess [in] A handle to the process that was originally passed to the SymInitialize function. I should probably read the docs more, huh? :) Thanks again. Now we have a global exception handler that works!Trump
Also from reading the docs, frame.AddrFrame.Offset should be context->Rbp; for x64...it seems since I copied some of this stuff from the stackwalker implementation on code project, it had its own errors in it :)Trump
Man, this kicks ass. I love it.Trump
Also some more adjustments I made in case anyone comes around this article and wants to do the same thing: You should use SymFromAddr instead of SymGetSymFromAddr64 (according to the source comments in SymGetSymFromAddr64), which means using SYMBOL_INFO instead of IMAGEHLP_SYMBOL64. Confirmed working on x64 and x86 builds on an x64 machine in both debug and release :)Trump
Any idea how to make this go deeper? Like, I want this code to run for all exceptions and give me the trace starting from the location the exception was raised/thrown...something like using AddVectoredExceptionHandler to do it: #19657446Trump
@Trump Sorry, I know nothing about that kind of problems and APIs.Mou
I'm trying to find a better alternative. Actually reading up about it in this article is really interesting: codeproject.com/Articles/207464/…Trump

© 2022 - 2024 — McMap. All rights reserved.