Windows SymGetLineFromAddr64给出错误7e/1e7

Windows SymGetLineFromAddr64给出错误7e/1e7,windows,winapi,Windows,Winapi,我正在写一个小调试器。当程序通过调用SymGetLineFromAddr64跳转到调试器时,我试图找到文件和代码行。当主机进程中断时,我调用gethreadcontext获取寄存器,StackWalk64获取当前堆栈,以及SymGetSymFromAddr64获取符号,所有这些都可以正常工作。然后我从addr64调用symgetlinefromr64,它失败了,出现了一系列奇怪的错误。输出的相关部分是: Loaded 'D:\git\debugging\Debug\debugging.exe'

我正在写一个小调试器。当程序通过调用
SymGetLineFromAddr64
跳转到调试器时,我试图找到文件和代码行。当主机进程中断时,我调用
gethreadcontext
获取寄存器,
StackWalk64
获取当前堆栈,以及
SymGetSymFromAddr64
获取符号,所有这些都可以正常工作。然后我从addr64调用
symgetlinefromr64
,它失败了,出现了一系列奇怪的错误。输出的相关部分是:

Loaded 'D:\git\debugging\Debug\debugging.exe' at 10000000 with symbols.

(Later on, for the first auto-breakpoint that gets called when the program first starts running)

Breakpoint.
Thread context successful.
Stack walk successful.
SymGetLineFromAddr64(PC) error: 487/1e7
SymGetLineFromAddr64(Frame) error: 126/7e
SymGetLineFromAddr64(Stack) error: 126/7e

(I type 'go' and the program proceeds to an actual breakpoint, a __debugbreak() call in the program.)

Breakpoint.
Thread context successful.
Stack walk successful.
SymGetSymFromAddr64 failed. error: 126/7e
SymGetLineFromAddr64(PC) error: 126/7e
SymGetLineFromAddr64(Frame) error: 126/7e
SymGetLineFromAddr64(Stack) error: 126/7e
错误126/7e是
Error\u MOD\u NOT\u FOUND
,但是我已经成功地加载了调试符号,正如您可以从上面的输出中看到的那样。错误487/1e7是
Error\u INVALID\u ADDRESS
,不确定这意味着什么,也不知道为什么在内存窗口中调出指定的地址时,它只显示在程序计数器上,给了我有效的内存,正如您所期望的那样,在地址的前面有一个
CC
断点

在有人问:是的,我确实看了这个问题:正如你从我的代码中看到的,我已经有了一个符号初始化,所以答案没有帮助

完整代码列表:

#include <Windows.h>
#include <DbgHelp.h>
#include <Psapi.h>
#include <stdio.h>
#include <string>
#include <locale>
#include <codecvt>

HANDLE process_handle;
DWORD process_id;
HANDLE thread_handle;
DWORD thread_id;
const char* process_file = "D:\\git\\debugging\\Debug\\debugging.exe";
STACKFRAME64 stack;
typedef enum {
    DBGFLAG_NONE = 0,
    DBGFLAG_BROKEN = (1 << 0),
    DBGFLAG_FIRSTBREAK = (1 << 1),
} dbgflags;
dbgflags debug_flags;

std::string GetFileNameFromHandle(HANDLE hFile);

char* EventIDToString(DWORD id)
{
    switch (id)
    {
    case 3: return "CREATE_PROCESS_DEBUG_EVENT";
    case 2: return "CREATE_THREAD_DEBUG_EVENT";
    case 1: return "EXCEPTION_DEBUG_EVENT";
    case 5: return "EXIT_PROCESS_DEBUG_EVENT";
    case 4: return "EXIT_THREAD_DEBUG_EVENT";
    case 6: return "LOAD_DLL_DEBUG_EVENT";
    case 8: return "OUTPUT_DEBUG_STRING_EVENT";
    case 9: return "RIP_EVENT";
    case 7: return "UNLOAD_DLL_DEBUG_EVENT";
    case 0: return "No event";
    default: return "Unknown event";
    }
}

