mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-10 00:29:31 +00:00
backtrace output for win platform added, testing with abort() call in ~AppClass()
This commit is contained in:
parent
d672353ff9
commit
0f4405dbaf
@ -231,6 +231,8 @@ void Application::socketReading() {
|
||||
}
|
||||
|
||||
void Application::socketError(QLocalSocket::LocalSocketError e) {
|
||||
if (App::quiting()) return;
|
||||
|
||||
if (_secondInstance) {
|
||||
LOG(("Could not write show command, error %1, quiting..").arg(e));
|
||||
return App::quit();
|
||||
@ -265,18 +267,33 @@ void Application::singleInstanceChecked() {
|
||||
if (cManyInstance()) {
|
||||
Logs::multipleInstances();
|
||||
}
|
||||
if ((!cManyInstance() && !Logs::instanceChecked()) || !Logs::started()) {
|
||||
MessageBox(0, (QString::fromStdWString(L"Could not initialize logs!\n\n") + Logs::full()).toStdWString().c_str(), L"Error!", MB_ICONERROR);
|
||||
// show error window
|
||||
App::quit();
|
||||
return;
|
||||
}
|
||||
|
||||
Global::start();
|
||||
|
||||
// if crashed, show window and try to autoupdate
|
||||
|
||||
new AppClass();
|
||||
if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) {
|
||||
// show error window
|
||||
MessageBox(0, (QString::fromStdWString(L"Could not start Telegram Dekstop! Log:\n\n") + Logs::full()).toStdWString().c_str(), L"Error!", MB_ICONERROR);
|
||||
App::quit();
|
||||
} else {
|
||||
SignalHandlers::Status status = SignalHandlers::start();
|
||||
if (status == SignalHandlers::CantOpen) {
|
||||
// show error window
|
||||
MessageBox(0, (QString::fromStdWString(L"Could not start Telegram Dekstop! Log:\n\n") + Logs::full()).toStdWString().c_str(), L"Error!", MB_ICONERROR);
|
||||
App::quit();
|
||||
} else {
|
||||
if (status == SignalHandlers::LastCrashed) {
|
||||
// show error window
|
||||
MessageBox(0, (QString::fromStdWString(L"Last time Telegram Dekstop crashed! Log:\n\n") + Logs::full()).toStdWString().c_str(), L"Error!", MB_ICONERROR);
|
||||
if (SignalHandlers::restart() == SignalHandlers::CantOpen) {
|
||||
// show error window
|
||||
MessageBox(0, (QString::fromStdWString(L"Could not start Telegram Dekstop! Log:\n\n") + Logs::full()).toStdWString().c_str(), L"Error!", MB_ICONERROR);
|
||||
App::quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
new AppClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::socketDisconnected() {
|
||||
@ -638,8 +655,6 @@ AppClass::AppClass() : QObject()
|
||||
, _uploader(0) {
|
||||
AppObject = this;
|
||||
|
||||
installSignalHandlers();
|
||||
|
||||
ThirdParty::start();
|
||||
Sandbox::start();
|
||||
Local::start();
|
||||
@ -1035,6 +1050,8 @@ void AppClass::execExternal(const QString &cmd) {
|
||||
}
|
||||
|
||||
AppClass::~AppClass() {
|
||||
abort();
|
||||
|
||||
_window.setParent(0);
|
||||
|
||||
anim::stopManager();
|
||||
|
@ -179,6 +179,8 @@ namespace Notify {
|
||||
struct GlobalDataStruct {
|
||||
QString LangSystemISO;
|
||||
int32 LangSystem = languageDefault;
|
||||
|
||||
QByteArray LastCrashDump;
|
||||
};
|
||||
GlobalDataStruct *GlobalData = 0;
|
||||
|
||||
@ -278,6 +280,7 @@ Type &Ref##Name() { \
|
||||
|
||||
DefineGlobalReadOnly(QString, LangSystemISO);
|
||||
DefineGlobalReadOnly(int32, LangSystem);
|
||||
DefineGlobal(QByteArray, LastCrashDump);
|
||||
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,7 @@ namespace Global {
|
||||
|
||||
DeclareGlobalReadOnly(QString, LangSystemISO);
|
||||
DeclareGlobalReadOnly(int32, LangSystem);
|
||||
DeclareGlobal(QByteArray, LastCrashDump);
|
||||
|
||||
}
|
||||
|
||||
|
@ -267,13 +267,11 @@ namespace Logs {
|
||||
}
|
||||
bool workingDirChosen = cBetaVersion();
|
||||
|
||||
QString moveOldDataFrom;
|
||||
QString initialWorkingDir = QDir(cWorkingDir()).absolutePath() + '/', moveOldDataFrom;
|
||||
if (cBetaVersion()) {
|
||||
cSetDebug(true);
|
||||
#if (defined Q_OS_MAC || defined Q_OS_LINUX)
|
||||
} else {
|
||||
QString wasDir = QDir(cWorkingDir()).absolutePath() + '/';
|
||||
|
||||
#ifdef _DEBUG
|
||||
cForceWorkingDir(cExeDir());
|
||||
#else
|
||||
@ -284,7 +282,7 @@ namespace Logs {
|
||||
workingDirChosen = true;
|
||||
|
||||
#if (defined Q_OS_LINUX && !defined _DEBUG) // fix first version
|
||||
moveOldDataFrom = wasDir;
|
||||
moveOldDataFrom = initialWorkingDir;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -303,17 +301,22 @@ namespace Logs {
|
||||
|
||||
cForceWorkingDir(QDir(cWorkingDir()).absolutePath() + '/');
|
||||
QDir().setCurrent(cWorkingDir());
|
||||
QDir().mkpath(cWorkingDir() + qstr("tdata"));
|
||||
|
||||
Global::WorkingDirReady();
|
||||
|
||||
LOG(("Launched version: %1, dev: %2, beta: %3, debug mode: %4, test dc: %5").arg(AppVersion).arg(Logs::b(cDevVersion())).arg(cBetaVersion()).arg(Logs::b(cDebug())).arg(Logs::b(cTestMode())));
|
||||
LOG(("Executable dir: %1, name: %2").arg(cExeDir()).arg(cExeName()));
|
||||
LOG(("Working dir: %1").arg(cWorkingDir()));
|
||||
LOG(("Arguments: %1").arg(cArguments()));
|
||||
|
||||
if (!LogsData->openMain()) {
|
||||
delete LogsData;
|
||||
LogsData = 0;
|
||||
}
|
||||
|
||||
LOG(("Launched version: %1, dev: %2, beta: %3, debug mode: %4, test dc: %5").arg(AppVersion).arg(Logs::b(cDevVersion())).arg(cBetaVersion()).arg(Logs::b(cDebug())).arg(Logs::b(cTestMode())));
|
||||
LOG(("Executable dir: %1, name: %2").arg(cExeDir()).arg(cExeName()));
|
||||
LOG(("Initial working dir: %1").arg(initialWorkingDir));
|
||||
LOG(("Working dir: %1").arg(cWorkingDir()));
|
||||
LOG(("Arguments: %1").arg(cArguments()));
|
||||
|
||||
if (!LogsData) {
|
||||
LOG(("Could not open '%1' for writing log!").arg(_logsFilePath(LogDataMain, qsl("_startXX"))));
|
||||
return;
|
||||
}
|
||||
@ -333,11 +336,12 @@ namespace Logs {
|
||||
for (LogsInMemoryList::const_iterator i = list.cbegin(), e = list.cend(); i != e; ++i) {
|
||||
if (i->first == LogDataMain) {
|
||||
_logsWrite(i->first, i->second);
|
||||
LOG(("First: %1, %2").arg(i->first).arg(i->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG(("Logs started."));
|
||||
LOG(("Logs started"));
|
||||
}
|
||||
|
||||
Initializer::~Initializer() {
|
||||
@ -368,6 +372,8 @@ namespace Logs {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (LogsInMemory) {
|
||||
t_assert(LogsInMemory != DeletedLogsInMemory);
|
||||
LogsInMemoryList list = *LogsInMemory;
|
||||
@ -539,3 +545,126 @@ void _moveOldDataFiles(const QString &wasDir) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace SignalHandlers {
|
||||
|
||||
QByteArray CrashDumpPath;
|
||||
FILE *CrashDumpFile = 0;
|
||||
int CrashDumpFileNo = 0;
|
||||
|
||||
void _writeChar(char ch) {
|
||||
fwrite(&ch, 1, 1, CrashDumpFile);
|
||||
}
|
||||
|
||||
dump::~dump() {
|
||||
if (CrashDumpFile) {
|
||||
fflush(CrashDumpFile);
|
||||
}
|
||||
}
|
||||
|
||||
const dump &operator<<(const dump &stream, const char *str) {
|
||||
if (!CrashDumpFile) return stream;
|
||||
|
||||
fwrite(str, 1, strlen(str), CrashDumpFile);
|
||||
return stream;
|
||||
}
|
||||
|
||||
const dump &operator<<(const dump &stream, int num) {
|
||||
if (!CrashDumpFile) return stream;
|
||||
|
||||
if (num < 0) {
|
||||
_writeChar('-');
|
||||
num = -num;
|
||||
}
|
||||
int upper = 1, prev = num / 10;
|
||||
while (prev >= upper) {
|
||||
upper *= 10;
|
||||
}
|
||||
while (upper > 0) {
|
||||
int digit = (num / upper);
|
||||
_writeChar('0' + digit);
|
||||
num -= digit * upper;
|
||||
upper /= 10;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
void Handler(int signum) {
|
||||
const char* name = 0;
|
||||
switch (signum) {
|
||||
case SIGABRT: name = "SIGABRT"; break;
|
||||
case SIGSEGV: name = "SIGSEGV"; break;
|
||||
case SIGILL: name = "SIGILL"; break;
|
||||
case SIGFPE: name = "SIGFPE"; break;
|
||||
#ifndef Q_OS_WIN
|
||||
case SIGBUS: name = "SIGBUS"; break;
|
||||
case SIGSYS: name = "SIGSYS"; break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (name) {
|
||||
dump() << "Caught signal " << signum << " (" << name << ")\n";
|
||||
} else {
|
||||
dump() << "Caught signal " << signum << "\n";
|
||||
}
|
||||
dump() << "Platform: ";
|
||||
switch (cPlatform()) {
|
||||
case dbipWindows: dump() << "win"; break;
|
||||
case dbipMac: dump() << "mac"; break;
|
||||
case dbipMacOld: dump() << "macold"; break;
|
||||
case dbipLinux64: dump() << "linux64"; break;
|
||||
case dbipLinux32: dump() << "linux32"; break;
|
||||
}
|
||||
dump() << "\n\nBacktrace:\n";
|
||||
psWriteStackTrace(CrashDumpFileNo);
|
||||
}
|
||||
|
||||
Status start() {
|
||||
CrashDumpPath = (cWorkingDir() + qsl("tdata/working")).toUtf8();
|
||||
if (FILE *f = fopen(CrashDumpPath.constData(), "rb")) {
|
||||
QByteArray lastdump;
|
||||
char buffer[64 * 1024] = { 0 };
|
||||
int32 read = 0;
|
||||
while ((read = fread(buffer, 1, 64 * 1024, f)) > 0) {
|
||||
lastdump.append(buffer, read);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
Global::SetLastCrashDump(lastdump);
|
||||
|
||||
LOG(("Opened '%1' for reading, the previous Telegram Desktop launch was not finished properly :( Crash log size: %2").arg(QString::fromUtf8(CrashDumpPath)).arg(lastdump.size()));
|
||||
|
||||
return LastCrashed;
|
||||
}
|
||||
return restart();
|
||||
}
|
||||
|
||||
Status restart() {
|
||||
CrashDumpFile = fopen(CrashDumpPath.constData(), "wb");
|
||||
if (CrashDumpFile) {
|
||||
CrashDumpFileNo = fileno(CrashDumpFile);
|
||||
|
||||
signal(SIGABRT, SignalHandlers::Handler);
|
||||
signal(SIGSEGV, SignalHandlers::Handler);
|
||||
signal(SIGILL, SignalHandlers::Handler);
|
||||
signal(SIGFPE, SignalHandlers::Handler);
|
||||
#ifndef Q_OS_WIN
|
||||
signal(SIGBUS, SignalHandlers::Handler);
|
||||
signal(SIGSYS, SignalHandlers::Handler);
|
||||
#endif
|
||||
return Started;
|
||||
}
|
||||
|
||||
LOG(("Could not open '%1' for writing!").arg(QString::fromUtf8(CrashDumpPath)));
|
||||
|
||||
return CantOpen;
|
||||
}
|
||||
|
||||
void finish() {
|
||||
if (CrashDumpFile) {
|
||||
fclose(CrashDumpFile);
|
||||
unlink(CrashDumpPath.constData());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -85,3 +85,22 @@ namespace Logs {
|
||||
|
||||
#define MTP_LOG(dc, msg) { if (cDebug() || !Logs::started()) Logs::writeMtp(dc, QString msg); }
|
||||
//usage MTP_LOG(dc, ("log: %1 %2").arg(1).arg(2))
|
||||
|
||||
namespace SignalHandlers {
|
||||
|
||||
struct dump {
|
||||
~dump();
|
||||
};
|
||||
const dump &operator<<(const dump &stream, const char *str);
|
||||
const dump &operator<<(const dump &stream, int num);
|
||||
|
||||
enum Status {
|
||||
CantOpen,
|
||||
LastCrashed,
|
||||
Started
|
||||
};
|
||||
Status start();
|
||||
Status restart(); // can be only CantOpen or Started
|
||||
void finish();
|
||||
|
||||
}
|
||||
|
@ -67,5 +67,6 @@ int main(int argc, char *argv[]) {
|
||||
psExecTelegram();
|
||||
}
|
||||
|
||||
SignalHandlers::finish();
|
||||
return result;
|
||||
}
|
||||
|
@ -2368,6 +2368,88 @@ typedef BOOL (FAR STDAPICALLTYPE *t_miniDumpWriteDump)(
|
||||
);
|
||||
t_miniDumpWriteDump miniDumpWriteDump = 0;
|
||||
|
||||
//// SymCleanup()
|
||||
//typedef BOOL(__stdcall *tSC)(IN HANDLE hProcess);
|
||||
//tSC pSC;
|
||||
//
|
||||
// SymFunctionTableAccess64()
|
||||
typedef PVOID (FAR STDAPICALLTYPE *t_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
|
||||
t_SymFunctionTableAccess64 symFunctionTableAccess64 = 0;
|
||||
|
||||
//// SymGetLineFromAddr64()
|
||||
//typedef BOOL(__stdcall *tSGLFA)(IN HANDLE hProcess, IN DWORD64 dwAddr,
|
||||
// OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line);
|
||||
//tSGLFA pSGLFA;
|
||||
//
|
||||
// SymGetModuleBase64()
|
||||
typedef DWORD64 (FAR STDAPICALLTYPE *t_SymGetModuleBase64)(IN HANDLE hProcess, IN DWORD64 dwAddr);
|
||||
t_SymGetModuleBase64 symGetModuleBase64 = 0;
|
||||
|
||||
//// SymGetModuleInfo64()
|
||||
//typedef BOOL(__stdcall *tSGMI)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V2 *ModuleInfo);
|
||||
//tSGMI pSGMI;
|
||||
|
||||
// // SymGetModuleInfo64()
|
||||
// typedef BOOL (__stdcall *tSGMI_V3)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V3 *ModuleInfo );
|
||||
// tSGMI_V3 pSGMI_V3;
|
||||
|
||||
//// SymGetOptions()
|
||||
//typedef DWORD(__stdcall *tSGO)(VOID);
|
||||
//tSGO pSGO;
|
||||
//
|
||||
//// SymGetSymFromAddr64()
|
||||
//typedef BOOL(__stdcall *tSGSFA)(IN HANDLE hProcess, IN DWORD64 dwAddr,
|
||||
// OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol);
|
||||
//tSGSFA pSGSFA;
|
||||
//
|
||||
//// SymInitialize()
|
||||
//typedef BOOL(__stdcall *tSI)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess);
|
||||
//tSI pSI;
|
||||
//
|
||||
//// SymLoadModule64()
|
||||
//typedef DWORD64(__stdcall *tSLM)(IN HANDLE hProcess, IN HANDLE hFile,
|
||||
// IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll);
|
||||
//tSLM pSLM;
|
||||
//
|
||||
//// SymSetOptions()
|
||||
//typedef DWORD(__stdcall *tSSO)(IN DWORD SymOptions);
|
||||
//tSSO pSSO;
|
||||
|
||||
typedef BOOL (FAR STDAPICALLTYPE *t_StackWalk64)(
|
||||
_In_ DWORD MachineType,
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ HANDLE hThread,
|
||||
_Inout_ LPSTACKFRAME64 StackFrame,
|
||||
_Inout_ PVOID ContextRecord,
|
||||
_In_opt_ PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
|
||||
_In_opt_ PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
|
||||
_In_opt_ PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
|
||||
_In_opt_ PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
|
||||
);
|
||||
t_StackWalk64 stackWalk64 = 0;
|
||||
|
||||
//// UnDecorateSymbolName()
|
||||
//typedef DWORD(__stdcall WINAPI *tUDSN)(PCSTR DecoratedName, PSTR UnDecoratedName,
|
||||
// DWORD UndecoratedLength, DWORD Flags);
|
||||
//tUDSN pUDSN;
|
||||
//
|
||||
//typedef BOOL(__stdcall WINAPI *tSGSP)(HANDLE hProcess, PSTR SearchPath, DWORD SearchPathLength);
|
||||
//tSGSP pSGSP;
|
||||
|
||||
BOOL __stdcall ReadProcessMemoryRoutine64(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 qwBaseAddress,
|
||||
_Out_writes_bytes_(nSize) PVOID lpBuffer,
|
||||
_In_ DWORD nSize,
|
||||
_Out_ LPDWORD lpNumberOfBytesRead
|
||||
) {
|
||||
SIZE_T st;
|
||||
BOOL bRet = ReadProcessMemory(hProcess, (LPVOID)qwBaseAddress, lpBuffer, nSize, &st);
|
||||
*lpNumberOfBytesRead = (DWORD)st;
|
||||
//printf("ReadMemory: hProcess: %p, baseAddr: %p, buffer: %p, size: %d, read: %d, result: %d\n", hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, (DWORD) st, (DWORD) bRet);
|
||||
return bRet;
|
||||
}
|
||||
|
||||
HANDLE _generateDumpFileAtPath(const WCHAR *path) {
|
||||
static const int maxFileLen = MAX_PATH * 10;
|
||||
|
||||
@ -2381,7 +2463,7 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) {
|
||||
}
|
||||
}
|
||||
|
||||
WCHAR szFileName[maxFileLen];
|
||||
WCHAR szFileName[maxFileLen];
|
||||
WCHAR szExeName[maxFileLen];
|
||||
|
||||
wcscpy_s(szExeName, _exeName);
|
||||
@ -2410,14 +2492,94 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) {
|
||||
return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
|
||||
}
|
||||
|
||||
bool LoadDbgHelp() {
|
||||
if (miniDumpWriteDump) return true;
|
||||
|
||||
HMODULE hDll = 0;
|
||||
|
||||
WCHAR szTemp[4096];
|
||||
if (GetModuleFileName(NULL, szTemp, 4096) > 0) {
|
||||
wcscat(szTemp, L".local");
|
||||
if (GetFileAttributes(szTemp) == INVALID_FILE_ATTRIBUTES) {
|
||||
// ".local" file does not exist, so we can try to load the dbghelp.dll from the "Debugging Tools for Windows"
|
||||
if (GetEnvironmentVariable(L"ProgramFiles", szTemp, 4096) > 0) {
|
||||
wcscat(szTemp, L"\\Debugging Tools for Windows\\dbghelp.dll");
|
||||
// now check if the file exists:
|
||||
if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) {
|
||||
hDll = LoadLibrary(szTemp);
|
||||
}
|
||||
}
|
||||
// Still not found? Then try to load the 64-Bit version:
|
||||
if (!hDll && (GetEnvironmentVariable(L"ProgramFiles", szTemp, 4096) > 0)) {
|
||||
wcscat(szTemp, L"\\Debugging Tools for Windows 64-Bit\\dbghelp.dll");
|
||||
if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) {
|
||||
hDll = LoadLibrary(szTemp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hDll) {
|
||||
hDll = LoadLibrary(L"DBGHELP.DLL");
|
||||
}
|
||||
|
||||
if (!hDll) return false;
|
||||
|
||||
miniDumpWriteDump = (t_miniDumpWriteDump)GetProcAddress(hDll, "MiniDumpWriteDump");
|
||||
|
||||
//pSI = (tSI)GetProcAddress(m_hDbhHelp, "SymInitialize");
|
||||
//pSC = (tSC)GetProcAddress(m_hDbhHelp, "SymCleanup");
|
||||
|
||||
stackWalk64 = (t_StackWalk64)GetProcAddress(hDll, "StackWalk64");
|
||||
//pSGO = (tSGO)GetProcAddress(m_hDbhHelp, "SymGetOptions");
|
||||
//pSSO = (tSSO)GetProcAddress(m_hDbhHelp, "SymSetOptions");
|
||||
|
||||
symFunctionTableAccess64 = (t_SymFunctionTableAccess64)GetProcAddress(hDll, "SymFunctionTableAccess64");
|
||||
//pSGLFA = (tSGLFA)GetProcAddress(m_hDbhHelp, "SymGetLineFromAddr64");
|
||||
symGetModuleBase64 = (t_SymGetModuleBase64)GetProcAddress(hDll, "SymGetModuleBase64");
|
||||
//pSGMI = (tSGMI)GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64");
|
||||
////pSGMI_V3 = (tSGMI_V3) GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64" );
|
||||
//pSGSFA = (tSGSFA)GetProcAddress(m_hDbhHelp, "SymGetSymFromAddr64");
|
||||
//pUDSN = (tUDSN)GetProcAddress(m_hDbhHelp, "UnDecorateSymbolName");
|
||||
//pSLM = (tSLM)GetProcAddress(m_hDbhHelp, "SymLoadModule64");
|
||||
//pSGSP = (tSGSP)GetProcAddress(m_hDbhHelp, "SymGetSearchPath");
|
||||
|
||||
if (!miniDumpWriteDump ||
|
||||
!stackWalk64) {
|
||||
miniDumpWriteDump = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
//// SymInitialize
|
||||
//if (szSymPath != NULL)
|
||||
// m_szSymPath = _strdup(szSymPath);
|
||||
//if (this->pSI(m_hProcess, m_szSymPath, FALSE) == FALSE)
|
||||
// this->m_parent->OnDbgHelpErr("SymInitialize", GetLastError(), 0);
|
||||
|
||||
//DWORD symOptions = this->pSGO(); // SymGetOptions
|
||||
//symOptions |= SYMOPT_LOAD_LINES;
|
||||
//symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
|
||||
////symOptions |= SYMOPT_NO_PROMPTS;
|
||||
//// SymSetOptions
|
||||
//symOptions = this->pSSO(symOptions);
|
||||
|
||||
//char buf[StackWalker::STACKWALK_MAX_NAMELEN] = { 0 };
|
||||
//if (this->pSGSP != NULL)
|
||||
//{
|
||||
// if (this->pSGSP(m_hProcess, buf, StackWalker::STACKWALK_MAX_NAMELEN) == FALSE)
|
||||
// this->m_parent->OnDbgHelpErr("SymGetSearchPath", GetLastError(), 0);
|
||||
//}
|
||||
//char szUserName[1024] = { 0 };
|
||||
//DWORD dwSize = 1024;
|
||||
//GetUserNameA(szUserName, &dwSize);
|
||||
//this->m_parent->OnSymInit(buf, symOptions, szUserName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void _generateDump(EXCEPTION_POINTERS* pExceptionPointers) {
|
||||
static const int maxFileLen = MAX_PATH * 10;
|
||||
|
||||
HMODULE hDll = LoadLibrary(L"DBGHELP.DLL");
|
||||
if (!hDll) return;
|
||||
|
||||
miniDumpWriteDump = (t_miniDumpWriteDump)GetProcAddress(hDll, "MiniDumpWriteDump");
|
||||
if (!miniDumpWriteDump) return;
|
||||
if (!LoadDbgHelp()) return;
|
||||
|
||||
HANDLE hDumpFile = 0;
|
||||
|
||||
@ -2465,6 +2627,150 @@ LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_op
|
||||
return 0;
|
||||
}
|
||||
|
||||
// stack walking code taken from StackWalker
|
||||
static const int StackEntryMaxNameLength = 1024;
|
||||
struct StackEntry {
|
||||
DWORD64 offset; // if 0, we have no valid entry
|
||||
CHAR name[StackEntryMaxNameLength];
|
||||
CHAR undName[StackEntryMaxNameLength];
|
||||
CHAR undFullName[StackEntryMaxNameLength];
|
||||
DWORD64 offsetFromSmybol;
|
||||
DWORD offsetFromLine;
|
||||
DWORD lineNumber;
|
||||
CHAR lineFileName[StackEntryMaxNameLength];
|
||||
DWORD symType;
|
||||
LPCSTR symTypeString;
|
||||
CHAR moduleName[StackEntryMaxNameLength];
|
||||
DWORD64 baseOfImage;
|
||||
CHAR loadedImageName[StackEntryMaxNameLength];
|
||||
};
|
||||
|
||||
enum StackEntryType {
|
||||
StackEntryFirst,
|
||||
StackEntryNext,
|
||||
StackEntryLast,
|
||||
};
|
||||
|
||||
struct IMAGEHLP_MODULE64_V2 {
|
||||
DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64)
|
||||
DWORD64 BaseOfImage; // base load address of module
|
||||
DWORD ImageSize; // virtual size of the loaded module
|
||||
DWORD TimeDateStamp; // date/time stamp from pe header
|
||||
DWORD CheckSum; // checksum from the pe header
|
||||
DWORD NumSyms; // number of symbols in the symbol table
|
||||
SYM_TYPE SymType; // type of symbols loaded
|
||||
CHAR ModuleName[32]; // module name
|
||||
CHAR ImageName[256]; // image name
|
||||
CHAR LoadedImageName[256]; // symbol file name
|
||||
};
|
||||
|
||||
char ImageHlpSymbol64[sizeof(IMAGEHLP_SYMBOL64) + StackEntryMaxNameLength];
|
||||
|
||||
void psWriteStackTrace(int n) {
|
||||
if (!LoadDbgHelp()) return;
|
||||
|
||||
HANDLE hThread = GetCurrentThread(), hProcess = GetCurrentProcess();
|
||||
const CONTEXT *context = NULL;
|
||||
LPVOID pUserData = NULL;
|
||||
|
||||
CONTEXT c;
|
||||
StackEntry csEntry;
|
||||
IMAGEHLP_SYMBOL64 *pSym = NULL;
|
||||
IMAGEHLP_MODULE64_V2 Module;
|
||||
IMAGEHLP_LINE64 Line;
|
||||
int frameNum;
|
||||
|
||||
if (!LoadDbgHelp()) {
|
||||
SignalHandlers::dump() << "ERROR: Could not load dbghelp.dll!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&c, 0, sizeof(CONTEXT));
|
||||
c.ContextFlags = CONTEXT_FULL;
|
||||
RtlCaptureContext(&c);
|
||||
|
||||
// init STACKFRAME for first call
|
||||
STACKFRAME64 s; // in/out stackframe
|
||||
memset(&s, 0, sizeof(s));
|
||||
DWORD imageType;
|
||||
#ifdef _M_IX86
|
||||
// normally, call ImageNtHeader() and use machine info from PE header
|
||||
imageType = IMAGE_FILE_MACHINE_I386;
|
||||
s.AddrPC.Offset = c.Eip;
|
||||
s.AddrPC.Mode = AddrModeFlat;
|
||||
s.AddrFrame.Offset = c.Ebp;
|
||||
s.AddrFrame.Mode = AddrModeFlat;
|
||||
s.AddrStack.Offset = c.Esp;
|
||||
s.AddrStack.Mode = AddrModeFlat;
|
||||
#elif _M_X64
|
||||
imageType = IMAGE_FILE_MACHINE_AMD64;
|
||||
s.AddrPC.Offset = c.Rip;
|
||||
s.AddrPC.Mode = AddrModeFlat;
|
||||
s.AddrFrame.Offset = c.Rsp;
|
||||
s.AddrFrame.Mode = AddrModeFlat;
|
||||
s.AddrStack.Offset = c.Rsp;
|
||||
s.AddrStack.Mode = AddrModeFlat;
|
||||
#elif _M_IA64
|
||||
imageType = IMAGE_FILE_MACHINE_IA64;
|
||||
s.AddrPC.Offset = c.StIIP;
|
||||
s.AddrPC.Mode = AddrModeFlat;
|
||||
s.AddrFrame.Offset = c.IntSp;
|
||||
s.AddrFrame.Mode = AddrModeFlat;
|
||||
s.AddrBStore.Offset = c.RsBSP;
|
||||
s.AddrBStore.Mode = AddrModeFlat;
|
||||
s.AddrStack.Offset = c.IntSp;
|
||||
s.AddrStack.Mode = AddrModeFlat;
|
||||
#else
|
||||
#error "Platform not supported!"
|
||||
#endif
|
||||
|
||||
pSym = (IMAGEHLP_SYMBOL64 *)ImageHlpSymbol64;
|
||||
memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + StackEntryMaxNameLength);
|
||||
pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
pSym->MaxNameLength = StackEntryMaxNameLength;
|
||||
|
||||
memset(&Line, 0, sizeof(Line));
|
||||
Line.SizeOfStruct = sizeof(Line);
|
||||
|
||||
memset(&Module, 0, sizeof(Module));
|
||||
Module.SizeOfStruct = sizeof(Module);
|
||||
|
||||
for (frameNum = 0; ; ++frameNum) {
|
||||
// get next stack frame (StackWalk64(), SymFunctionTableAccess64(), SymGetModuleBase64())
|
||||
// if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can
|
||||
// assume that either you are done, or that the stack is so hosed that the next
|
||||
// deeper frame could not be found.
|
||||
// CONTEXT need not to be suplied if imageTyp is IMAGE_FILE_MACHINE_I386!
|
||||
if (!stackWalk64(imageType, hProcess, hThread, &s, &c, ReadProcessMemoryRoutine64, symFunctionTableAccess64, symGetModuleBase64, NULL)) {
|
||||
SignalHandlers::dump() << "ERROR: Call to StackWalk64() failed!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
csEntry.offset = s.AddrPC.Offset;
|
||||
csEntry.name[0] = 0;
|
||||
csEntry.undName[0] = 0;
|
||||
csEntry.undFullName[0] = 0;
|
||||
csEntry.offsetFromSmybol = 0;
|
||||
csEntry.offsetFromLine = 0;
|
||||
csEntry.lineFileName[0] = 0;
|
||||
csEntry.lineNumber = 0;
|
||||
csEntry.loadedImageName[0] = 0;
|
||||
csEntry.moduleName[0] = 0;
|
||||
if (s.AddrPC.Offset == s.AddrReturn.Offset) {
|
||||
SignalHandlers::dump() << s.AddrPC.Offset << "\n";
|
||||
SignalHandlers::dump() << "ERROR: StackWalk64() endless callstack!";
|
||||
return;
|
||||
}
|
||||
if (s.AddrPC.Offset != 0) { // we seem to have a valid PC
|
||||
SignalHandlers::dump() << s.AddrPC.Offset << "\n";
|
||||
}
|
||||
|
||||
if (s.AddrReturn.Offset == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class StringReferenceWrapper {
|
||||
public:
|
||||
|
||||
|
@ -117,6 +117,8 @@ extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter;
|
||||
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers);
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
|
||||
|
||||
void psWriteStackTrace(int n);
|
||||
|
||||
void psDeleteDir(const QString &dir);
|
||||
|
||||
void psUserActionDone();
|
||||
|
@ -22,6 +22,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
#define PSAPI_VERSION 1 // fix WinXP
|
||||
//#define Q_NO_TEMPLATE_FRIENDS // fix some compiler difference issues
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/pem.h>
|
||||
|
@ -22,8 +22,6 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||
|
||||
#include "application.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 };
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
@ -309,47 +307,6 @@ namespace ThirdParty {
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
FILE *_crashDump = 0;
|
||||
int _crashDumpNo = 0;
|
||||
}
|
||||
|
||||
void _signalHandler(int signum) {
|
||||
const char* name = 0;
|
||||
switch (signum) {
|
||||
case SIGABRT: name = "SIGABRT"; break;
|
||||
case SIGSEGV: name = "SIGSEGV"; break;
|
||||
case SIGILL: name = "SIGILL"; break;
|
||||
case SIGFPE: name = "SIGFPE"; break;
|
||||
#ifndef Q_OS_WIN
|
||||
case SIGBUS: name = "SIGBUS"; break;
|
||||
case SIGSYS: name = "SIGSYS"; break;
|
||||
#endif
|
||||
}
|
||||
LOG(("Caught signal %1").arg(name));
|
||||
if (name)
|
||||
fprintf(stdout, "Caught signal %d (%s)\n", signum, name);
|
||||
else
|
||||
fprintf(stdout, "Caught signal %d\n", signum);
|
||||
|
||||
|
||||
//printStackTrace();
|
||||
}
|
||||
|
||||
void installSignalHandlers() {
|
||||
_crashDump = fopen((cWorkingDir() + qsl("tdata/working")).toUtf8().constData(), "wb");
|
||||
if (_crashDump) _crashDumpNo = fileno(_crashDump);
|
||||
|
||||
signal(SIGABRT, _signalHandler);
|
||||
signal(SIGSEGV, _signalHandler);
|
||||
signal(SIGILL, _signalHandler);
|
||||
signal(SIGFPE, _signalHandler);
|
||||
#ifndef Q_OS_WIN
|
||||
signal(SIGBUS, _signalHandler);
|
||||
signal(SIGSYS, _signalHandler);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool checkms() {
|
||||
int64 unixms = (myunixtime() - _timeStart) * 1000LL + _msAddToUnixtime;
|
||||
int64 ms = int64(getms(true));
|
||||
|
@ -143,8 +143,6 @@ inline void mylocaltime(struct tm * _Tm, const time_t * _Time) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void installSignalHandlers();
|
||||
|
||||
namespace ThirdParty {
|
||||
|
||||
void start();
|
||||
|
Loading…
Reference in New Issue
Block a user