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(进程句柄,