DWORD ProcessEvent(DEBUG_EVENT* de)
{
    switch (de->dwDebugEventCode)
    {
    default:
        printf("Processing event code: %d (%s)\n", de->dwDebugEventCode, EventIDToString(de->dwDebugEventCode));
        break;

    case CREATE_PROCESS_DEBUG_EVENT:
    {
        DWORD options = SymGetOptions();
        options |= SYMOPT_DEBUG;
        ::SymSetOptions(options);

        std::string directory = process_file;
        directory = directory.substr(0, directory.find_last_of('\\'));
        BOOL r = SymInitialize(process_handle, directory.c_str(), false);
        if (r)
            printf("Initialized symbols\n");
        else
        {
            printf("Symbol initialization failed\n");
            break;
        }

        HANDLE hFile = CreateFile(process_file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
        DWORD size = GetFileSize(hFile, NULL);
        CloseHandle(hFile);

        DWORD64 dwBase = SymLoadModule64(process_handle, NULL, process_file, 0, (DWORD64)0x10000000, size);

        IMAGEHLP_MODULE64 mi;
        mi.SizeOfStruct = sizeof(mi);
        r = SymGetModuleInfo64(process_handle, dwBase, &mi);

        if (r && mi.SymType == SymPdb)
            printf((std::string("Loaded '") + process_file + std::string("' at %x with symbols\n")).c_str(), 0x10000000);
        else
            printf((std::string("Loaded '") + process_file + std::string("' at %x without symbols\n")).c_str(), 0x10000000);

        break;
    }

    case LOAD_DLL_DEBUG_EVENT:
    {
        std::string image = GetFileNameFromHandle(de->u.LoadDll.hFile);

        DWORD64 dwBase = SymLoadModule64(process_handle, NULL, image.c_str(), 0, (DWORD64)de->u.LoadDll.lpBaseOfDll, 0);

        IMAGEHLP_MODULE64 mi;
        mi.SizeOfStruct = sizeof(mi);
        BOOL r = SymGetModuleInfo64(process_handle, dwBase, &mi);

        if (r && mi.SymType == SymPdb)
            printf((std::string("Loaded '") + image + std::string("' at %x with symbols\n")).c_str(), de->u.LoadDll.lpBaseOfDll);
        else
            printf((std::string("Loaded '") + image + std::string("' at %x without symbols\n")).c_str(), de->u.LoadDll.lpBaseOfDll);
    }

    case EXCEPTION_DEBUG_EVENT:
    {
        DWORD code = de->u.Exception.ExceptionRecord.ExceptionCode;
        switch (code)
        {
        case 0x80000003:
            printf("Breakpoint.\n");
            return DBG_CONTROL_BREAK;
            break;

        default:
            printf("Exception code: %x\n", code);
            return DBG_EXCEPTION_NOT_HANDLED;
        }
        break;
    }

    case OUTPUT_DEBUG_STRING_EVENT:
    {
        SIZE_T read;
        char* buffer = new char[de->u.DebugString.nDebugStringLength*(de->u.DebugString.fUnicode + 1)];

        ReadProcessMemory(process_handle, de->u.DebugString.lpDebugStringData, buffer, de->u.DebugString.nDebugStringLength, &read);

        std::string debug;
        if (de->u.DebugString.fUnicode)
        {
            std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
            debug = converter.to_bytes((wchar_t*)buffer);
        }
        else
            debug = buffer;

        delete buffer;

        printf("Debug: %s\n", debug.c_str());
        break;
    }
    }
    return DBG_CONTINUE;
}

void FindCode()
{
    IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)new char[sizeof(IMAGEHLP_SYMBOL64) + MAX_SYM_NAME];
    memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + MAX_SYM_NAME);
    symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
    symbol->MaxNameLength = MAX_SYM_NAME;

    DWORD64 displacement64;

    BOOL b = SymGetSymFromAddr64(process_handle, stack.AddrPC.Offset, &displacement64, symbol);
    DWORD e = GetLastError();
    if (!b)
        printf("SymGetSymFromAddr64 failed. error: %d/%x\n", e, e);

    DWORD displacement;

    IMAGEHLP_LINE64 line = { 0 };
    line.SizeOfStruct = sizeof(line);

    BOOL r = SymGetLineFromAddr64(process_handle, stack.AddrPC.Offset, &displacement, &line);
    e = GetLastError();
    printf("SymGetLineFromAddr64(PC) error: %d/%x\n", e, e);

    r = SymGetLineFromAddr64(process_handle, stack.AddrFrame.Offset, &displacement, &line);
    e = GetLastError();
    printf("SymGetLineFromAddr64(Frame) error: %d/%x\n", e, e);

    r = SymGetLineFromAddr64(process_handle, stack.AddrStack.Offset, &displacement, &line);
    e = GetLastError();
    printf("SymGetLineFromAddr64(Stack) error: %d/%x\n", e, e);

    /*  const size_t file_length = 1000;
    PSYMBOL_INFO si = (PSYMBOL_INFO)new char[sizeof(SYMBOL_INFO) + file_length];
    memset(si, 0, sizeof(SYMBOL_INFO) + file_length);
    si->SizeOfStruct = sizeof(SYMBOL_INFO);
    si->MaxNameLen = file_length;

    BOOL r = SymFromAddr(process_handle, stack.AddrPC.Offset, &displacement64, si);*/

    delete symbol;
}

