From 2f76f9cf494744dc409dd2140bbbe96c6fd6286a Mon Sep 17 00:00:00 2001 From: Nikolaus Gullotta Date: Sun, 28 Jun 2020 20:31:24 -0500 Subject: [PATCH 1/3] Add simple stack trace on unhandled exception This leverages wxStackWalker and the OnFatalException handler to access frames and their associated data --- Source/Core/Core/CMakeLists.txt | 1 + Source/Core/Core/Debugger/StackWalker.cpp | 61 +++++++++++++++++++++++ Source/Core/Core/Debugger/StackWalker.h | 25 ++++++++++ Source/Core/Core/Slippi/SlippiUser.cpp | 4 ++ Source/Core/DolphinWX/Main.cpp | 3 ++ 5 files changed, 94 insertions(+) create mode 100644 Source/Core/Core/Debugger/StackWalker.cpp create mode 100644 Source/Core/Core/Debugger/StackWalker.h diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index ffaa683ae4..9362e686ce 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -25,6 +25,7 @@ set(SRCS ActionReplay.cpp Debugger/Debugger_SymbolMap.cpp Debugger/Dump.cpp Debugger/PPCDebugInterface.cpp + Debugger/StackWalker.cpp DSP/DSPAssembler.cpp DSP/DSPDisassembler.cpp DSP/DSPAccelerator.cpp diff --git a/Source/Core/Core/Debugger/StackWalker.cpp b/Source/Core/Core/Debugger/StackWalker.cpp new file mode 100644 index 0000000000..88c3668804 --- /dev/null +++ b/Source/Core/Core/Debugger/StackWalker.cpp @@ -0,0 +1,61 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include +#include + +#include "Common/CommonPaths.h" +#include "Common/FileUtil.h" +#include "Common/StringUtil.h" +#include "Core/Debugger/StackWalker.h" + + +StackWalker::StackWalker(bool log) + : _log(log) +{ +#if defined(__APPLE__) + std::string path = File::GetBundleDirectory() + "/Contents/Resources"; +#elif defined(_WIN32) + std::string path = File::GetExeDirectory(); +#else + std::string path = File::GetSysDirectory(); +#endif + + int timestamp = std::time(0); + path = StringFromFormat("%s%d.txt", path.c_str(), timestamp); + + if (_log) + { + printf("%s\n", path.c_str()); + File::CreateEmptyFile(path); + log_file = File::IOFile(path, "wb"); + } +} + + +void StackWalker::OnStackFrame(const wxStackFrame& frame) +{ + const std::string head = StringFromFormat( + "Frame@ %p\n", + frame.GetAddress() + ); + + const std::string body = StringFromFormat( + "%lu %lu %s %s %s\n", + frame.GetLine(), + frame.GetLevel(), + frame.GetFileName().c_str().AsChar(), + frame.GetModule().c_str().AsChar(), + frame.GetName().c_str().AsChar() + ); + + if (_log) { + log_file.WriteBytes(head.data(), head.length()); + log_file.WriteBytes(body.data(), body.length()); + } + + // To stdout as well + printf("%s%s", head.c_str(), body.c_str()); +} \ No newline at end of file diff --git a/Source/Core/Core/Debugger/StackWalker.h b/Source/Core/Core/Debugger/StackWalker.h new file mode 100644 index 0000000000..c2e36fe5c9 --- /dev/null +++ b/Source/Core/Core/Debugger/StackWalker.h @@ -0,0 +1,25 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include + +#include "Common/FileUtil.h" + +class StackWalker : public wxStackWalker +{ + public: + StackWalker(bool); + ~StackWalker() { log_file.Close(); }; + + const File::IOFile& get_log_file() { return log_file; }; + bool will_write() {return _log; }; + + protected: + void OnStackFrame(const wxStackFrame&); + + private: + File::IOFile log_file; + bool _log; +}; diff --git a/Source/Core/Core/Slippi/SlippiUser.cpp b/Source/Core/Core/Slippi/SlippiUser.cpp index 7b1071361b..823383d573 100644 --- a/Source/Core/Core/Slippi/SlippiUser.cpp +++ b/Source/Core/Core/Slippi/SlippiUser.cpp @@ -65,6 +65,10 @@ bool SlippiUser::AttemptLogin() { std::string userFilePath = getUserFilePath(); + // Crash this bitch + std::string* foo = nullptr; + foo->resize(69); + INFO_LOG(SLIPPI_ONLINE, "Looking for file at: %s", userFilePath.c_str()); { diff --git a/Source/Core/DolphinWX/Main.cpp b/Source/Core/DolphinWX/Main.cpp index 0a7a4cd8b2..0b4930197c 100644 --- a/Source/Core/DolphinWX/Main.cpp +++ b/Source/Core/DolphinWX/Main.cpp @@ -38,6 +38,7 @@ #include "Core/HW/Wiimote.h" #include "Core/Host.h" #include "Core/Movie.h" +#include "Core/Debugger/StackWalker.h" #include "DolphinWX/Debugger/CodeWindow.h" #include "DolphinWX/Debugger/JitWindow.h" @@ -473,6 +474,8 @@ int DolphinApp::OnExit() void DolphinApp::OnFatalException() { + StackWalker walker (true); + walker.WalkFromException(); WiimoteReal::Shutdown(); } From c75f46f7dead66b7a7bb4492d83c135fcbdf14bf Mon Sep 17 00:00:00 2001 From: Nikolaus Gullotta Date: Sun, 28 Jun 2020 20:34:50 -0500 Subject: [PATCH 2/3] Stop crashing the program intentionally --- Source/Core/Core/Slippi/SlippiUser.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Source/Core/Core/Slippi/SlippiUser.cpp b/Source/Core/Core/Slippi/SlippiUser.cpp index 823383d573..7b1071361b 100644 --- a/Source/Core/Core/Slippi/SlippiUser.cpp +++ b/Source/Core/Core/Slippi/SlippiUser.cpp @@ -65,10 +65,6 @@ bool SlippiUser::AttemptLogin() { std::string userFilePath = getUserFilePath(); - // Crash this bitch - std::string* foo = nullptr; - foo->resize(69); - INFO_LOG(SLIPPI_ONLINE, "Looking for file at: %s", userFilePath.c_str()); { From 9500da911d8e618e1ce9b894c0db0a5781dbae1a Mon Sep 17 00:00:00 2001 From: Nikolaus Gullotta Date: Tue, 30 Jun 2020 21:09:33 -0500 Subject: [PATCH 3/3] Always ensure that path ends with a directory seperator On windows, it can be the case, that the path returned by File::GetExeDirectory does not end in a directory seperator This will *hopefully* ensure that this is not the case --- Source/Core/Core/Debugger/StackWalker.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/Core/Core/Debugger/StackWalker.cpp b/Source/Core/Core/Debugger/StackWalker.cpp index 88c3668804..954c706724 100644 --- a/Source/Core/Core/Debugger/StackWalker.cpp +++ b/Source/Core/Core/Debugger/StackWalker.cpp @@ -22,8 +22,15 @@ StackWalker::StackWalker(bool log) #else std::string path = File::GetSysDirectory(); #endif + + // This conversion is necessary for *reasons* + char sep = DIR_SEP_CHR; + if (path.back() != sep) { + path.push_back(sep); + } int timestamp = std::time(0); + path = StringFromFormat("%s%d.txt", path.c_str(), timestamp); if (_log)