|
@@ -6,74 +6,129 @@
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
+#include <AzCore/Debug/TraceMessageBus.h>
|
|
#include <AzCore/IO/SystemFile.h>
|
|
#include <AzCore/IO/SystemFile.h>
|
|
#include <AzCore/std/string/string_view.h>
|
|
#include <AzCore/std/string/string_view.h>
|
|
|
|
|
|
#include <ctype.h>
|
|
#include <ctype.h>
|
|
|
|
+#include <execinfo.h>
|
|
#include <signal.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
#include <unistd.h>
|
|
|
|
|
|
-namespace AZ::Debug::Platform
|
|
|
|
|
|
+namespace AZ::Debug
|
|
{
|
|
{
|
|
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
|
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
|
- bool performDebuggerDetection()
|
|
|
|
|
|
+ void ExceptionHandler(int signal);
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ constexpr int MaxMessageLength = 4096;
|
|
|
|
+ constexpr int MaxStackLines = 100;
|
|
|
|
+
|
|
|
|
+ namespace Platform
|
|
{
|
|
{
|
|
- AZ::IO::SystemFile processStatusFile;
|
|
|
|
- if (!processStatusFile.Open("/proc/self/status", AZ::IO::SystemFile::SF_OPEN_READ_ONLY))
|
|
|
|
|
|
+#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
|
|
|
+ bool performDebuggerDetection()
|
|
{
|
|
{
|
|
|
|
+ AZ::IO::SystemFile processStatusFile;
|
|
|
|
+ if (!processStatusFile.Open("/proc/self/status", AZ::IO::SystemFile::SF_OPEN_READ_ONLY))
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ char buffer[4096];
|
|
|
|
+ AZ::IO::SystemFile::SizeType numRead = processStatusFile.Read(sizeof(buffer), buffer);
|
|
|
|
+
|
|
|
|
+ const AZStd::string_view processStatusView(buffer, buffer + numRead);
|
|
|
|
+ constexpr AZStd::string_view tracerPidString = "TracerPid:";
|
|
|
|
+ const size_t tracerPidOffset = processStatusView.find(tracerPidString);
|
|
|
|
+ if (tracerPidOffset == AZStd::string_view::npos)
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ for (size_t i = tracerPidOffset + tracerPidString.length(); i < numRead; ++i)
|
|
|
|
+ {
|
|
|
|
+ if (!::isspace(processStatusView[i]))
|
|
|
|
+ {
|
|
|
|
+ return processStatusView[i] != '0';
|
|
|
|
+ }
|
|
|
|
+ }
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
- char buffer[4096];
|
|
|
|
- AZ::IO::SystemFile::SizeType numRead = processStatusFile.Read(sizeof(buffer), buffer);
|
|
|
|
|
|
+ bool IsDebuggerPresent()
|
|
|
|
+ {
|
|
|
|
+ static bool s_detectionPerformed = false;
|
|
|
|
+ static bool s_debuggerDetected = false;
|
|
|
|
+ if (!s_detectionPerformed)
|
|
|
|
+ {
|
|
|
|
+ s_debuggerDetected = performDebuggerDetection();
|
|
|
|
+ s_detectionPerformed = true;
|
|
|
|
+ }
|
|
|
|
+ return s_debuggerDetected;
|
|
|
|
+ }
|
|
|
|
|
|
- const AZStd::string_view processStatusView(buffer, buffer + numRead);
|
|
|
|
- constexpr AZStd::string_view tracerPidString = "TracerPid:";
|
|
|
|
- const size_t tracerPidOffset = processStatusView.find(tracerPidString);
|
|
|
|
- if (tracerPidOffset == AZStd::string_view::npos)
|
|
|
|
|
|
+ bool AttachDebugger()
|
|
{
|
|
{
|
|
|
|
+ // Not supported yet
|
|
|
|
+ AZ_Assert(false, "AttachDebugger() is not supported for Unix platform yet");
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
- for (size_t i = tracerPidOffset + tracerPidString.length(); i < numRead; ++i)
|
|
|
|
|
|
+
|
|
|
|
+ void SignalHandler(int handler)
|
|
|
|
+ {
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void HandleExceptions(bool isEnabled)
|
|
{
|
|
{
|
|
- if (!::isspace(processStatusView[i]))
|
|
|
|
|
|
+ if (isEnabled)
|
|
{
|
|
{
|
|
- return processStatusView[i] != '0';
|
|
|
|
|
|
+ signal(SIGSEGV, ExceptionHandler);
|
|
|
|
+ signal(SIGTRAP, ExceptionHandler);
|
|
|
|
+ signal(SIGILL, ExceptionHandler);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ signal(SIGSEGV, SIG_DFL);
|
|
|
|
+ signal(SIGTRAP, SIG_DFL);
|
|
|
|
+ signal(SIGILL, SIG_DFL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
|
|
- bool IsDebuggerPresent()
|
|
|
|
- {
|
|
|
|
- static bool s_detectionPerformed = false;
|
|
|
|
- static bool s_debuggerDetected = false;
|
|
|
|
- if (!s_detectionPerformed)
|
|
|
|
|
|
+ void DebugBreak()
|
|
{
|
|
{
|
|
- s_debuggerDetected = performDebuggerDetection();
|
|
|
|
- s_detectionPerformed = true;
|
|
|
|
|
|
+ raise(SIGINT);
|
|
}
|
|
}
|
|
- return s_debuggerDetected;
|
|
|
|
- }
|
|
|
|
|
|
+#endif // AZ_ENABLE_DEBUG_TOOLS
|
|
|
|
|
|
- bool AttachDebugger()
|
|
|
|
|
|
+ void Terminate(int exitCode)
|
|
|
|
+ {
|
|
|
|
+ _exit(exitCode);
|
|
|
|
+ }
|
|
|
|
+ } // namespace Platform
|
|
|
|
+
|
|
|
|
+#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
|
|
|
+ void ExceptionHandler(int signal)
|
|
{
|
|
{
|
|
- // Not supported yet
|
|
|
|
- AZ_Assert(false, "AttachDebugger() is not supported for Unix platform yet");
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ char message[MaxMessageLength];
|
|
|
|
+ Debug::Trace::Instance().Output(nullptr, "==================================================================\n");
|
|
|
|
+ azsnprintf(message, MaxMessageLength, "Error: signal %s: \n", strsignal(signal));
|
|
|
|
+ Debug::Trace::Instance().Output(nullptr, message);
|
|
|
|
|
|
- void HandleExceptions(bool)
|
|
|
|
- {}
|
|
|
|
|
|
+ void* buffers[MaxStackLines];
|
|
|
|
+ int numberBacktraceStrings = backtrace(buffers, MaxStackLines);
|
|
|
|
+ char** backtraceResults = backtrace_symbols(buffers, numberBacktraceStrings);
|
|
|
|
+ if (backtraceResults == nullptr)
|
|
|
|
+ {
|
|
|
|
+ Debug::Trace::Instance().Output(nullptr, "==================================================================\n");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ for (int j = 0; j < numberBacktraceStrings; j++)
|
|
|
|
+ {
|
|
|
|
+ Debug::Trace::Instance().Output(nullptr, backtraceResults[j]);
|
|
|
|
+ }
|
|
|
|
|
|
- void DebugBreak()
|
|
|
|
- {
|
|
|
|
- raise(SIGINT);
|
|
|
|
|
|
+ Debug::Trace::Instance().Output(nullptr, "==================================================================\n");
|
|
}
|
|
}
|
|
-#endif // AZ_ENABLE_DEBUG_TOOLS
|
|
|
|
|
|
+#endif
|
|
|
|
|
|
- void Terminate(int exitCode)
|
|
|
|
- {
|
|
|
|
- _exit(exitCode);
|
|
|
|
- }
|
|
|
|
-} // namespace AZ::Debug::Platform
|
|
|
|
|
|
+} // namespace AZ::Debug
|