Beispiel #1
0
TEST(RecorderTest, CallStackRecorderTest) {
	TRACER_TRACE(&C::Foo) foo;
	auto fc = tracer::RecordCallStack(foo);

	RunFoo();
	for (auto itr : fc.GetCallStack(0).Entries())
		;//std::cout << itr.File() << " " << itr.Line() << " " << itr.FuncName() << std::endl;
	EXPECT_EQ(true, fc.GetCallStack(0).IsCalledBy("RunFoo"));
	
	void(*f)();
	f = [] () { RunFoo(); };
	f();
	EXPECT_EQ(true, fc.GetCallStack(1).IsCalledBy(f));
}
Beispiel #2
0
// トラッキングの初期化
void InitTracking()
{
    UINT i;
    CALLSTACK_DATA *s;

    // ハッシュリスト初期化
    hashlist = (TRACKING_LIST **)OSMemoryAlloc(sizeof(TRACKING_LIST *) * TRACKING_NUM_ARRAY);

    for (i = 0; i < TRACKING_NUM_ARRAY; i++)
    {
        hashlist[i] = NULL;
    }

    obj_id = 0;

    // ロック作成
    obj_lock = OSNewLock();
    obj_id_lock = OSNewLock();
    cs_lock = OSNewLock();

    s = GetCallStack();
    if (s == NULL)
    {
        do_not_get_callstack = true;
    }
    else
    {
        do_not_get_callstack = false;
        FreeCallStack(s);
    }
}
Beispiel #3
0
void CGameAISystem::Error(const char* functionName) const
{
	string logMessage;
	logMessage.Format(
		"[%s]: An entity entered or left a module while the modules were being updated.\n"
		"This is bad and we'd appreciate it if you'd help us by informing Jonas, Mario and Marcio.\n",
		functionName);

	gEnv->pLog->LogError("-------------------------- Error in GameAISystem ---------------------------------");
	gEnv->pLog->LogError(logMessage.c_str());

#if defined(GAME_AI_ASSERTS_ENABLED)

	if (ICVar* sys_no_crash_dialog = gEnv->pConsole->GetCVar("sys_no_crash_dialog"))
	{
		const bool dialogsAreAllowed = sys_no_crash_dialog->GetIVal() == 0;
		if (dialogsAreAllowed)
		{
			InformContentCreatorOfError(logMessage);
		}
	}

#else

	gEnv->pLog->LogError("Generating callstack... please wait...");
	string callstack;
	GetCallStack(callstack);
	gEnv->pLog->LogError("Callstack:\n%s", callstack.c_str());
	//CrashOnPurpose();

#endif

}
Beispiel #4
0
int StackTrace::GetCallStack(Address* callStack, int maxDepth, int entriesToSkip)
{
    PCONTEXT pContext(0);
    HMODULE hKernel32Dll = GetModuleHandle("kernel32.dll");
    void (WINAPI *pRtlCaptureContext)(PCONTEXT);
    *(void**)&pRtlCaptureContext = GetProcAddress(hKernel32Dll, "RtlCaptureContext");
    CONTEXT context;
    if (pRtlCaptureContext)
    {
        memset(&context, 0, sizeof(context));
        context.ContextFlags = CONTEXT_FULL;
        pRtlCaptureContext(&context);
        pContext = &context;
    }
    // +1 -> skip over "us"
    return GetCallStack(pContext, callStack,  maxDepth, entriesToSkip + 1);
}
Beispiel #5
0
// 新しいオブジェクトを追跡リストに入れる
void TrackNewObj(UINT64 addr, char *name, UINT size)
{
    TRACKING_OBJECT *o;
    UINT new_id;
    // 引数チェック
    if (addr == 0 || name == NULL)
    {
        return;
    }

    if (IsMemCheck() == false)
    {
        // リリースモードでは追跡しない
        return;
    }

    if (disable_tracking)
    {
        return;
    }

    // 新しい ID の生成
    OSLock(obj_id_lock);
    {
        new_id = ++obj_id;
    }
    OSUnlock(obj_id_lock);

    o = OSMemoryAlloc(sizeof(TRACKING_OBJECT));
    o->Id = new_id;
    o->Address = addr;
    o->Name = name;
    o->Size = size;
    o->CreatedDate = LocalTime64();
    o->CallStack = WalkDownCallStack(GetCallStack(), 2);

    o->FileName[0] = 0;
    o->LineNumber = 0;

    LockTrackingList();
    {
        InsertTrackingList(o);
    }
    UnlockTrackingList();
}
Beispiel #6
0
// Put a new object into the tracking list
void TrackNewObj(UINT64 addr, char *name, UINT size)
{
	TRACKING_OBJECT *o;
	UINT new_id;
	// Validate arguments
	if (addr == 0 || name == NULL)
	{
		return;
	}

	if (IsMemCheck() == false)
	{
		// Don't track in the release mode
		return;
	}

	if (disable_tracking)
	{
		return;
	}

	// Generate a new ID
	OSLock(obj_id_lock);
	{
		new_id = ++obj_id;
	}
	OSUnlock(obj_id_lock);

	o = OSMemoryAlloc(sizeof(TRACKING_OBJECT));
	o->Id = new_id;
	o->Address = addr;
	o->Name = name;
	o->Size = size;
	o->CreatedDate = LocalTime64();
	o->CallStack = WalkDownCallStack(GetCallStack(), 2);

	o->FileName[0] = 0;
	o->LineNumber = 0;

	LockTrackingList();
	{
		InsertTrackingList(o);
	}
	UnlockTrackingList();
}
Beispiel #7
0
void CGameAISystem::InformContentCreatorOfError(string logMessage) const
{
#if defined(GAME_AI_ASSERTS_ENABLED)

	if (g_gameAISystemAssertsAllowed)
	{
		CursorShowerWithStack cursorShowerWithStack;
		cursorShowerWithStack.StoreCurrentAndShow();

		string dialogMessage = logMessage +
			"\n"
			"Do you want to help?\n"
			"Yes\t- Help out and generate callstack (takes around 30 seconds)\n"
			"No\t- Not this time\n"
			"Cancel\t- Ignore similar errors for the rest of this session";

		const char* dialogCaption = "Error in GameAISystem";
		int messageBoxResult = CryMessageBox(dialogMessage.c_str(), dialogCaption, MB_ICONERROR | MB_YESNOCANCEL);

		switch (messageBoxResult)
		{
		case IDYES:
			{
				string callstack;
				GetCallStack(callstack);

				gEnv->pLog->LogError("Callstack:\n%s", callstack.c_str());

				messageBoxResult = CryMessageBox(
					"The callstack has been generated.\n"
					"\n"
					"Do you want me to prepare an email for you, describing the issue?",
					dialogCaption, MB_ICONINFORMATION | MB_YESNO);

				if (messageBoxResult == IDYES)
				{
					string_replace(callstack, "\n", "%%0A");

					string command = string().Format(
						"mailto:[email protected];[email protected];[email protected]"
						"?subject=Error in GameAISystem"
						"&body="
						"[Auto-generated e-mail]%%0A"
						"%%0A"
						"Hi,%%0A"
						"%%0A"
						"This is an auto-generated email.%%0A"
						"An error occurred in the GameAISystem: An entity entered or left a module while the modules were being updated.%%0A"
						"%%0A"
						"Here is the callstack:%%0A"
						+ callstack);

					ShellExecute(0, "open", command.c_str(), "", "", SW_NORMAL);
					CryMessageBox("Thanks! The email is being created for you.\nHave a nice day! :)", dialogCaption, MB_ICONINFORMATION | MB_OK);
				}
				else
				{
					CryMessageBox("Ok! The callstack has been written to the log file anyway.\nHave a nice day! :)", dialogCaption, MB_ICONINFORMATION | MB_OK);
				}

				break;
			}

		case IDNO:
			break;

		case IDCANCEL:
			g_gameAISystemAssertsAllowed = false;
			break;
		}

		cursorShowerWithStack.RevertToPrevious();
	}

#endif
}
Beispiel #8
0
static BOOL saveMiniDump(EXCEPTION_POINTERS* pExceptionInfos)
{
	BOOL result = FALSE;
#ifdef _M_IX86
	if (pExceptionInfos->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)  
	{  
		static char TempStack[1024 * 128];
		__asm mov eax,offset TempStack[1024 * 128];
		__asm mov esp,eax;
	}
#endif

	CrashInfo crashInfo = GetCrashInfo(pExceptionInfos->ExceptionRecord);
	vector<CallStackInfo> arrCallStackInfo = GetCallStack(pExceptionInfos->ContextRecord);
	CString dumpPath = FileMgr::GetAppPath() + _T("\\MyEcho.dmp");

	Json::Value jDump, jCrash, jCallStack;
	CHAR szObject[MAX_PATH];
	::GetModuleFileNameA(NULL, szObject, MAX_PATH);
	jCrash["Object"] = szObject;
	jCrash["ErrorCode"] = crashInfo.ErrorCode;
	jCrash["Address"] = crashInfo.Address;
	jCrash["Flags"] = crashInfo.Flags;

	for (vector<CallStackInfo>::iterator i = arrCallStackInfo.begin(); i != arrCallStackInfo.end(); ++i)
	{
		CallStackInfo callstackinfo = (*i);
		jCallStack[callstackinfo.MethodName] = std::string("[") + callstackinfo.ModuleName + std::string("] [File:") + callstackinfo.FileName + std::string(" @Line ") + callstackinfo.LineNumber + std::string("]");
		//cout << callstackinfo.MethodName << "() : [" << callstackinfo.ModuleName << "] (File: " << callstackinfo.FileName << " @Line " << callstackinfo.LineNumber << ")" << endl;  
	}

	jDump["crash"] = jCrash;
	jDump["callstack"] = jCallStack;

	// 程序崩溃时,将写入程序目录下的MyDump.dmp文件
	HANDLE hFile = ::CreateFile(dumpPath, GENERIC_WRITE,
		FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL, NULL );
	if (hFile != INVALID_HANDLE_VALUE)
	{
		/*
		MINIDUMP_EXCEPTION_INFORMATION exptInfo;
		exptInfo.ThreadId = ::GetCurrentThreadId();
		exptInfo.ExceptionPointers = pExceptionInfos;

		result = ::MiniDumpWriteDump(::GetCurrentProcess(),
			::GetCurrentProcessId(),
			hFile, MiniDumpNormal,
			&exptInfo, NULL, NULL);
		if (!result)
		{
			TCHAR temp[1024] = {0};
			_stprintf(temp, _T("GetLastError() 2 = %d"), GetLastError());
			OutputDebugString(temp);
		} */

		DWORD dwWritten = 0;
		WriteFile(hFile, jDump.toStyledString().c_str(),
			jDump.toStyledString().length(), &dwWritten, NULL);
		::CloseHandle(hFile);
	}
	else
	{
		TCHAR temp[1024] = {0};
		_stprintf(temp, _T("GetLastError() 1 = %d"), GetLastError());
		OutputDebugString(temp);
	}

	return result;
}
Beispiel #9
0
LONG WINAPI UnhandledExceptionHandler(_EXCEPTION_POINTERS *ExceptionInfo){
	List<LoadedModule*> LoadedModules;
	EnumerateLoadedModules(GetCurrentProcess(), (PENUMLOADED_MODULES_CALLBACK)AddLoadedModule, &LoadedModules);

	StringList HeaderList;
	
	if(ExceptionInfo->ContextRecord->ContextFlags & CONTEXT_INTEGER){
		PCONTEXT reg = ExceptionInfo->ContextRecord;
		HeaderList.push_back(String("Register-EAX: %1").arg(reg->Eax, 16, true, 8));
		HeaderList.push_back(String("Register-ECX: %1").arg(reg->Ecx, 16, true, 8));
		HeaderList.push_back(String("Register-EDX: %1").arg(reg->Edx, 16, true, 8));
		HeaderList.push_back(String("Register-EBX: %1").arg(reg->Ebx, 16, true, 8));
		HeaderList.push_back(String("Register-EDI: %1").arg(reg->Edi, 16, true, 8));
		HeaderList.push_back(String("Register-ESI: %1").arg(reg->Esi, 16, true, 8));
	}

	if(ExceptionInfo->ContextRecord->ContextFlags & CONTEXT_CONTROL){
		PCONTEXT reg = ExceptionInfo->ContextRecord;
		HeaderList.push_back(String("Register-EBP: %1").arg(reg->Edi, 16, true, 8));
		HeaderList.push_back(String("Register-ESP: %1").arg(reg->Esi, 16, true, 8));
	}

	HeaderList.push_back(String("Exception-Address: %1").arg((unsigned int)ExceptionInfo->ExceptionRecord->ExceptionAddress, 16, true, 8));
	HeaderList.push_back(String("Exception-Flags: %1").arg((unsigned int)ExceptionInfo->ExceptionRecord->ExceptionFlags, 16, true, 8));
	HeaderList.push_back(String("Exception-Code: %1").arg((unsigned int)ExceptionInfo->ExceptionRecord->ExceptionCode, 16, true, 8));
	
	CGameOBJ* self = CObjMGR::GetSelf();
	const char* name = (self)?self->GetName():"No Character";
	HeaderList.push_back(String("Character: %1").arg(name));
	String module = "Unknown";

	unsigned int codeAddress = (unsigned int)((char*)ExceptionInfo->ExceptionRecord->ExceptionAddress);
	module = GetModuleName(codeAddress, &LoadedModules);
	HeaderList.push_back(String("Module: %1").arg(module));

	unsigned char* codePtr = (unsigned char*)ExceptionInfo->ExceptionRecord->ExceptionAddress;
	//if(IsBadReadPtr(codePtr - 20, 40) || !IsBadCodePtr(FARPROC(codePtr))){
	String code = String("Code-Data: Version: %1 ").arg(gVersion);
	if(CTERRAIN::Instance()) {
		code += String("Zone: %1 ").arg(CTERRAIN::Instance()->m_nZoneNO);
	}
	if(gRecvPacket) {
		code += String("RecvPacket: %1").arg(gRecvPacket->Command(), 16);
	}
	/*}else{
		for(int i = -20; i < 20; ++i)
			code += String::Create("%02X", codePtr[i]);
	}*/

	HeaderList.push_back(code);

    OSVERSIONINFO osvi;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx(&osvi);
	HeaderList.push_back(String("Windows: %1.%2").arg((unsigned int)osvi.dwMajorVersion).arg((unsigned int)osvi.dwMinorVersion));

	GetCallStack(ExceptionInfo, &LoadedModules, HeaderList);

	unsigned int bufLen = 100;
	for(StringList::Iterator itr = HeaderList.begin(); itr != HeaderList.end(); ++itr)
		bufLen += strlen(*itr) + 3;

	char* theHeaders = new char[bufLen];
	theHeaders[0] = 0;
	for(StringList::Iterator itr = HeaderList.begin(); itr != HeaderList.end(); ++itr){
		strcat_s(theHeaders, bufLen, *itr);
		strcat_s(theHeaders, bufLen, ";\r\n");
	}

	if(MessageBoxA(NULL, "Would you like to submit this error to the titanROSE team?", "An error has occured.", MB_ICONERROR | MB_YESNO) == IDYES){
		HINTERNET theInternet = InternetOpenA("titanROSE.Client", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
		HINTERNET theConnection = InternetConnectA(theInternet, "crash.titanrose.com", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL);
		HINTERNET theRequest = HttpOpenRequestA(theConnection, "GET", NULL, NULL, "trose.exe", NULL, INTERNET_FLAG_PRAGMA_NOCACHE |INTERNET_FLAG_RELOAD, NULL);
		HttpAddRequestHeadersA(theRequest, theHeaders, -1, HTTP_ADDREQ_FLAG_ADD);
		BOOL theResult = HttpSendRequestA(theRequest, NULL, 0, NULL, 0);
		if(theResult == TRUE){
			MessageBoxA(NULL, "Your error report was successfully uploaded, thank you.", "Error Report Submitted", MB_OK | MB_ICONASTERISK);
		}else{
			strcat_s(theHeaders, bufLen, "\r\nThere was an error submitting your error report, please post this message box on the forums.");
			MessageBoxA(NULL, theHeaders, "Error submitting Error Report", MB_OK);
		}
	}

	LoadedModules.delete_values();
	delete [] theHeaders;

	return EXCEPTION_EXECUTE_HANDLER;
}