mirror of https://github.com/procxx/kepka.git
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) {
|
void Application::socketError(QLocalSocket::LocalSocketError e) {
|
||||||
|
if (App::quiting()) return;
|
||||||
|
|
||||||
if (_secondInstance) {
|
if (_secondInstance) {
|
||||||
LOG(("Could not write show command, error %1, quiting..").arg(e));
|
LOG(("Could not write show command, error %1, quiting..").arg(e));
|
||||||
return App::quit();
|
return App::quit();
|
||||||
|
@ -265,18 +267,33 @@ void Application::singleInstanceChecked() {
|
||||||
if (cManyInstance()) {
|
if (cManyInstance()) {
|
||||||
Logs::multipleInstances();
|
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();
|
Global::start();
|
||||||
|
|
||||||
// if crashed, show window and try to autoupdate
|
if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) {
|
||||||
|
// show error window
|
||||||
new AppClass();
|
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() {
|
void Application::socketDisconnected() {
|
||||||
|
@ -638,8 +655,6 @@ AppClass::AppClass() : QObject()
|
||||||
, _uploader(0) {
|
, _uploader(0) {
|
||||||
AppObject = this;
|
AppObject = this;
|
||||||
|
|
||||||
installSignalHandlers();
|
|
||||||
|
|
||||||
ThirdParty::start();
|
ThirdParty::start();
|
||||||
Sandbox::start();
|
Sandbox::start();
|
||||||
Local::start();
|
Local::start();
|
||||||
|
@ -1035,6 +1050,8 @@ void AppClass::execExternal(const QString &cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
AppClass::~AppClass() {
|
AppClass::~AppClass() {
|
||||||
|
abort();
|
||||||
|
|
||||||
_window.setParent(0);
|
_window.setParent(0);
|
||||||
|
|
||||||
anim::stopManager();
|
anim::stopManager();
|
||||||
|
|
|
@ -179,6 +179,8 @@ namespace Notify {
|
||||||
struct GlobalDataStruct {
|
struct GlobalDataStruct {
|
||||||
QString LangSystemISO;
|
QString LangSystemISO;
|
||||||
int32 LangSystem = languageDefault;
|
int32 LangSystem = languageDefault;
|
||||||
|
|
||||||
|
QByteArray LastCrashDump;
|
||||||
};
|
};
|
||||||
GlobalDataStruct *GlobalData = 0;
|
GlobalDataStruct *GlobalData = 0;
|
||||||
|
|
||||||
|
@ -278,6 +280,7 @@ Type &Ref##Name() { \
|
||||||
|
|
||||||
DefineGlobalReadOnly(QString, LangSystemISO);
|
DefineGlobalReadOnly(QString, LangSystemISO);
|
||||||
DefineGlobalReadOnly(int32, LangSystem);
|
DefineGlobalReadOnly(int32, LangSystem);
|
||||||
|
DefineGlobal(QByteArray, LastCrashDump);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,7 @@ namespace Global {
|
||||||
|
|
||||||
DeclareGlobalReadOnly(QString, LangSystemISO);
|
DeclareGlobalReadOnly(QString, LangSystemISO);
|
||||||
DeclareGlobalReadOnly(int32, LangSystem);
|
DeclareGlobalReadOnly(int32, LangSystem);
|
||||||
|
DeclareGlobal(QByteArray, LastCrashDump);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -267,13 +267,11 @@ namespace Logs {
|
||||||
}
|
}
|
||||||
bool workingDirChosen = cBetaVersion();
|
bool workingDirChosen = cBetaVersion();
|
||||||
|
|
||||||
QString moveOldDataFrom;
|
QString initialWorkingDir = QDir(cWorkingDir()).absolutePath() + '/', moveOldDataFrom;
|
||||||
if (cBetaVersion()) {
|
if (cBetaVersion()) {
|
||||||
cSetDebug(true);
|
cSetDebug(true);
|
||||||
#if (defined Q_OS_MAC || defined Q_OS_LINUX)
|
#if (defined Q_OS_MAC || defined Q_OS_LINUX)
|
||||||
} else {
|
} else {
|
||||||
QString wasDir = QDir(cWorkingDir()).absolutePath() + '/';
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
cForceWorkingDir(cExeDir());
|
cForceWorkingDir(cExeDir());
|
||||||
#else
|
#else
|
||||||
|
@ -284,7 +282,7 @@ namespace Logs {
|
||||||
workingDirChosen = true;
|
workingDirChosen = true;
|
||||||
|
|
||||||
#if (defined Q_OS_LINUX && !defined _DEBUG) // fix first version
|
#if (defined Q_OS_LINUX && !defined _DEBUG) // fix first version
|
||||||
moveOldDataFrom = wasDir;
|
moveOldDataFrom = initialWorkingDir;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -303,17 +301,22 @@ namespace Logs {
|
||||||
|
|
||||||
cForceWorkingDir(QDir(cWorkingDir()).absolutePath() + '/');
|
cForceWorkingDir(QDir(cWorkingDir()).absolutePath() + '/');
|
||||||
QDir().setCurrent(cWorkingDir());
|
QDir().setCurrent(cWorkingDir());
|
||||||
|
QDir().mkpath(cWorkingDir() + qstr("tdata"));
|
||||||
|
|
||||||
Global::WorkingDirReady();
|
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()) {
|
if (!LogsData->openMain()) {
|
||||||
delete LogsData;
|
delete LogsData;
|
||||||
LogsData = 0;
|
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"))));
|
LOG(("Could not open '%1' for writing log!").arg(_logsFilePath(LogDataMain, qsl("_startXX"))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -333,11 +336,12 @@ namespace Logs {
|
||||||
for (LogsInMemoryList::const_iterator i = list.cbegin(), e = list.cend(); i != e; ++i) {
|
for (LogsInMemoryList::const_iterator i = list.cbegin(), e = list.cend(); i != e; ++i) {
|
||||||
if (i->first == LogDataMain) {
|
if (i->first == LogDataMain) {
|
||||||
_logsWrite(i->first, i->second);
|
_logsWrite(i->first, i->second);
|
||||||
|
LOG(("First: %1, %2").arg(i->first).arg(i->second));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Logs started."));
|
LOG(("Logs started"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Initializer::~Initializer() {
|
Initializer::~Initializer() {
|
||||||
|
@ -368,6 +372,8 @@ namespace Logs {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (LogsInMemory) {
|
if (LogsInMemory) {
|
||||||
t_assert(LogsInMemory != DeletedLogsInMemory);
|
t_assert(LogsInMemory != DeletedLogsInMemory);
|
||||||
LogsInMemoryList list = *LogsInMemory;
|
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); }
|
#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))
|
//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();
|
psExecTelegram();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SignalHandlers::finish();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2368,6 +2368,88 @@ typedef BOOL (FAR STDAPICALLTYPE *t_miniDumpWriteDump)(
|
||||||
);
|
);
|
||||||
t_miniDumpWriteDump miniDumpWriteDump = 0;
|
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) {
|
HANDLE _generateDumpFileAtPath(const WCHAR *path) {
|
||||||
static const int maxFileLen = MAX_PATH * 10;
|
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];
|
WCHAR szExeName[maxFileLen];
|
||||||
|
|
||||||
wcscpy_s(szExeName, _exeName);
|
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);
|
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) {
|
void _generateDump(EXCEPTION_POINTERS* pExceptionPointers) {
|
||||||
static const int maxFileLen = MAX_PATH * 10;
|
static const int maxFileLen = MAX_PATH * 10;
|
||||||
|
|
||||||
HMODULE hDll = LoadLibrary(L"DBGHELP.DLL");
|
if (!LoadDbgHelp()) return;
|
||||||
if (!hDll) return;
|
|
||||||
|
|
||||||
miniDumpWriteDump = (t_miniDumpWriteDump)GetProcAddress(hDll, "MiniDumpWriteDump");
|
|
||||||
if (!miniDumpWriteDump) return;
|
|
||||||
|
|
||||||
HANDLE hDumpFile = 0;
|
HANDLE hDumpFile = 0;
|
||||||
|
|
||||||
|
@ -2465,6 +2627,150 @@ LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_op
|
||||||
return 0;
|
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 {
|
class StringReferenceWrapper {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,8 @@ extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter;
|
||||||
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers);
|
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers);
|
||||||
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
|
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
|
||||||
|
|
||||||
|
void psWriteStackTrace(int n);
|
||||||
|
|
||||||
void psDeleteDir(const QString &dir);
|
void psDeleteDir(const QString &dir);
|
||||||
|
|
||||||
void psUserActionDone();
|
void psUserActionDone();
|
||||||
|
|
|
@ -22,6 +22,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
#define PSAPI_VERSION 1 // fix WinXP
|
#define PSAPI_VERSION 1 // fix WinXP
|
||||||
//#define Q_NO_TEMPLATE_FRIENDS // fix some compiler difference issues
|
//#define Q_NO_TEMPLATE_FRIENDS // fix some compiler difference issues
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
|
|
|
@ -22,8 +22,6 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 };
|
uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 };
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#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() {
|
bool checkms() {
|
||||||
int64 unixms = (myunixtime() - _timeStart) * 1000LL + _msAddToUnixtime;
|
int64 unixms = (myunixtime() - _timeStart) * 1000LL + _msAddToUnixtime;
|
||||||
int64 ms = int64(getms(true));
|
int64 ms = int64(getms(true));
|
||||||
|
|
|
@ -143,8 +143,6 @@ inline void mylocaltime(struct tm * _Tm, const time_t * _Time) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void installSignalHandlers();
|
|
||||||
|
|
||||||
namespace ThirdParty {
|
namespace ThirdParty {
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
|
Loading…
Reference in New Issue