void symWineCallback(const char *msg) { if (g_symLog) { wchar_t tmp[2048]; MultiByteToWideChar(CP_ACP, 0, msg, -1, tmp, sizeof(tmp)); g_symLog(L"WINE: "); g_symLog(tmp); } }
void symWineCallback(const char *msg) { #ifdef _DEBUG OutputDebugStringA(msg); #endif if (!msg || !*msg) return; static bool newline = true; if (g_symLog) { if (newline) g_symLog(L"WINE: "); newline = msg[strlen(msg) - 1] == '\n'; wchar_t tmp[2048]; MultiByteToWideChar(CP_ACP, 0, msg, -1, tmp, sizeof(tmp)); g_symLog(tmp); } }
BOOL CALLBACK symCallback(HANDLE hProcess, ULONG ActionCode, ULONG64 CallbackData, ULONG64 UserContext) { switch(ActionCode) { case CBA_DEBUG_INFO: if (g_symLog) { g_symLog((const wchar_t*)CallbackData); } return TRUE; default: return FALSE; } }
void SymbolInfo::loadSymbols(HANDLE process_handle_, bool download) { process_handle = process_handle_; wxBusyCursor busy; is64BitProcess = Is64BitProcess(process_handle); DWORD options = dbgHelpMs.SymGetOptions(); #ifdef _WIN64 if(!is64BitProcess) { options |= SYMOPT_INCLUDE_32BIT_MODULES; } #endif options |= SYMOPT_LOAD_LINES | SYMOPT_DEBUG; dbgHelpMs.SymSetOptions(options); dbgHelpGcc.SymSetOptions(options); #ifdef _WIN64 dbgHelpGccWow64.SymSetOptions(options); #endif std::wstring sympath; // Add the program's own directory to the search path. // Useful if someone's copied the EXE and PDB to a different machine or location. wchar_t szExePath[MAX_PATH] = L""; DWORD pathsize = MAX_PATH; BOOL gotImageName = FALSE; #ifdef _WIN64 // GetModuleFileNameEx doesn't always work across 64->32 bit boundaries. // Use QueryFullProcessImageName if we have it. { typedef BOOL WINAPI QueryFullProcessImageNameFn(HANDLE hProcess, DWORD dwFlags, LPTSTR lpExeName, PDWORD lpdwSize); QueryFullProcessImageNameFn *fn = (QueryFullProcessImageNameFn *)GetProcAddress(GetModuleHandle(L"kernel32"),"QueryFullProcessImageNameW"); if (fn) gotImageName = fn(process_handle, 0, szExePath, &pathsize); } #endif if (!gotImageName) gotImageName = GetModuleFileNameEx(process_handle, NULL, szExePath, pathsize); if (gotImageName) { // Convert the EXE path to its containing folder and append the // resulting folder to the symbol search path. wchar_t *p = wcsrchr(szExePath, '\\'); if (p != NULL) { *p = '\0'; sympath += std::wstring(L";") + szExePath; } } prefs.AdjustSymbolPath(sympath, download); for( int n=0;n<4;n++ ) { wenforce(dbgHelpMs.SymInitializeW(process_handle, L"", FALSE), "SymInitialize"); // Hook the debug output, so we actually can provide a clue as to // what's happening. dbgHelpMs.SymRegisterCallbackW64(process_handle, symCallback, NULL); // Add our PDB search paths. wenforce(dbgHelpMs.SymSetSearchPathW(process_handle, sympath.c_str()), "SymSetSearchPathW"); // Load symbol information for all modules. // Normally SymInitialize would do this, but we instead do it ourselves afterwards // so that we can hook the debug output for it. wenforce(dbgHelpMs.SymRefreshModuleList(process_handle), "SymRefreshModuleList"); wenforce(dbgHelpMs.SymEnumerateModulesW64(process_handle, EnumModules, this), "SymEnumerateModules64"); if (!modules.empty()) break; // Sometimes the module enumeration will fail (no error code, but no modules // will be returned). If we try again a little later it seems to work. // I suspect this may be if we try and enum modules too early on, before the process // has really had a chance to 'get going'. // Perhaps a better solution generally would be to manually load module symbols on demand, // as each sample comes in? That'd also solve the problem of modules getting loaded/unloaded // mid-profile. Yes, I'll probably do that some day. Sleep(100); dbgHelpMs.SymCleanup(process_handle); } DbgHelp *gcc = &dbgHelpGcc; #ifdef _WIN64 // We can't use the regular dbghelpw to profile 32-bit applications, // as it's got compiled-in things that assume 64-bit. So we instead have // a special Wow64 build, which is compiled as 64-bit code but using 32-bit // definitions. We load that instead. if (!is64BitProcess) gcc = &dbgHelpGccWow64; #endif // Now that we've loaded all the modules and debug info for the regular stuff, // we initialize the GCC dbghelp and let it have a go at the ones we couldn't do. wenforce(gcc->SymInitializeW(process_handle, NULL, FALSE), "SymInitialize"); gcc->SymSetDbgPrint(&symWineCallback); for (size_t n=0;n<modules.size();n++) { Module &mod = modules[n]; IMAGEHLP_MODULEW64 info; info.SizeOfStruct = sizeof(info); if (!dbgHelpMs.SymGetModuleInfoW64(process_handle, mod.base_addr, &info)) continue; // If we have a module with no symbol information from the MS dbghelp, // let the gcc one handle it instead. if (info.SymType == SymNone) { gcc->SymLoadModuleExW(process_handle, NULL, info.ImageName, info.ModuleName, info.BaseOfImage, info.ImageSize, NULL, 0); mod.dbghelp = gcc; } } if (g_symLog) g_symLog(L"\nFinished.\n"); sortModules(); }