Beispiel #1
0
/** Print stack traces for relevant threads. */
void HangHandler(bool simhang)
{
	PRINT("Hang detection triggered %sfor Spring %s.", simhang ? "(in sim thread) " : "", SpringVersion::GetFull().c_str());
#ifdef USE_GML
	PRINT("MT with %d threads.", gmlThreadCount);
#endif

	initImageHlpDll();

	// Record list of loaded DLLs.
	PRINT("DLL information:");
	SymEnumerateModules(GetCurrentProcess(), EnumModules, NULL);


	if (drawthread != INVALID_HANDLE_VALUE) {
		// Record stacktrace.
		PRINT("Stacktrace:");
		Stacktrace(NULL, drawthread);
	}

#if defined(USE_GML) && GML_ENABLE_SIM
	if (gmlMultiThreadSim && simthread != INVALID_HANDLE_VALUE) {
		PRINT("Stacktrace (sim):");
		Stacktrace(NULL, simthread);
	}
#endif

	// Unintialize IMAGEHLP.DLL
	SymCleanup(GetCurrentProcess());

	logOutput.Flush();
}
void PrepareStacktrace() {
	InitImageHlpDll();

	// Record list of loaded DLLs.
	PRINT("DLL information:");
	SymEnumerateModules(GetCurrentProcess(), EnumModules, NULL);
}
Beispiel #3
0
/** Called by windows if an exception happens. */
static LONG CALLBACK ExceptionHandler(LPEXCEPTION_POINTERS e)
{
	// Prologue.
	logOutput.SetSubscribersEnabled(false);
	PRINT("Spring %s has crashed.", SpringVersion::GetFull().c_str());
#ifdef USE_GML
	PRINT("MT with %d threads.", gmlThreadCount);
#endif
	initImageHlpDll();

	// Record exception info.
	PRINT("Exception: %s (0x%08lx)", ExceptionName(e->ExceptionRecord->ExceptionCode), e->ExceptionRecord->ExceptionCode);
	PRINT("Exception Address: 0x%08lx", (unsigned long int) (PVOID) e->ExceptionRecord->ExceptionAddress);

	// Record list of loaded DLLs.
	PRINT("DLL information:");
	SymEnumerateModules(GetCurrentProcess(), EnumModules, NULL);

	// Record stacktrace.
	PRINT("Stacktrace:");
	Stacktrace(e);

	// Unintialize IMAGEHLP.DLL
	SymCleanup(GetCurrentProcess());

	// Cleanup.
	SDL_Quit();
	logOutput.End();  // Stop writing to log.
	// FIXME: update closing of demo to new netcode

	// Inform user.
	char dir[MAX_PATH], msg[MAX_PATH+200];
	GetCurrentDirectory(sizeof(dir) - 1, dir);
	SNPRINTF(msg, sizeof(msg),
		"Spring has crashed.\n\n"
		"A stacktrace has been written to:\n"
		"%s\\infolog.txt", dir);
	MessageBox(NULL, msg, "Spring: Unhandled exception", 0);

	// this seems to silently close the application
	return EXCEPTION_EXECUTE_HANDLER;

	// this triggers the microsoft "application has crashed" error dialog
	//return EXCEPTION_CONTINUE_SEARCH;

	// in practice, 100% CPU usage but no continuation of execution
	// (tested segmentation fault and division by zero)
	//return EXCEPTION_CONTINUE_EXECUTION;
}
Beispiel #4
0
BOOL dbg_get_debuggee_info(HANDLE hProcess, IMAGEHLP_MODULE* imh_mod)
{
    struct mod_loader_info  mli;
    DWORD                   opt;

    /* this will resynchronize builtin dbghelp's internal ELF module list */
    SymLoadModule(hProcess, 0, 0, 0, 0, 0);
    mli.handle  = hProcess;
    mli.imh_mod = imh_mod;
    imh_mod->SizeOfStruct = sizeof(*imh_mod);
    imh_mod->BaseOfImage = 0;
    /* this is a wine specific options to return also ELF modules in the
     * enumeration
     */
    SymSetOptions((opt = SymGetOptions()) | 0x40000000);
    SymEnumerateModules(hProcess, mod_loader_cb, (void*)&mli);
    SymSetOptions(opt);

    return imh_mod->BaseOfImage != 0;
}
Beispiel #5
0
/*
================
Sys_PrintStackTrace

Occurs when we encounter a fatal error.
Prints the stack trace as well as some other data.
================
*/
LONG WINAPI Sys_PrintStackTrace(EXCEPTION_POINTERS* exception)
{
	STACKFRAME frame = {};
#ifdef WIN32
	DWORD machine = IMAGE_FILE_MACHINE_I386;
#else
	DWORD machine = IMAGE_FILE_MACHINE_AMD64;
#endif
	HANDLE process = GetCurrentProcess();
	HANDLE thread = GetCurrentThread();
	int i = 0;

	frame.AddrPC.Mode = AddrModeFlat;
	frame.AddrFrame.Mode = AddrModeFlat;
	frame.AddrStack.Mode = AddrModeFlat;

#ifdef WIN32
	frame.AddrPC.Offset = exception->ContextRecord->Eip;
	frame.AddrFrame.Offset = exception->ContextRecord->Ebp;
	frame.AddrStack.Offset = exception->ContextRecord->Esp;
#else
	frame.AddrPC.Offset = exception->ContextRecord->Rip;
	frame.AddrFrame.Offset = exception->ContextRecord->Rbp;
	frame.AddrStack.Offset = exception->ContextRecord->Rsp;
#endif

	Com_Printf("------------------------\n");
	Com_Printf("Enumerate Modules:\n");
	Com_Printf("------------------------\n");
	SymRefreshModuleList(process);
	SymEnumerateModules(process, Sys_PrintModule, nullptr);

	Com_Printf("\n\n");
	Com_Printf("------------------------\n");
	Com_Printf("Stack trace : \n");
	Com_Printf("------------------------\n");
	while (StackWalk(machine, process, thread, &frame, exception->ContextRecord, nullptr, SymFunctionTableAccess, SymGetModuleBase, nullptr))
	{
		DWORD moduleBase = SymGetModuleBase(process, frame.AddrPC.Offset);
		char moduleName[MAX_PATH];
		char funcName[MAX_PATH];
		char fileName[MAX_PATH];
		DWORD address = frame.AddrPC.Offset;
		char symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 255];
		PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
		IMAGEHLP_LINE line;
		DWORD offset = 0;

		line.SizeOfStruct = sizeof(IMAGEHLP_LINE);
		symbol->SizeOfStruct = (sizeof IMAGEHLP_SYMBOL) + 255;
		symbol->MaxNameLength = 254;

		if (moduleBase && GetModuleFileNameA((HINSTANCE)moduleBase, moduleName, MAX_PATH))
		{
			Sys_CleanModuleName(moduleName, MAX_PATH);
		}
		else
		{
			moduleName[0] = '\0';
		}

		if (SymGetSymFromAddr(process, frame.AddrPC.Offset, &offset, symbol))
		{
			Q_strncpyz(funcName, symbol->Name, MAX_PATH);
		}
		else
		{
			funcName[0] = '\0';
		}

		if (SymGetLineFromAddr(process, frame.AddrPC.Offset, &offset, &line))
		{
			Q_strncpyz(fileName, line.FileName, MAX_PATH);
			Sys_CleanModuleName(fileName, MAX_PATH);
			Com_sprintf(fileName, MAX_PATH, "%s:%i", fileName, line.LineNumber);
		}
		else
		{
			fileName[0] = '\0';
		}

		Com_Printf("%03i %20s 0x%08X | %s (%s)\n", i, moduleName, address, funcName, fileName);
		i++;
	}

	Sys_Error("Unhanded Exception: 0x%08X", exception->ExceptionRecord->ExceptionCode);
