static enum dbg_start minidump_do_reload(struct tgt_process_minidump_data* data) { ULONG size; MINIDUMP_DIRECTORY* dir; void* stream; DWORD pid = 1; /* by default */ HANDLE hProc = (HANDLE)0x900DBAAD; int i; MINIDUMP_MODULE_LIST* mml; MINIDUMP_MODULE* mm; MINIDUMP_STRING* mds; char exec_name[1024]; char name[1024]; unsigned len; /* fetch PID */ if (MiniDumpReadDumpStream(data->mapping, MiscInfoStream, &dir, &stream, &size)) { MINIDUMP_MISC_INFO* mmi = (MINIDUMP_MISC_INFO*)stream; if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID) pid = mmi->ProcessId; } /* fetch executable name (it's normally the first one in module list) */ strcpy(exec_name, "<minidump-exec>"); /* default */ if (MiniDumpReadDumpStream(data->mapping, ModuleListStream, &dir, &stream, &size)) { mml = (MINIDUMP_MODULE_LIST*)stream; if (mml->NumberOfModules) { char* ptr; mm = &mml->Modules[0]; mds = (MINIDUMP_STRING*)((char*)data->mapping + mm->ModuleNameRva); len = WideCharToMultiByte(CP_ACP, 0, mds->Buffer, mds->Length / sizeof(WCHAR), name, sizeof(name) - 1, NULL, NULL); name[len] = 0; for (ptr = name + len - 1; ptr >= name; ptr--) { if (*ptr == '/' || *ptr == '\\') { strcpy(exec_name, ptr + 1); break; } } if (ptr < name) strcpy(exec_name, name); } } if (MiniDumpReadDumpStream(data->mapping, SystemInfoStream, &dir, &stream, &size)) { MINIDUMP_SYSTEM_INFO* msi = (MINIDUMP_SYSTEM_INFO*)stream; const char *str; char tmp[128]; dbg_printf("WineDbg starting on minidump on pid %lu\n", pid); switch (msi->ProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_UNKNOWN: str = "Unknown"; break; case PROCESSOR_ARCHITECTURE_INTEL: strcpy(tmp, "Intel "); switch (msi->ProcessorLevel) { case 3: str = "80386"; break; case 4: str = "80486"; break; case 5: str = "Pentium"; break; case 6: str = "Pentium Pro/II"; break; default: str = "???"; break; } strcat(tmp, str); if (msi->ProcessorLevel == 3 || msi->ProcessorLevel == 4) { if (HIWORD(msi->ProcessorRevision) == 0xFF) sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIBYTE(LOWORD(msi->ProcessorRevision)), LOBYTE(LOWORD(msi->ProcessorRevision))); else sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIWORD(msi->ProcessorRevision), LOWORD(msi->ProcessorRevision)); } else sprintf(tmp + strlen(tmp), "-%d.%d", HIWORD(msi->ProcessorRevision), LOWORD(msi->ProcessorRevision)); str = tmp; break; case PROCESSOR_ARCHITECTURE_MIPS: str = "Mips"; break; case PROCESSOR_ARCHITECTURE_ALPHA: str = "Alpha"; break; case PROCESSOR_ARCHITECTURE_PPC: str = "PowerPC"; break; default: str = "???"; break; } dbg_printf(" %s was running on #%d %s CPU%s", exec_name, msi->u.s.NumberOfProcessors, str, msi->u.s.NumberOfProcessors < 2 ? "" : "s"); switch (msi->MajorVersion) { case 3: switch (msi->MinorVersion) { case 51: str = "NT 3.51"; break; default: str = "3-????"; break; } break; case 4: switch (msi->MinorVersion) { case 0: str = (msi->PlatformId == VER_PLATFORM_WIN32_NT) ? "NT 4.0" : "95"; break; case 10: str = "98"; break; case 90: str = "ME"; break; default: str = "5-????"; break; } break; case 5: switch (msi->MinorVersion) { case 0: str = "2000"; break; case 1: str = "XP"; break; case 2: str = "Server 2003"; break; default: str = "5-????"; break; } break; default: str = "???"; break; } dbg_printf(" on Windows %s (%lu)\n", str, msi->BuildNumber); /* FIXME CSD: msi->CSDVersionRva */ } dbg_curr_process = dbg_add_process(&be_process_minidump_io, pid, hProc); dbg_curr_pid = pid; dbg_curr_process->pio_data = data; dbg_set_process_name(dbg_curr_process, exec_name); SymInitialize(hProc, NULL, FALSE); if (MiniDumpReadDumpStream(data->mapping, ThreadListStream, &dir, &stream, &size)) { MINIDUMP_THREAD_LIST* mtl = (MINIDUMP_THREAD_LIST*)stream; MINIDUMP_THREAD* mt = &mtl->Threads[0]; dbg_add_thread(dbg_curr_process, mt->ThreadId, NULL, (void*)(DWORD_PTR)mt->Teb); } /* first load ELF modules, then do the PE ones */ if (MiniDumpReadDumpStream(data->mapping, Wine_ElfModuleListStream, &dir, &stream, &size)) { char buffer[MAX_PATH]; mml = (MINIDUMP_MODULE_LIST*)stream; for (i = 0, mm = &mml->Modules[0]; i < mml->NumberOfModules; i++, mm++) { mds = (MINIDUMP_STRING*)((char*)data->mapping + mm->ModuleNameRva); len = WideCharToMultiByte(CP_ACP, 0, mds->Buffer, mds->Length / sizeof(WCHAR), name, sizeof(name) - 1, NULL, NULL); name[len] = 0; if (SymFindFileInPath(hProc, NULL, name, (void*)(DWORD_PTR)mm->CheckSum, 0, 0, SSRVOPT_DWORD, buffer, validate_file, NULL)) SymLoadModule(hProc, NULL, buffer, NULL, mm->BaseOfImage, mm->SizeOfImage); else SymLoadModuleEx(hProc, NULL, name, NULL, mm->BaseOfImage, mm->SizeOfImage, NULL, SLMFLAG_VIRTUAL); } } if (MiniDumpReadDumpStream(data->mapping, ModuleListStream, &dir, &stream, &size)) { mml = (MINIDUMP_MODULE_LIST*)stream; for (i = 0, mm = &mml->Modules[0]; i < mml->NumberOfModules; i++, mm++) { mds = (MINIDUMP_STRING*)((char*)data->mapping + mm->ModuleNameRva); len = WideCharToMultiByte(CP_ACP, 0, mds->Buffer, mds->Length / sizeof(WCHAR), name, sizeof(name) - 1, NULL, NULL); name[len] = 0; SymLoadModule(hProc, NULL, name, NULL, mm->BaseOfImage, mm->SizeOfImage); } } if (MiniDumpReadDumpStream(data->mapping, ExceptionStream, &dir, &stream, &size)) { MINIDUMP_EXCEPTION_STREAM* mes = (MINIDUMP_EXCEPTION_STREAM*)stream; if ((dbg_curr_thread = dbg_get_thread(dbg_curr_process, mes->ThreadId))) { ADDRESS64 addr; dbg_curr_tid = mes->ThreadId; dbg_curr_thread->in_exception = TRUE; dbg_curr_thread->excpt_record.ExceptionCode = mes->ExceptionRecord.ExceptionCode; dbg_curr_thread->excpt_record.ExceptionFlags = mes->ExceptionRecord.ExceptionFlags; dbg_curr_thread->excpt_record.ExceptionRecord = (void*)(DWORD_PTR)mes->ExceptionRecord.ExceptionRecord; dbg_curr_thread->excpt_record.ExceptionAddress = (void*)(DWORD_PTR)mes->ExceptionRecord.ExceptionAddress; dbg_curr_thread->excpt_record.NumberParameters = mes->ExceptionRecord.NumberParameters; for (i = 0; i < dbg_curr_thread->excpt_record.NumberParameters; i++) { dbg_curr_thread->excpt_record.ExceptionInformation[i] = mes->ExceptionRecord.ExceptionInformation[i]; } memcpy(&dbg_context, (char*)data->mapping + mes->ThreadContext.Rva, min(sizeof(dbg_context), mes->ThreadContext.DataSize)); memory_get_current_pc(&addr); stack_fetch_frames(); be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0); stack_info(); be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context); stack_backtrace(mes->ThreadId); source_list_from_addr(&addr, 0); } } return start_ok; }
/*********************************************************************** * SymLoadModuleExW (DBGHELP.@) */ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageName, PCWSTR wModuleName, DWORD64 BaseOfDll, DWORD DllSize, PMODLOAD_DATA Data, DWORD Flags) { LPSTR ImageName, ModuleName; unsigned len; BOOL ret; if (wImageName) { len = WideCharToMultiByte(CP_ACP,0, wImageName, -1, NULL, 0, NULL, NULL); ImageName = HeapAlloc(GetProcessHeap(), 0, len); WideCharToMultiByte(CP_ACP,0, wImageName, -1, ImageName, len, NULL, NULL); } else ImageName = NULL; if (wModuleName) { len = WideCharToMultiByte(CP_ACP,0, wModuleName, -1, NULL, 0, NULL, NULL); ModuleName = HeapAlloc(GetProcessHeap(), 0, len); WideCharToMultiByte(CP_ACP,0, wModuleName, -1, ModuleName, len, NULL, NULL); } else ModuleName = NULL; ret = SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, DllSize, Data, Flags); HeapFree(GetProcessHeap(), 0, ImageName); HeapFree(GetProcessHeap(), 0, ModuleName); return ret; }
void PlatformDebugSymbols::loadSymbolInfo(mt_uint64 base_address, mt_uint64 len, const char* sympath) { LoadedModule ld; ld.oldBase = base_address; ld.len = len; ld.newBase = SymLoadModuleEx(GetCurrentProcess(), 0, sympath, 0, 0, 0, 0, 0); loadedModules.push_back(ld); }
void CDebugger::Hook(DWORD dwProcessId) { if (!m_pFuzz->m_bHook) { return; } HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); // Load symbol m_pSymbols->RefreshSymbols(hProcess); SymLoadModuleEx(hProcess, NULL, m_pModulePath, NULL, m_dwBaseOfDll, 0, NULL, 0); cout << "mod: " << m_pModulePath << "addr: " << m_dwBaseOfDll << endl; // Find api address PSYMBOL_INFO pSymInfo = m_pSymbols->SymbolFromName(m_pFuzz->m_pHookApi); if (pSymInfo) { cout << "[+] Address of " << pSymInfo->Name << ": " << pSymInfo->Address << endl; } else { cout << "[-] Address of " << m_pFuzz->m_pHookApi << " not found!" << endl; return; } unsigned int iHookAddr = (unsigned int)pSymInfo->Address; // Hook api address SIZE_T iWriteBytes; bool bSuccess = WriteProcessMemory(hProcess, (void*)iHookAddr, (void*)m_pFuzz->m_pHookCode, sizeof(m_pFuzz->m_pHookCode), &iWriteBytes); if (bSuccess) { cout << "[+] Hook success at" << iHookAddr << endl; } else { cout << "[-] Hook failed at" << iHookAddr << endl; } }
void AbstractBTGenerator::LoadSymbols() { TModulesMap modules = m_process.GetModules(); for (TModulesMap::iterator i = modules.begin(); i != modules.end(); i++) { MODULEINFO modInfo; ZeroMemory(&modInfo, sizeof(modInfo)); QString strModule = i.key(); GetModuleInformation(m_process.GetHandle(), i.value(), &modInfo, sizeof(modInfo)); SymLoadModuleEx( m_process.GetHandle(), NULL, (CHAR*) i.key().toLatin1().constData(), (CHAR*) i.key().toLatin1().constData(), (DWORD64) modInfo.lpBaseOfDll, modInfo.SizeOfImage, NULL, 0); LoadSymbol(strModule, (DWORD64) modInfo.lpBaseOfDll); if (!IsSymbolLoaded(strModule)) { emit MissingSymbol(strModule); } } emit DebugLine(QString()); }
//------------------------------------------------------------------------- DWORD64 Injector::_LoadSymbolModule( const CHAR* name ) { MODULEENTRY32 me; HANDLE handle; // loop until retries exhausted for( ULong retry = 0; retry < LOADSYMBOLMODULE_RETRIES; ++retry ) { // create toolhelp snapshot handle = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE|TH32CS_SNAPMODULE32, GetProcessId(_process) ); // if created if( handle != INVALID_HANDLE_VALUE ) { DWORD64 base_address = 0; // init me.dwSize = sizeof(me); // walk modules if( Module32First(handle, &me) ) { do { // if matches if( _stricmp(me.szModule, name) == 0 ) { // load module into symbol loader base_address = SymLoadModuleEx( _process, NULL, me.szExePath, me.szModule, (DWORD64)me.modBaseAddr, me.modBaseSize, NULL, 0); break; } } while( Module32Next(handle, &me) ); } // close toolhelp snapshot CloseHandle(handle); return base_address; } // wait a little Sleep(LOADSYMBOLMODULE_RETRYDELAY); } return 0; }
static void loadModule(HANDLE hProcess, HANDLE hFile, PCSTR pszImageName, LPVOID lpBaseOfDll) { if (!SymLoadModuleEx(hProcess, hFile, pszImageName, NULL, (UINT_PTR)lpBaseOfDll, 0, NULL, 0)) { OutputDebug("warning: SymLoadModule64 failed: 0x%08lx\n", GetLastError()); } if (hFile) { CloseHandle(hFile); } }
HRESULT JpfsvLoadModuleContext( __in JPFSV_HANDLE ContextHandle, __in PCWSTR ModulePath, __in_opt PCWSTR Alias, __in DWORD_PTR LoadAddress, __in_opt DWORD SizeOfDll ) { PJPFSV_CONTEXT Context = ( PJPFSV_CONTEXT ) ContextHandle; DWORD64 ImgLoadAddress; if ( ! Context || Context->Signature != JPFSV_CONTEXT_SIGNATURE || ! ModulePath || ! LoadAddress ) { return E_INVALIDARG; } EnterCriticalSection( &JpfsvpDbghelpLock ); ImgLoadAddress = SymLoadModuleEx( Context->ProcessHandle, NULL, ModulePath, Alias, LoadAddress, SizeOfDll, NULL, 0 ); LeaveCriticalSection( &JpfsvpDbghelpLock ); if ( 0 == ImgLoadAddress ) { DWORD Err = GetLastError(); if ( ERROR_SUCCESS == Err ) { // // This seems to mean that the module has already been // loaded. // return S_FALSE; } else { return HRESULT_FROM_WIN32( Err ); } } return S_OK; }
virtual void NotifyFunctionEmitted(const Function &F, void *Code, size_t Size, const EmittedFunctionDetails &Details) { #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_) assert(!jl_in_stackwalk); jl_in_stackwalk = 1; uintptr_t catchjmp = (uintptr_t)Code+Size; *(uint8_t*)(catchjmp+0) = 0x48; *(uint8_t*)(catchjmp+1) = 0xb8; // mov RAX, QWORD PTR [...] *(uint64_t*)(catchjmp+2) = (uint64_t)&_seh_exception_handler; *(uint8_t*)(catchjmp+10) = 0xff; *(uint8_t*)(catchjmp+11) = 0xe0; // jmp RAX PRUNTIME_FUNCTION tbl = (PRUNTIME_FUNCTION)((catchjmp+12+3)&~(uintptr_t)3); uint8_t *UnwindData = (uint8_t*)((((uintptr_t)&tbl[1])+3)&~(uintptr_t)3); RUNTIME_FUNCTION fn = {0,(DWORD)Size+13,(DWORD)(intptr_t)(UnwindData-(uint8_t*)Code)}; tbl[0] = fn; UnwindData[0] = 0x09; // version info, UNW_FLAG_EHANDLER UnwindData[1] = 4; // size of prolog (bytes) UnwindData[2] = 2; // count of unwind codes (slots) UnwindData[3] = 0x05; // frame register (rbp) = rsp UnwindData[4] = 4; // second instruction UnwindData[5] = 0x03; // mov RBP, RSP UnwindData[6] = 1; // first instruction UnwindData[7] = 0x50; // push RBP *(DWORD*)&UnwindData[8] = (DWORD)(catchjmp-(intptr_t)Code); DWORD mod_size = (DWORD)(size_t)(&UnwindData[8]-(uint8_t*)Code); if (!SymLoadModuleEx(GetCurrentProcess(), NULL, NULL, NULL, (DWORD64)Code, mod_size, NULL, SLMFLAG_VIRTUAL)) { static int warned = 0; if (!warned) { JL_PRINTF(JL_STDERR, "WARNING: failed to insert function info for backtrace\n"); warned = 1; } } else { if (!SymAddSymbol(GetCurrentProcess(), (ULONG64)Code, F.getName().data(), (DWORD64)Code, mod_size, 0)) { JL_PRINTF(JL_STDERR, "WARNING: failed to insert function name into debug info\n"); } if (!RtlAddFunctionTable(tbl,1,(DWORD64)Code)) { JL_PRINTF(JL_STDERR, "WARNING: failed to insert function stack unwind info\n"); } } jl_in_stackwalk = 0; FuncInfo tmp = {&F, Size, std::string(), std::string(), tbl, Details.LineStarts}; #else FuncInfo tmp = {&F, Size, std::string(F.getName().data()), std::string(), Details.LineStarts}; #endif info[(size_t)(Code)] = tmp; }
// list all symbols of the module passed in void enumModulesDlg::GetModuleSymbols( PCSTR imageName, EnumModuleInfo *userContext ) { HANDLE hProcess = GetCurrentProcess(); // NOT safe to hookhop DWORD64 BaseOfDll; char *Mask = "*"; BOOL status; status = (BOOL)HookHop::FunctionHop(SymInitialize, hProcess, NULL, FALSE); if (status == FALSE) { return; } BaseOfDll = SymLoadModuleEx(hProcess, // NOT safe to hookhop NULL, imageName, NULL, 0, 0, NULL, 0); if (BaseOfDll == 0) { SymCleanup(hProcess); return; } if (::SymEnumSymbols( // One of the parameters is 64-bit, and so we can't use our hook hop hProcess, // Process handle from SymInitialize. BaseOfDll, // Base address of module. Mask, // Name of symbols to match. EnumSymProc, // Symbol handler procedure. userContext)) // User context. { // SymEnumSymbols succeeded } else { // SymEnumSymbols failed } SymCleanup( hProcess ); // NOT safe to hookhop }
//-------------------------------------------------------------------------------------- ULONGLONG GetSymbolByName(char *lpszModuleName, HMODULE hModule, char *lpszName) { ULONGLONG Ret = 0; // try to load debug symbols for module if (SymLoadModuleEx(GetCurrentProcess(), NULL, lpszModuleName, NULL, (DWORD64)hModule, 0, NULL, 0)) { ENUM_SYM_PARAM Param; Param.Address = NULL; Param.lpszName = lpszName; // get specified symbol address by name if (!SymEnumSymbols( GetCurrentProcess(), (DWORD64)hModule, NULL, EnumSymbolsProc, &Param)) { DbgMsg(__FILE__, __LINE__, "SymEnumSymbols() ERROR %d\n", GetLastError()); } if (Param.Address == NULL) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ERROR: Can't locate symbol\n"); } else { Ret = Param.Address; } // unload symbols SymUnloadModule64(GetCurrentProcess(), (DWORD64)hModule); } else { DbgMsg(__FILE__, __LINE__, "SymLoadModuleEx() ERROR %d\n", GetLastError()); } return Ret; }
DWORD64 WINAPI MgwSymLoadModuleEx(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD DllSize, PMODLOAD_DATA Data, DWORD Flags) { DWORD dwRet; dwRet = SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, DllSize, Data, Flags); if (BaseOfDll) { mgwhelp_module_lookup(hProcess, hFile, ImageName, BaseOfDll); } return dwRet; }
static void loadModule(HANDLE hProcess, HANDLE hFile, PCSTR pszImageName, LPVOID lpBaseOfDll) { bool deferred = SymGetOptions() & SYMOPT_DEFERRED_LOADS; // We must pass DllSize for deferred symbols to work correctly // https://groups.google.com/forum/#!topic/comp.os.ms-windows.programmer.win32/ulkwYhM3020 DWORD DllSize = 0; if (deferred) { DllSize = getModuleSize(hProcess, lpBaseOfDll); } if (!SymLoadModuleEx(hProcess, hFile, pszImageName, NULL, (UINT_PTR)lpBaseOfDll, DllSize, NULL, 0)) { OutputDebug("warning: SymLoadModule64 failed: 0x%08lx\n", GetLastError()); } // DbgHelp keeps an copy of hFile, and closing the handle here may cause // CBA_DEFERRED_SYMBOL_LOAD_PARTIAL events. if (hFile && !deferred) { CloseHandle(hFile); } }
const bool Symbols::EnumerateModuleSymbols(const char * const pModulePath, const DWORD64 dwBaseAddress) { DWORD64 dwBaseOfDll = SymLoadModuleEx(m_hProcess, m_hFile, pModulePath, nullptr, dwBaseAddress, 0, nullptr, 0); if (dwBaseOfDll == 0) { fprintf(stderr, "Could not load modules for %s. Error = %X.\n", pModulePath, GetLastError()); return false; } UserContext userContext = { this, pModulePath }; const bool bSuccess = BOOLIFY(SymEnumSymbols(m_hProcess, dwBaseOfDll, "*!*", SymEnumCallback, &userContext)); if (!bSuccess) { fprintf(stderr, "Could not enumerate symbols for %s. Error = %X.\n", pModulePath, GetLastError()); } return bSuccess; }
void *Ploopgrab(LPVOID args) { DEBUG_EVENT dbg; DWORD cont = DBG_CONTINUE, size = 0; TCHAR pszFilename[MAX_PATH+1]; DWORD64 mod; struct proc_uc *tmp = args; struct ps_prochandle *P = tmp->ps; int first_execp = 0; BOOL wow = 0; char *s; DWORD Options = SymGetOptions(); if (DebugActiveProcess(P->pid) == 0) { dprintf( "failed to debug process (%d): %d\n", P->pid, GetLastError() ); pthread_mutex_lock(&P->mutex); P->status = PS_STOP; P->flags = CREATE_FAILED; if (P->status == PS_STOP) pthread_cond_signal(&P->cond); pthread_mutex_unlock(&P->mutex); return NULL; } DebugSetProcessKillOnExit(FALSE); P->wstat = 0; P->exitcode = 0; P->event = CreateEvent(NULL,FALSE,FALSE,NULL); P->dll_load_order = 1; SymSetOptions(Options|SYMOPT_INCLUDE_32BIT_MODULES|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG); while (1) { if (WaitForDebugEvent(&dbg, INFINITE) == 0) { return NULL; } cont = DBG_CONTINUE; pthread_mutex_lock(&P->mutex); switch (dbg.dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: P->thandle = dbg.u.CreateProcessInfo.hThread; P->phandle = dbg.u.CreateProcessInfo.hProcess; if ((SymInitialize(P->phandle, 0, FALSE) == FALSE)) { dprintf("SymInitialize failed (%d): %d\n", P->pid, GetLastError()); break; } s = GetFileNameFromHandle(dbg.u.CreateProcessInfo.hFile, pszFilename); addmodule(P, dbg.u.CreateProcessInfo.hFile, s, dbg.u.CreateProcessInfo.lpBaseOfImage, PE_TYPE_EXE, P->dll_load_order); size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL); if (size == INVALID_FILE_SIZE) { size = 0; } if ((mod = SymLoadModuleEx(P->phandle, dbg.u.CreateProcessInfo.hFile, s, NULL, (ULONG_PTR) dbg.u.CreateProcessInfo.lpBaseOfImage, size, NULL, 0)) == FALSE) { dprintf("SymLoadModule64 Failed for %s: %d\n", s, GetLastError()); break; } #if __amd64__ if (Is32bitProcess(P->phandle)) { P->model = PR_MODEL_ILP32; wow = 1; } else P->model = PR_MODEL_ILP64; #else P->model = PR_MODEL_ILP32; #endif CloseHandle(dbg.u.CreateProcessInfo.hFile); P->status = PS_RUN; P->msg.type = 0; break; case CREATE_THREAD_DEBUG_EVENT: P->status = PS_RUN; P->msg.type = 0; break; case LOAD_DLL_DEBUG_EVENT: s = GetFileNameFromHandle(dbg.u.LoadDll.hFile, pszFilename); if (first_execp) { P->dll_load_order++; } addmodule(P, dbg.u.LoadDll.hFile, s, dbg.u.LoadDll.lpBaseOfDll, PE_TYPE_DLL, P->dll_load_order); size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL); if (size == INVALID_FILE_SIZE) { size = 0; } #if __amd64__ /* Not tracing 64 bit dlls for 32 bit process */ if (P->model == PR_MODEL_ILP32 && is64bitmodule(dbg.u.LoadDll.lpBaseOfDll, s)) { CloseHandle(dbg.u.LoadDll.hFile ); break; } #endif if ((mod = SymLoadModuleEx(P->phandle, dbg.u.LoadDll.hFile, s, NULL, (ULONG_PTR) dbg.u.LoadDll.lpBaseOfDll, size, NULL, 0)) == FALSE) { dprintf("SymLoadModule64 failed for %s: %d\n", s, GetLastError()); break; } CloseHandle(dbg.u.LoadDll.hFile ); if (first_execp == 0) { P->status = PS_RUN; P->msg.type = RD_DLACTIVITY; } else { P->status = PS_STOP; P->msg.type = RD_DLACTIVITY; } break; case UNLOAD_DLL_DEBUG_EVENT: if (SymUnloadModule64(P->phandle, (ULONG_PTR) dbg.u.UnloadDll.lpBaseOfDll) == FALSE) { dprintf("SymUnloadModule64 failed-Imagebase %p: %d\n", dbg.u.UnloadDll.lpBaseOfDll, GetLastError()); break; } delmodule(P, (ULONG64) dbg.u.UnloadDll.lpBaseOfDll); P->status = PS_RUN; P->msg.type = RD_DLACTIVITY; break; case EXIT_PROCESS_DEBUG_EVENT: P->exitcode = dbg.u.ExitProcess.dwExitCode; P->status = PS_UNDEAD; P->msg.type = RD_NONE; //SymCleanup(P->phandle); break; case EXIT_THREAD_DEBUG_EVENT: P->status = PS_RUN; P->msg.type = 0; break; case EXCEPTION_DEBUG_EVENT: switch(dbg.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_BREAKPOINT: if (first_execp++ == 0) { pthread_cond_signal(&P->cond); } P->status = PS_STOP; P->msg.type = 0; break; default: if (dbg.u.Exception.dwFirstChance == 0) P->wstat = dbg.u.Exception.ExceptionRecord.ExceptionCode; P->status = PS_RUN; cont = DBG_EXCEPTION_NOT_HANDLED; break; } break; default: P->status = PS_RUN; dprintf("Debug Event not processed: %d\n", dbg.dwDebugEventCode); break; } if (P->status != PS_RUN) SetEvent(P->event); while (P->status == PS_STOP) pthread_cond_wait(&P->cond, &P->mutex); pthread_mutex_unlock(&P->mutex); ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, cont); } }
static void *Ploopcreate(LPVOID args) { STARTUPINFO si; PROCESS_INFORMATION pi; DEBUG_EVENT dbg; DWORD cont; BOOL wow = 0; DWORD Options = SymGetOptions(), excep, size = 0; TCHAR pszFilename[MAX_PATH+1]; struct proc_uc *tmp = args; struct ps_prochandle *P = tmp->ps; int first_execp = 0; char *s, targs[256], *ctmp; char *const *argv = tmp->args; int len; ctmp = targs; while (*argv != NULL) { len = strlen(*argv); sprintf(ctmp, "%s ", *argv); ctmp = ctmp + len + 1; argv++; } *ctmp = '\0'; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); if(!CreateProcess( NULL, // module name targs, // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE DEBUG_ONLY_THIS_PROCESS, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi ) // Pointer to PROCESS_INFORMATION structure ) { pthread_mutex_lock(&P->mutex); P->status = PS_STOP; P->flags = CREATE_FAILED; pthread_cond_signal(&P->cond); pthread_mutex_unlock(&P->mutex); return NULL; } P->pid = pi.dwProcessId; P->tid = pi.dwThreadId; P->wstat = 0; P->exitcode = 0; P->event = CreateEvent(NULL,FALSE,FALSE,NULL); P->dll_load_order = 1; #if __amd64__ /* There seems to be a bug in 64 bit version of dbghelp.dll * when SYMOPT_DEFERRED_LOADS is set, * dtrace -n "pid$target:kernel32::entry, pid$target:KernelBase::entry" -c test.exe, * when SymEnumSymbols (Psymbol_iter_by_addr) is called on this two dll, * the second call (KernelBase) will enumerate the * symbols from the previous enumurated (kernel32) dll (from the first call). * This behaviour is not present in 32 bit. */ Options &= ~SYMOPT_DEFERRED_LOADS; #endif SymSetOptions(Options|SYMOPT_INCLUDE_32BIT_MODULES|SYMOPT_DEBUG); while (1) { if (WaitForDebugEvent(&dbg, INFINITE) == 0) { return NULL; } cont = DBG_CONTINUE; pthread_mutex_lock(&P->mutex); switch (dbg.dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: P->phandle = dbg.u.CreateProcessInfo.hProcess; P->thandle = dbg.u.CreateProcessInfo.hThread; if ((SymInitialize(P->phandle, 0, FALSE) == FALSE)) { dprintf("SymInitialize failed: %d\n", GetLastError()); break; } s = GetFileNameFromHandle(dbg.u.CreateProcessInfo.hFile, pszFilename); addmodule(P, dbg.u.CreateProcessInfo.hFile, s, dbg.u.CreateProcessInfo.lpBaseOfImage, PE_TYPE_EXE, P->dll_load_order); size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL); if (size == INVALID_FILE_SIZE) { size = 0; } if (SymLoadModuleEx(P->phandle, dbg.u.CreateProcessInfo.hFile, s, NULL, (ULONG_PTR) dbg.u.CreateProcessInfo.lpBaseOfImage, size, NULL, 0) == 0) { dprintf("SymLoadModule64 failed for %s:%d\n", s, GetLastError()); break; } #if __amd64__ if (Is32bitProcess(P->phandle)) { P->model = PR_MODEL_ILP32; wow = 1; } else P->model = PR_MODEL_ILP64; #else P->model = PR_MODEL_ILP32; #endif P->status = PS_STOP; P->msg.type = 0; CloseHandle(dbg.u.CreateProcessInfo.hFile); pthread_cond_signal(&P->cond); break; case CREATE_THREAD_DEBUG_EVENT: P->status = PS_RUN; P->msg.type = 0; break; case LOAD_DLL_DEBUG_EVENT: s = GetFileNameFromHandle(dbg.u.LoadDll.hFile, pszFilename); if (first_execp == 2) { P->dll_load_order++; } addmodule(P, dbg.u.LoadDll.hFile, s, dbg.u.LoadDll.lpBaseOfDll, PE_TYPE_DLL, P->dll_load_order); size = GetFileSize(dbg.u.LoadDll.hFile, NULL); if (size == INVALID_FILE_SIZE) { size = 0; } #if __amd64__ /* Not tracing 64 bit dlls for 32 bit process */ if (P->model == PR_MODEL_ILP32 && is64bitmodule(dbg.u.LoadDll.lpBaseOfDll, s)) { CloseHandle(dbg.u.LoadDll.hFile ); break; } #endif if (SymLoadModuleEx(P->phandle, dbg.u.LoadDll.hFile, s, NULL, (ULONG_PTR) dbg.u.LoadDll.lpBaseOfDll, size, NULL, 0) == FALSE) { dprintf("SymLoadModule64 dailed for %s:%d\n", s, GetLastError()); break; } CloseHandle(dbg.u.LoadDll.hFile ); P->status = PS_STOP; P->msg.type = RD_DLACTIVITY; break; case UNLOAD_DLL_DEBUG_EVENT: if (SymUnloadModule64(P->phandle, (ULONG_PTR) dbg.u.UnloadDll.lpBaseOfDll) == FALSE) { dprintf("SymUnloadModule64 failed-Imagebase %p:%d\n", dbg.u.UnloadDll.lpBaseOfDll, GetLastError()); break; } delmodule(P, (ULONG64) dbg.u.UnloadDll.lpBaseOfDll); P->status = PS_RUN; P->msg.type = RD_DLACTIVITY; break; case EXIT_PROCESS_DEBUG_EVENT: P->exitcode = dbg.u.ExitProcess.dwExitCode; P->status = PS_UNDEAD; P->msg.type = RD_NONE; break; case EXIT_THREAD_DEBUG_EVENT: P->status = PS_RUN; P->msg.type = 0; break; case EXCEPTION_DEBUG_EVENT: switch(excep = dbg.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_BREAKPOINT: case 0x4000001F: /* WOW64 exception breakpoint */ /* NOTE: Dtrace sets a BP at main (entry point of the process), which is implemented * with Psetbkpt, Pdelbkpt & Pexecbkpt. But I have implemnted it here. */ if ((excep == EXCEPTION_BREAKPOINT && first_execp == 0 && wow == 0) || (excep == 0x4000001F && first_execp == 0 && wow == 1) ) { SYMBOL_INFO *Symbol; GElf_Sym sym; ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; Symbol = (SYMBOL_INFO *) buffer; Symbol->SizeOfStruct= sizeof(SYMBOL_INFO ); Symbol->MaxNameLen = MAX_SYM_NAME; if (Pxlookup_by_name(P, LM_ID_BASE, "a.out", "main", &sym, NULL) != 0 && Pxlookup_by_name(P, LM_ID_BASE, "a.out", "WinMain", &sym, NULL) != 0) { dprintf("failed to find entry point (main):%d\n", GetLastError()); break; } if (setbkpt(P, (uintptr_t) sym.st_value) != 0) { dprintf("failed to set breakpoint for %s at address %p\n", Symbol->Name, Symbol->Address); break; } first_execp = 1; P->status = PS_RUN; P->msg.type = 0; break; } if (dbg.u.Exception.ExceptionRecord.ExceptionAddress != (PVOID) P->addr) { dprintf("expecting execption at %p:but recived from %p\n", P->addr, dbg.u.Exception.ExceptionRecord.ExceptionAddress); P->status = PS_RUN; cont = DBG_EXCEPTION_NOT_HANDLED; break; } if (delbkpt(P, P->addr) != 0) { dprintf("failed to delete brk point at %p:(main)\n", P->addr); break; } if (adjbkpt(P, wow) != 0) { dprintf("failed to normalize brk point (main)\n"); break; } first_execp = 2; P->status = PS_STOP; P->msg.type = RD_MAININIT; break;/* if (first_execp == 0) { P->status = PS_STOP; P->msg.type = RD_MAININIT; first_execp = 2; } else { P->status = PS_RUN; cont = DBG_EXCEPTION_NOT_HANDLED; } break;*/ default: if (dbg.u.Exception.dwFirstChance == 0) P->wstat = dbg.u.Exception.ExceptionRecord.ExceptionCode; P->status = PS_RUN; cont = DBG_EXCEPTION_NOT_HANDLED; break; } break; default: P->status = PS_RUN; dprintf("Debug Event not processed: %d\n", dbg.dwDebugEventCode); break; } if (P->status != PS_RUN) SetEvent(P->event); while (P->status == PS_STOP) pthread_cond_wait(&P->cond, &P->mutex); pthread_mutex_unlock(&P->mutex); ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, cont); } }
int main(int argc, char *argv[]) { DWORD error; HANDLE process; ULONG64 module_base; int i; char* search; char buf[256]; /* Enough to hold one hex address, I trust! */ int rv = 0; /* We may add SYMOPT_UNDNAME if --demangle is specified: */ DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES; char* filename = "a.out"; /* The default if -e isn't specified */ int print_function_name = 0; /* Set to 1 if -f is specified */ for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--functions") == 0 || strcmp(argv[i], "-f") == 0) { print_function_name = 1; } else if (strcmp(argv[i], "--demangle") == 0 || strcmp(argv[i], "-C") == 0) { symopts |= SYMOPT_UNDNAME; } else if (strcmp(argv[i], "-e") == 0) { if (i + 1 >= argc) { fprintf(stderr, "FATAL ERROR: -e must be followed by a filename\n"); return 1; } filename = argv[i+1]; i++; /* to skip over filename too */ } else if (strcmp(argv[i], "--help") == 0) { usage(); exit(0); } else { usage(); exit(1); } } process = GetCurrentProcess(); if (!SymInitialize(process, NULL, FALSE)) { error = GetLastError(); fprintf(stderr, "SymInitialize returned error : %d\n", error); return 1; } search = malloc(SEARCH_CAP); if (SymGetSearchPath(process, search, SEARCH_CAP)) { if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) { fprintf(stderr, "Search path too long\n"); SymCleanup(process); return 1; } strcat(search, ";" WEBSYM); } else { error = GetLastError(); fprintf(stderr, "SymGetSearchPath returned error : %d\n", error); rv = 1; /* An error, but not a fatal one */ strcpy(search, WEBSYM); /* Use a default value */ } if (!SymSetSearchPath(process, search)) { error = GetLastError(); fprintf(stderr, "SymSetSearchPath returned error : %d\n", error); rv = 1; /* An error, but not a fatal one */ } SymSetOptions(symopts); module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0); if (!module_base) { /* SymLoadModuleEx failed */ error = GetLastError(); fprintf(stderr, "SymLoadModuleEx returned error : %d for %s\n", error, filename); SymCleanup(process); return 1; } buf[sizeof(buf)-1] = '\0'; /* Just to be safe */ while (fgets(buf, sizeof(buf)-1, stdin)) { /* GNU addr2line seems to just do a strtol and ignore any * weird characters it gets, so we will too. */ unsigned __int64 addr = _strtoui64(buf, NULL, 16); ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; IMAGEHLP_LINE64 line; DWORD dummy; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; if (print_function_name) { if (SymFromAddr(process, (DWORD64)addr, NULL, pSymbol)) { printf("%s\n", pSymbol->Name); } else { printf("??\n"); } } line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); if (SymGetLineFromAddr64(process, (DWORD64)addr, &dummy, &line)) { printf("%s:%d\n", line.FileName, (int)line.LineNumber); } else { printf("??:0\n"); } } SymUnloadModule64(process, module_base); SymCleanup(process); return rv; }
/** * Loads modules for current process. */ static void LoadProcessModules(const FString &RemoteStorage) { int32 ErrorCode = 0; HANDLE ProcessHandle = GetCurrentProcess(); // Enumerate process modules. HMODULE* ModuleHandlePointer = GetProcessModules(ProcessHandle); if (!ModuleHandlePointer) { ErrorCode = GetLastError(); return; } // Load the modules. for( int32 ModuleIndex = 0; ModuleHandlePointer[ModuleIndex]; ModuleIndex++ ) { MODULEINFO ModuleInfo = {0}; #if WINVER > 0x502 WCHAR ModuleName[FProgramCounterSymbolInfo::MAX_NAME_LENGHT] = {0}; WCHAR ImageName[FProgramCounterSymbolInfo::MAX_NAME_LENGHT] = {0}; #else ANSICHAR ModuleName[FProgramCounterSymbolInfo::MAX_NAME_LENGHT] = { 0 }; ANSICHAR ImageName[FProgramCounterSymbolInfo::MAX_NAME_LENGHT] = { 0 }; #endif #if PLATFORM_64BITS static_assert(sizeof( MODULEINFO ) == 24, "Broken alignment for 64bit Windows include."); #else static_assert(sizeof( MODULEINFO ) == 12, "Broken alignment for 32bit Windows include."); #endif FGetModuleInformation( ProcessHandle, ModuleHandlePointer[ModuleIndex], &ModuleInfo, sizeof( ModuleInfo ) ); FGetModuleFileNameEx( ProcessHandle, ModuleHandlePointer[ModuleIndex], ImageName, FProgramCounterSymbolInfo::MAX_NAME_LENGHT ); FGetModuleBaseName( ProcessHandle, ModuleHandlePointer[ModuleIndex], ModuleName, FProgramCounterSymbolInfo::MAX_NAME_LENGHT ); // Set the search path to find PDBs in the same folder as the DLL. #if WINVER > 0x502 WCHAR SearchPath[MAX_PATH] = {0}; WCHAR* FileName = NULL; const auto Result = GetFullPathNameW( ImageName, MAX_PATH, SearchPath, &FileName ); #else ANSICHAR SearchPath[MAX_PATH] = { 0 }; ANSICHAR* FileName = NULL; const auto Result = GetFullPathNameA( ImageName, MAX_PATH, SearchPath, &FileName ); #endif FString SearchPathList; if (Result != 0 && Result < MAX_PATH) { *FileName = 0; #if WINVER > 0x502 SearchPathList = SearchPath; #else SearchPathList = ANSI_TO_TCHAR(SearchPath); #endif } if (!RemoteStorage.IsEmpty()) { if (!SearchPathList.IsEmpty()) { SearchPathList.AppendChar(';'); } SearchPathList.Append(RemoteStorage); } #if WINVER > 0x502 SymSetSearchPathW(ProcessHandle, *SearchPathList); // Load module. const DWORD64 BaseAddress = SymLoadModuleExW( ProcessHandle, ModuleHandlePointer[ModuleIndex], ImageName, ModuleName, (DWORD64) ModuleInfo.lpBaseOfDll, (uint32) ModuleInfo.SizeOfImage, NULL, 0 ); if( !BaseAddress ) { ErrorCode = GetLastError(); UE_LOG(LogWindows, Warning, TEXT("SymLoadModuleExW. Error: %d"), GetLastError()); } #else SymSetSearchPath(ProcessHandle, TCHAR_TO_ANSI(*SearchPathList)); // Load module. const DWORD64 BaseAddress = SymLoadModuleEx( ProcessHandle, ModuleHandlePointer[ModuleIndex], ImageName, ModuleName, (DWORD64)ModuleInfo.lpBaseOfDll, (uint32)ModuleInfo.SizeOfImage, NULL, 0 ); if (!BaseAddress) { ErrorCode = GetLastError(); UE_LOG(LogWindows, Warning, TEXT("SymLoadModuleEx. Error: %d"), GetLastError()); } #endif } // Free the module handle pointer allocated in case the static array was insufficient. FMemory::Free(ModuleHandlePointer); }
/*********************************************************************** * SymLoadModule64 (DBGHELP.@) */ DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll) { return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll, NULL, 0); }
int main(int argc, char **argv) { BOOL bRet; DWORD dwRet; bool debug = false; char *szModule = nullptr; bool functions = false; bool demangle = false; bool pretty = false; while (1) { int opt = getopt(argc, argv, "?CDe:fHp"); switch (opt) { case 'C': demangle = true; break; case 'D': debug = true; break; case 'e': szModule = optarg; break; case 'f': functions = true; break; case 'H': usage(argv[0]); return EXIT_SUCCESS; case 'p': pretty = true; break; case '?': fprintf(stderr, "error: invalid option `%c`\n", optopt); /* pass-through */ default: usage(argv[0]); return EXIT_FAILURE; case -1: break; } if (opt == -1) { break; } } if (szModule == nullptr) { usage(argv[0]); return EXIT_FAILURE; } // Load the module HMODULE hModule = nullptr; #ifdef _WIN64 hModule = LoadLibraryExA(szModule, NULL, LOAD_LIBRARY_AS_DATAFILE); #endif if (!hModule) { hModule = LoadLibraryExA(szModule, NULL, DONT_RESOLVE_DLL_REFERENCES); } if (!hModule) { fprintf(stderr, "error: failed to load %s\n", szModule); return EXIT_FAILURE; } DWORD dwSymOptions = SymGetOptions(); dwSymOptions |= SYMOPT_LOAD_LINES; #ifndef NDEBUG dwSymOptions |= SYMOPT_DEBUG; #endif // We can get more information by calling UnDecorateSymbolName() ourselves. dwSymOptions &= ~SYMOPT_UNDNAME; SymSetOptions(dwSymOptions); HANDLE hProcess = GetCurrentProcess(); bRet = InitializeSym(hProcess, FALSE); assert(bRet); if (debug) { SymRegisterCallback64(hProcess, &callback, 0); } dwRet = SymLoadModuleEx(hProcess, NULL, szModule, NULL, (DWORD64)(UINT_PTR)hModule, 0, NULL, 0); if (!dwRet) { fprintf(stderr, "warning: failed to load module symbols\n"); } if (!GetModuleHandleA("symsrv.dll")) { fprintf(stderr, "warning: symbol server not loaded\n"); } while (optind < argc) { const char *arg = argv[optind++]; DWORD64 dwRelAddr; if (arg[0] == '0' && arg[1] == 'x') { sscanf(&arg[2], "%08" PRIX64, &dwRelAddr); } else { dwRelAddr = atol(arg); } UINT_PTR dwAddr = (UINT_PTR)hModule + dwRelAddr; if (functions) { struct { SYMBOL_INFO Symbol; CHAR Name[512]; } sym; char UnDecoratedName[512]; const char *function = "??"; ZeroMemory(&sym, sizeof sym); sym.Symbol.SizeOfStruct = sizeof sym.Symbol; sym.Symbol.MaxNameLen = sizeof sym.Symbol.Name + sizeof sym.Name; DWORD64 dwSymDisplacement = 0; bRet = SymFromAddr(hProcess, dwAddr, &dwSymDisplacement, &sym.Symbol); if (bRet) { function = sym.Symbol.Name; if (demangle) { if (UnDecorateSymbolName( sym.Symbol.Name, UnDecoratedName, sizeof UnDecoratedName, UNDNAME_COMPLETE)) { function = UnDecoratedName; } } } fputs(function, stdout); fputs(pretty ? " at " : "\n", stdout); } IMAGEHLP_LINE64 line; ZeroMemory(&line, sizeof line); line.SizeOfStruct = sizeof line; DWORD dwLineDisplacement = 0; bRet = SymGetLineFromAddr64(hProcess, dwAddr, &dwLineDisplacement, &line); if (bRet) { fprintf(stdout, "%s:%lu\n", line.FileName, line.LineNumber); } else { fputs("??:?\n", stdout); } fflush(stdout); } SymCleanup(hProcess); FreeLibrary(hModule); return 0; }
int dbg_help_client_t::init(char* path) { DWORD64 dwBaseAddr=0; int chars; char exe_path[MAX_PATH]; chars = GetModuleFileName(NULL, exe_path, MAX_PATH); if (chars == 0) { fprintf(stderr,"Could not find base path for XED executable\n"); fflush(stderr); exit(1); } //fprintf(stderr,"EXE PATH %s\n", exe_path); char* dir = find_base_path(exe_path); //fprintf(stderr,"DIR %s\n", dir); char* dbghelp = append3(dir,"\\","dbghelp.dll"); //fprintf(stderr,"DBGHLP %s\n", dbghelp); if (_access_s(dbghelp,4) != 0) { //fprintf(stderr, // "WARNING: Could not find dbghelp.dll in xed.exe directory\n"); //fflush(stderr); return 0; } //fprintf(stderr,"FOUND DBGHELP\n"); if (validate_version(dbghelp)) { fprintf(stderr, "WARNING: dbghelp.dll version is too old\n"); fflush(stderr); return 0; } //FIXME: Add a version check for the dll ( ImagehlpApiVersion is NOT //the right thing) SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); hProcess = GetCurrentProcess(); if (SymInitialize(hProcess, NULL, FALSE)) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymInitialize returned error : %d 0x%x\n", error, error); fflush(stderr); return 0; } actual_base = SymLoadModuleEx(hProcess, NULL, path, NULL, dwBaseAddr, 0, NULL, 0); if (actual_base) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymLoadModuleEx returned error : %d 0x%x\n", error, error); fflush(stderr); return 0; } if (SymEnumerateModules64(hProcess, (PSYM_ENUMMODULES_CALLBACK64)enum_modules, this)) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymEnumerateModules64 returned error : %d 0x%x\n", error, error); fflush(stderr); return 0; } if (SymEnumSymbols(hProcess, actual_base, 0, enum_sym, this)) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymEnumSymbols failed: %d 0x%x\n", error, error); fflush(stderr); return 0; } make_symbol_vector(&sym_tab); initialized = true; return 1; }
int main(int argc, char *argv[]) { DWORD error; HANDLE process; ULONG64 module_base; SYM_CONTEXT ctx; int i; char* search; char* filename = NULL; int rv = 0; /* We may add SYMOPT_UNDNAME if --demangle is specified: */ DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--demangle") == 0 || strcmp(argv[i], "-C") == 0) { symopts |= SYMOPT_UNDNAME; } else if (strcmp(argv[i], "--help") == 0) { usage(); exit(0); } else { break; } } if (i != argc - 1) { usage(); exit(1); } filename = argv[i]; process = GetCurrentProcess(); if (!SymInitialize(process, NULL, FALSE)) { error = GetLastError(); fprintf(stderr, "SymInitialize returned error : %d\n", error); return 1; } search = malloc(SEARCH_CAP); if (SymGetSearchPath(process, search, SEARCH_CAP)) { if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) { fprintf(stderr, "Search path too long\n"); SymCleanup(process); return 1; } strcat(search, ";" WEBSYM); } else { error = GetLastError(); fprintf(stderr, "SymGetSearchPath returned error : %d\n", error); rv = 1; /* An error, but not a fatal one */ strcpy(search, WEBSYM); /* Use a default value */ } if (!SymSetSearchPath(process, search)) { error = GetLastError(); fprintf(stderr, "SymSetSearchPath returned error : %d\n", error); rv = 1; /* An error, but not a fatal one */ } SymSetOptions(symopts); module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0); if (!module_base) { /* SymLoadModuleEx failed */ error = GetLastError(); fprintf(stderr, "SymLoadModuleEx returned error : %d for %s\n", error, filename); SymCleanup(process); return 1; } ShowSymbolInfo(process, module_base); memset(&ctx, 0, sizeof(ctx)); ctx.module_base = module_base; if (!SymEnumSymbols(process, module_base, NULL, EnumSymProc, &ctx)) { error = GetLastError(); fprintf(stderr, "SymEnumSymbols returned error: %d\n", error); rv = 1; } else { DWORD j; qsort(ctx.syms, ctx.syms_len, sizeof(ctx.syms[0]), sym_cmp); for (j = 0; j < ctx.syms_len; j++) { printf("%016I64x X %s\n", ctx.syms[j].addr, ctx.syms[j].name); } /* In a perfect world, maybe we'd clean up ctx's memory? */ } SymUnloadModule64(process, module_base); SymCleanup(process); return rv; }