void main()
{
    STARTUPINFO si = { 0 };
    si.cb = sizeof(si);
    PROCESS_INFORMATION pi = { 0 };
    BOOL r = CreateProcess(NULL, (char*)process_file, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi);

    process_handle = pi.hProcess;
    process_id = pi.dwProcessId;

    while (true)
    {
        if (debug_flags & DBGFLAG_BROKEN)
        {
            char input[100];
            gets_s(input);

            if (strcmp(input, "go") == 0)
            {
                printf("Continuing...\n");
                ContinueDebugEvent(process_id, thread_id, DBG_CONTINUE);
                debug_flags = (dbgflags)(debug_flags & ~DBGFLAG_BROKEN);
                CloseHandle(thread_handle);
            }
        }
        else
        {
            DEBUG_EVENT de = { 0 };
            WaitForDebugEvent(&de, 0);
            if (de.dwDebugEventCode)
            {
                DWORD control = ProcessEvent(&de);

                thread_id = de.dwThreadId;

                if (control == DBG_CONTROL_BREAK)
                {
                    thread_handle = OpenThread(READ_CONTROL | THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, false, de.dwThreadId);

                    debug_flags = (dbgflags)(debug_flags | DBGFLAG_BROKEN);

                    CONTEXT c = { 0 };
                    c.ContextFlags = CONTEXT_FULL;

                    BOOL b = GetThreadContext(thread_handle, &c);
                    if (b)
                        printf("Thread context successful.\n");
                    else
                        printf("Thread context failed.\n");

                    STACKFRAME64 sf = { 0 };
                    sf.AddrPC.Mode = sf.AddrFrame.Mode = sf.AddrStack.Mode = AddrModeFlat;
                    sf.AddrPC.Offset = c.Eip;
                    sf.AddrFrame.Offset = c.Ebp;
                    sf.AddrStack.Offset = c.Esp;

                    BOOL r = StackWalk64(IMAGE_FILE_MACHINE_I386, process_handle, thread_handle, &sf, &c,
                        NULL, &SymFunctionTableAccess64, &SymGetModuleBase64, NULL);

                    stack = sf;

                    if (r)
                        printf("Stack walk successful.\n");
                    else
                        printf("Stack walk failed.\n");

                    FindCode();
                }
                else
                {
                    ContinueDebugEvent(de.dwProcessId, de.dwThreadId, control);

                    if (!control)
                        process_handle = false;
                }
            }
        }
    }
}




