//****************************************************************** void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, const CONTEXT* context_record, LLSD& info) //****************************************************************** // Fill Str with call stack info. // pException can be either GetExceptionInformation() or NULL. // If pException = NULL - get current call stack. { LPWSTR Module_Name = new WCHAR[MAX_PATH]; PBYTE Module_Addr = 0; LLSD params; PBYTE Esp = NULL; LLSD tmp_info; bool fake_frame = false; bool ebp_used = false; const int HEURISTIC_MAX_WALK = 20; int heuristic_walk_i = 0; int Ret_Addr_I = 0; WSTACK Stack = {0, 0}; PSTACK Ebp; if (exception_record && context_record) //fake frame for exception address { Stack.Ebp = (PSTACK)(context_record->Ebp); Stack.Ret_Addr = (PBYTE)exception_record->ExceptionAddress; Ebp = &Stack; Esp = (PBYTE) context_record->Esp; fake_frame = true; } else if(context_record) { Ebp = (PSTACK)(context_record->Ebp); Esp = (PBYTE)(context_record->Esp); } else { Ebp = (PSTACK)&exception_record - 1; //frame addr of Get_Call_Stack() Esp = (PBYTE)&exception_record; // Skip frame of Get_Call_Stack(). if (!IsBadReadPtr(Ebp, sizeof(PSTACK))) Ebp = Ebp->Ebp; //caller ebp } // Trace CALL_TRACE_MAX calls maximum - not to exceed DUMP_SIZE_MAX. // Break trace on wrong stack frame. for (Ret_Addr_I = 0; heuristic_walk_i < HEURISTIC_MAX_WALK && Ret_Addr_I < CALL_TRACE_MAX && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr)); Ret_Addr_I++) { // If module with Ebp->Ret_Addr found. if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr)) { // Save module's address and full path. tmp_info["CallStack"][Ret_Addr_I]["ModuleName"] = ll_convert_wide_to_string(Module_Name); tmp_info["CallStack"][Ret_Addr_I]["ModuleAddress"] = (int)Module_Addr; tmp_info["CallStack"][Ret_Addr_I]["CallOffset"] = (int)(Ebp->Ret_Addr - Module_Addr); // Save 5 params of the call. We don't know the real number of params. if (fake_frame && !Ret_Addr_I) //fake frame for exception address params[0] = "Exception Offset"; else if (!IsBadReadPtr(Ebp, sizeof(PSTACK) + 5 * sizeof(DWORD))) { for(int j = 0; j < 5; ++j) { params[j] = (int)Ebp->Param[j]; } } tmp_info["CallStack"][Ret_Addr_I]["Parameters"] = params; } tmp_info["CallStack"][Ret_Addr_I]["ReturnAddress"] = (int)Ebp->Ret_Addr; // get ready for next frame // Set ESP to just after return address. Not the real esp, but just enough after the return address if(!fake_frame) { Esp = (PBYTE)Ebp + 8; } else { fake_frame = false; } // is next ebp valid? // only run if we've never found a good ebp // and make sure the one after is valid as well if( !ebp_used && shouldUseStackWalker(Ebp, 2)) { heuristic_walk_i++; PBYTE new_ebp = get_valid_frame(Esp); if (new_ebp != NULL) { Ebp = (PSTACK)new_ebp; } } else { ebp_used = true; Ebp = Ebp->Ebp; } } /* TODO remove or turn this code back on to edit the stack after i see a few raw ones. -Palmer // Now go back through and edit out heuristic stacks that could very well be bogus. // Leave the top and the last 3 stack chosen by the heuristic, however. if(heuristic_walk_i > 2) { info["CallStack"][0] = tmp_info["CallStack"][0]; std::string ttest = info["CallStack"][0]["ModuleName"]; for(int cur_frame = 1; (cur_frame + heuristic_walk_i - 2 < Ret_Addr_I); ++cur_frame) { // edit out the middle heuristic found frames info["CallStack"][cur_frame] = tmp_info["CallStack"][cur_frame + heuristic_walk_i - 2]; } } else { info = tmp_info; } */ info = tmp_info; info["HeuristicWalkI"] = heuristic_walk_i; info["EbpUsed"] = ebp_used; } //Get_Call_Stack
//************************************************************* LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException) //************************************************************* // Allocate Str[DUMP_SIZE_MAX] and return Str with dump, if !pException - just return call stack in Str. { LLSD info; LPWSTR Str; int Str_Len; // int i; LPWSTR Module_Name = new WCHAR[MAX_PATH]; PBYTE Module_Addr; HANDLE hFile; FILETIME Last_Write_Time; FILETIME Local_File_Time; SYSTEMTIME T; Str = new WCHAR[DUMP_SIZE_MAX]; Str_Len = 0; if (!Str) return NULL; Get_Version_Str(info); GetModuleFileName(NULL, Str, MAX_PATH); info["Process"] = ll_convert_wide_to_string(Str); info["ThreadID"] = (S32)GetCurrentThreadId(); // If exception occurred. if (pException) { EXCEPTION_RECORD & E = *pException->ExceptionRecord; CONTEXT & C = *pException->ContextRecord; // If module with E.ExceptionAddress found - save its path and date. if (Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress, Module_Name, Module_Addr)) { info["Module"] = ll_convert_wide_to_string(Module_Name); if ((hFile = CreateFile(Module_Name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { if (GetFileTime(hFile, NULL, NULL, &Last_Write_Time)) { FileTimeToLocalFileTime(&Last_Write_Time, &Local_File_Time); FileTimeToSystemTime(&Local_File_Time, &T); info["DateModified"] = llformat("%02d/%02d/%d", T.wMonth, T.wDay, T.wYear); } CloseHandle(hFile); } } else { info["ExceptionAddr"] = (int)E.ExceptionAddress; } info["ExceptionCode"] = (int)E.ExceptionCode; /* //TODO: Fix this if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { // Access violation type - Write/Read. LLSD exception_info; exception_info["Type"] = E.ExceptionInformation[0] ? "Write" : "Read"; exception_info["Address"] = llformat("%08x", E.ExceptionInformation[1]); info["Exception Information"] = exception_info; } */ // Save instruction that caused exception. /* std::string str; for (i = 0; i < 16; i++) str += llformat(" %02X", PBYTE(E.ExceptionAddress)[i]); info["Instruction"] = str; */ LLSD registers; registers["EAX"] = (int)C.Eax; registers["EBX"] = (int)C.Ebx; registers["ECX"] = (int)C.Ecx; registers["EDX"] = (int)C.Edx; registers["ESI"] = (int)C.Esi; registers["EDI"] = (int)C.Edi; registers["ESP"] = (int)C.Esp; registers["EBP"] = (int)C.Ebp; registers["EIP"] = (int)C.Eip; registers["EFlags"] = (int)C.EFlags; info["Registers"] = registers; } //if (pException) // Save call stack info. Get_Call_Stack(pException->ExceptionRecord, pException->ContextRecord, info); return info; } //Get_Exception_Info
U32 cycles = seconds * CYCLES_PER_SECOND; while( cycles-- ) { update_messages(); ms_sleep(1000 / CYCLES_PER_SECOND); } } // Include product name in the window caption. void LLCrashLoggerWindows::ProcessCaption(HWND hWnd) { TCHAR templateText[MAX_STRING]; /* Flawfinder: ignore */ TCHAR header[MAX_STRING]; std::string final; GetWindowText(hWnd, templateText, sizeof(templateText)); final = llformat(ll_convert_wide_to_string(templateText).c_str(), gProductName.c_str()); ConvertLPCSTRToLPWSTR(final.c_str(), header); SetWindowText(hWnd, header); } // Include product name in the diaog item text. void LLCrashLoggerWindows::ProcessDlgItemText(HWND hWnd, int nIDDlgItem) { TCHAR templateText[MAX_STRING]; /* Flawfinder: ignore */ TCHAR header[MAX_STRING]; std::string final; GetDlgItemText(hWnd, nIDDlgItem, templateText, sizeof(templateText)); final = llformat(ll_convert_wide_to_string(templateText).c_str(), gProductName.c_str()); ConvertLPCSTRToLPWSTR(final.c_str(), header); SetDlgItemText(hWnd, nIDDlgItem, header);