BsLinuxCrashHandler.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Prerequisites/BsPrerequisitesUtil.h"
  4. #include "Debug/BsDebug.h"
  5. #include "FileSystem/BsFileSystem.h"
  6. #include <cxxabi.h>
  7. #include <execinfo.h>
  8. #include <ctime>
  9. #include <sstream>
  10. #include <csignal>
  11. namespace bs
  12. {
  13. CrashHandler::CrashHandler() {}
  14. CrashHandler::~CrashHandler() {}
  15. String CrashHandler::getCrashTimestamp()
  16. {
  17. std::time_t t = time(0);
  18. struct tm *now = localtime(&t);
  19. String timeStamp = "{0}{1}{2}_{3}{4}";
  20. String strYear = toString(now->tm_year, 4, '0');
  21. String strMonth = toString(now->tm_mon, 2, '0');
  22. String strDay = toString(now->tm_mday, 2, '0');
  23. String strHour = toString(now->tm_hour, 2, '0');
  24. String strMinute = toString(now->tm_min, 2, '0');
  25. return StringUtil::format(timeStamp, strYear, strMonth, strDay, strHour, strMinute);
  26. }
  27. String CrashHandler::getStackTrace()
  28. {
  29. StringStream stackTrace;
  30. void *trace[BS_MAX_STACKTRACE_DEPTH];
  31. int trace_size = backtrace(trace, BS_MAX_STACKTRACE_DEPTH);
  32. char **messages = backtrace_symbols(trace, trace_size);
  33. // Most lines returned by backtrace_symbols() look like this:
  34. //
  35. // <path/to/binary>(mangled_symbol+offset) [address]
  36. //
  37. // For those lines, we demangle the symbol with abi::__cxa_demangle(),
  38. // others are good as is.
  39. for (int i = 0; i < trace_size && messages != NULL; ++i)
  40. {
  41. // Try to find the characters surrounding the mangled name: '(' and '+'
  42. char *mangled_name = NULL, *offset_begin = NULL, *offset_end = NULL;
  43. for (char *p = messages[i]; *p; ++p)
  44. {
  45. if (*p == '(')
  46. mangled_name = p;
  47. else if (*p == '+')
  48. offset_begin = p;
  49. else if (*p == ')') {
  50. offset_end = p;
  51. break;
  52. }
  53. }
  54. bool lineContainsMangledSymbol = mangled_name != NULL
  55. && offset_begin != NULL
  56. && offset_end != NULL
  57. && mangled_name < offset_begin;
  58. stackTrace << toString(i) << ") ";
  59. if (lineContainsMangledSymbol)
  60. {
  61. *mangled_name++ = '\0';
  62. *offset_begin++ = '\0';
  63. *offset_end++ = '\0';
  64. int status;
  65. char *real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
  66. char *output_name = status == 0 /* Demangling successful */? real_name : mangled_name;
  67. stackTrace << String(messages[i])
  68. << ": " << output_name
  69. << "+" << offset_begin << offset_end;
  70. free(real_name);
  71. }
  72. else
  73. stackTrace << String(messages[i]);
  74. if (i < trace_size - 1)
  75. stackTrace << "\n";
  76. }
  77. free(messages);
  78. return stackTrace.str();
  79. }
  80. void CrashHandler::reportCrash(const String& type,
  81. const String& description,
  82. const String& function,
  83. const String& file,
  84. UINT32 line) const
  85. {
  86. logErrorAndStackTrace(type, description, function, file, line);
  87. saveCrashLog();
  88. // Allow the debugger a chance to attach
  89. std::raise(SIGINT);
  90. }
  91. }