std::string GetFileNameFromHandle(HANDLE hFile)
{
    BOOL bSuccess = FALSE;
    TCHAR pszFilename[MAX_PATH + 1];
    HANDLE hFileMap;

    std::string strFilename;

    // Get the file size.
    DWORD dwFileSizeHi = 0;
    DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);

    if (dwFileSizeLo == 0 && dwFileSizeHi == 0)
    {
        return FALSE;
    }

    // Create a file mapping object.
    hFileMap = CreateFileMapping(hFile,
        NULL,
        PAGE_READONLY,
        0,
        1,
        NULL);

    if (hFileMap)
    {
        // Create a file mapping to get the file name.
        void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);

        if (pMem)
        {
            if (GetMappedFileName(GetCurrentProcess(),
                pMem,
                pszFilename,
                MAX_PATH))
            {
#define BUFSIZE 1000
                // Translate path with device name to drive letters.
                TCHAR szTemp[BUFSIZE];
                szTemp[0] = '\0';

                if (GetLogicalDriveStrings(BUFSIZE - 1, szTemp))
                {
                    TCHAR szName[MAX_PATH];
                    TCHAR szDrive[3] = TEXT(" :");
                    BOOL bFound = FALSE;
                    TCHAR* p = szTemp;

                    do
                    {
                        // Copy the drive letter to the template string
                        *szDrive = *p;

                        // Look up each device name
                        if (QueryDosDevice(szDrive, szName, MAX_PATH))
                        {
                            size_t uNameLen = strlen(szName);

                            if (uNameLen < MAX_PATH)
                            {
                                bFound = _strnicmp(pszFilename, szName,
                                    uNameLen) == 0;

                                if (bFound)
                                {
                                    strFilename = std::string(szDrive) + (pszFilename + uNameLen);
                                }
                            }
                        }

                        // Go to the next NULL character.
                        while (*p++);
                    } while (!bFound && *p); // end of string
                }
            }
            bSuccess = TRUE;
            UnmapViewOfFile(pMem);
        }

        CloseHandle(hFileMap);
    }

    return(strFilename);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
