2
0

BsUnixCrashHandler.cpp 3.1 KB

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