#ifdef _DEBUG
	return EXCEPTION_CONTINUE_SEARCH;
#else
	return EXCEPTION_EXECUTE_HANDLER;
#endif
	
}
Beispiel #6
0
/** Print out a stacktrace. */
static void Stacktrace(LPEXCEPTION_POINTERS e, HANDLE hThread = INVALID_HANDLE_VALUE)
{
	PIMAGEHLP_SYMBOL pSym;
	STACKFRAME sf;
	HANDLE process, thread;
	DWORD dwModBase, Disp, dwModAddrToPrint;
	BOOL more = FALSE;
	int count = 0;
	char modname[MAX_PATH];

	process = GetCurrentProcess();

	if (!InitImageHlpDll())
		return;

	// List all loaded DLLs.
	PRINT("DLL information:");
	SymEnumerateModules(process, EnumModules, NULL);

	bool suspended = false;
	CONTEXT c;
	if (e) {
		c = *e->ContextRecord;
		thread = GetCurrentThread();
	} else {
		SuspendThread(hThread);
		suspended = true;
		memset(&c, 0, sizeof(CONTEXT));
		c.ContextFlags = CONTEXT_FULL;
		// FIXME: This does not work if you want to dump the current thread's stack
		if (!GetThreadContext(hThread, &c)) {
			SymCleanup(process); // Unintialize IMAGEHLP.DLL
			ResumeThread(hThread);
			return;
		}
		thread = hThread;
	}
	ZeroMemory(&sf, sizeof(sf));
	sf.AddrPC.Offset = c.Eip;
	sf.AddrStack.Offset = c.Esp;
	sf.AddrFrame.Offset = c.Ebp;
	sf.AddrPC.Mode = AddrModeFlat;
	sf.AddrStack.Mode = AddrModeFlat;
	sf.AddrFrame.Mode = AddrModeFlat;

	// use globalalloc to reduce risk for allocator related deadlock
	pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc(GMEM_FIXED, 16384);
	char* printstrings = (char*)GlobalAlloc(GMEM_FIXED, 0);

	PRINT("Stacktrace:");
	bool containsOglDll = false;
	while (true) {
		more = StackWalk(
			IMAGE_FILE_MACHINE_I386, // TODO: fix this for 64 bit windows?
			process,
			thread,
			&sf,
			&c,
			NULL,
			SymFunctionTableAccess,
			SymGetModuleBase,
			NULL
		);
		if (!more || sf.AddrFrame.Offset == 0 || count > MAX_STACK_DEPTH) {
			break;
		}

		dwModBase = SymGetModuleBase(process, sf.AddrPC.Offset);

		if (dwModBase) {
			GetModuleFileName((HINSTANCE)dwModBase, modname, MAX_PATH);
		} else {
			strcpy(modname, "Unknown");
		}

		pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
		pSym->MaxNameLength = MAX_PATH;

		char* printstringsnew = (char*) GlobalAlloc(GMEM_FIXED, (count + 1) * BUFFER_SIZE);
		memcpy(printstringsnew, printstrings, count * BUFFER_SIZE);
		GlobalFree(printstrings);
		printstrings = printstringsnew;

		if (SymGetSymFromAddr(process, sf.AddrPC.Offset, &Disp, pSym)) {
			// This is the code path taken on VC if debugging syms are found.
			SNPRINTF(printstrings + count * BUFFER_SIZE, BUFFER_SIZE, "(%d) %s(%s+%#0lx) [0x%08lX]", count, modname, pSym->Name, Disp, sf.AddrPC.Offset);
		} else {
			// This is the code path taken on MinGW, and VC if no debugging syms are found.
			if (strstr(modname, ".exe")) {
				// for the .exe, we need the absolute address
				dwModAddrToPrint = sf.AddrPC.Offset;
			} else {
				// for DLLs, we need the module-internal/relative address
				dwModAddrToPrint = sf.AddrPC.Offset - dwModBase;
			}
			SNPRINTF(printstrings + count * BUFFER_SIZE, BUFFER_SIZE, "(%d) %s [0x%08lX]", count, modname, dwModAddrToPrint);
		}

		// OpenGL lib names (ATI): "atioglxx.dll" "atioglx2.dll"
		containsOglDll = containsOglDll || strstr(modname, "atiogl");
		// OpenGL lib names (Nvidia): "nvoglnt.dll" "nvoglv32.dll" "nvoglv64.dll" (last one is a guess)
		containsOglDll = containsOglDll || strstr(modname, "nvogl");
		// OpenGL lib names (Intel): "ig4dev32.dll" "ig4dev64.dll"
		containsOglDll = containsOglDll || strstr(modname, "ig4dev");

		++count;
	}

	// Unintialize IMAGEHLP.DLL
	SymCleanup(process);

	if (suspended) {
		ResumeThread(hThread);
	}

	if (containsOglDll) {
		PRINT("This stack trace indicates a problem with your graphic card driver. "
		      "Please try upgrading or downgrading it. "
		      "Specifically recommended is the latest driver, and one that is as old as your graphic card. "
		      "Make sure to use a driver removal utility, before installing other drivers.");
	}

	for (int i = 0; i < count; ++i) {
		PRINT("%s", printstrings + i * BUFFER_SIZE);
	}

	GlobalFree(printstrings);
	GlobalFree(pSym);
}
static void JKG_Assert_ListModules(fileHandle_t *f) {
	SymEnumerateModules(GetCurrentProcess(), (PSYM_ENUMMODULES_CALLBACK)JKG_Assert_EnumModules, (PVOID)f );
}