处理过程\处理;
德沃德进程;
手柄螺纹与手柄;
德沃德螺纹;
const char*process\u file=“D:\\git\\Debug\\Debug\\Debug.exe”;
STACKFRAME64堆栈;
类型定义枚举{
DBGFLAG_NONE=0,
DBGFLAG_break=(1 dwDebugEventCode,EventIDToString(de->dwDebugEventCode));
打破
案例创建\流程\调试\事件:
{
DWORD options=SymGetOptions();
选项|=SYMOPT|U调试;
::SymSetOptions(选项);
std::string directory=process\u文件;
directory=directory.substr(0,directory.find\u last\u of('\\');
BOOL r=symcinitialize(进程句柄,directory.c_str(),false);
if(r)
printf(“初始化符号\n”);
其他的
{
printf(“符号初始化失败\n”);
打破
}
HANDLE hFile=CreateFile(进程文件、通用文件、文件共享文件、NULL、打开文件、0、NULL);
DWORD size=GetFileSize(hFile,NULL);
闭合手柄(hFile);
DWORD64 dwBase=SymLoadModule64(进程\句柄,NULL,进程\文件,0,(DWORD64)0x10000000,大小);
IMAGEHLP_模块64 mi;
mi.SizeOfStruct=sizeof(mi);
r=SymGetModuleInfo64(进程句柄、dwBase和mi);
if(r&&mi.SymType==SymPdb)
printf((std::string(“Loaded”))+进程文件+std::string(“'at%x,带符号“\n”)).c_str(),0x10000000);
其他的
printf((std::string(“Loaded”))+进程文件+std::string(“'at%x,不带符号”)).c_str(),0x10000000);
打破
}
案例加载\u DLL\u调试\u事件:
{
std::string image=GetFileNameFromHandle(de->u.LoadDll.hFile);
DWORD64 dwBase=SymLoadModule64(process_handle,NULL,image.c_str(),0,(DWORD64)de->u.LoadDll.lpbaseofdl,0);
IMAGEHLP_模块64 mi;
mi.SizeOfStruct=sizeof(mi);
BOOL r=symgetmoduleinfo 64(进程句柄、dwBase和mi);
if(r&&mi.SymType==SymPdb)
printf((std::string(“Loaded”)+image+std::string(“'at%x,带符号“\n”)).c_str(),de->u.LoadDll.lpbaseofdl);
其他的
printf((std::string(“Loaded”)+image+std::string(“'at%x,不带符号”)).c_str(),de->u.LoadDll.lpbaseofdl);
}
案例异常\u调试\u事件:
{
DWORD代码=de->u.Exception.ExceptionRecord.ExceptionCode;
开关(代码)
{
案例0x8000003:
printf(“断点。\n”);
返回DBG_控制_中断;
打破
违约:
printf(“异常代码:%x\n”,代码);
返回未处理的DBG_异常;
}
打破
}
案例输出\u调试\u字符串\u事件:
{
尺寸不可读取;
char*buffer=new char[de->u.DebugString.nDebugStringLength*(de->u.DebugString.fUnicode+1)];
ReadProcessMemory(进程句柄,de->u.DebugString.lpDebugStringData,缓冲区,de->u.DebugString.nDebugStringLength,&read);
字符串调试;
if(de->u.DebugString.fUnicode)
{
std::wstring_转换器;
调试=转换器到字节((wchar\u t*)缓冲区);
}
其他的
调试=缓冲区;
删除缓冲区;
printf(“调试:%s\n”,Debug.c_str());
打破
}
}
返回DBG_CONTINUE;
}
void FindCode()
{
IMAGEHLP_SYMBOL64*符号=(IMAGEHLP_SYMBOL64*)新字符[sizeof(IMAGEHLP_SYMBOL64)+最大SYM_名称];
memset(符号,0,sizeof(IMAGEHLP_SYMBOL64)+MAX_SYM_NAME);
symbol->SizeOfStruct=sizeof(图像HLP_SYMBOL64);
symbol->MaxNameLength=MAX_SYM_名称;
DWORD64位移64;
BOOL b=SymGetSymFromAddr64(进程句柄,stack.AddrPC.Offset和置换64,符号);
DWORD e=GetLastError();
如果(!b)
printf(“SymGetSymFromAddr64失败。错误:%d/%x\n”,e,e);
德沃德位移;
IMAGEHLP_LINE64 line={0};
line.SizeOfStruct=sizeof(line);
BOOL r=SymGetLineFromAddr64(进程句柄、stack.AddrPC.Offset、位移和行);
e=GetLastError();
printf(“SymGetLineFromAddr64(PC)错误:%d/%x\n”,e,e);
r=SymGetLineFromAddr64(进程\句柄、stack.AddrFrame.Offset、位移和行);
e=GetLastError();
printf(“SymGetLineFromAddr64(帧)错误:%d/%x\n”,e,e);
r=SymGetLineFromAddr64(进程\句柄、stack.AddrStack.Offset、位移和行);
e=GetLastError();
printf(“SymGetLineFromAddr64(堆栈)错误:%d/%x\n”,e,e);
/*常量大小文件长度=1000;
PSYMBOL_INFO si=(PSYMBOL_INFO)新字符[sizeof(SYMBOL_INFO)+文件长度];
memset(si,0,sizeof(SYMBOL\u INFO)+文件长度);
si->SizeOfStruct=sizeof(符号信息);
si->MaxNameLen=文件长度;
BOOL r=SymFromAddr(进程句柄,