Ejemplo n.º 1
0
static void dbgHelpLoad(LPCWSTR name, DbgHelp* dest)
{
	HMODULE hMod = wenforce(LoadLibrary(name), L"Could not load " + std::wstring(name));
	IMPORT(StackWalk64);
	IMPORT(SymFunctionTableAccess64);
	IMPORT(SymGetModuleBase64);
	IMPORT(SymCleanup);
	IMPORT(SymEnumerateModulesW64);
	IMPORT(SymSetSearchPathW);
	IMPORT(SymInitializeW);
	IMPORT(SymSetOptions);
	IMPORT(SymGetOptions);
	IMPORT(SymGetModuleInfoW64);
	IMPORT(SymFromAddrW);
	IMPORT(SymGetLineFromAddrW64);
	IMPORT(SymRegisterCallbackW64);
	IMPORT(SymRefreshModuleList);
	IMPORT(SymLoadModuleExW);
	IMPORT(SymSetDbgPrint); // Custom Wine extension
	IMPORT(MiniDumpWriteDump);
}
Ejemplo n.º 2
0
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();
}