stacktrace_linux.cpp 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*
  2. * Copyright (c) 2012-2014 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #include "config.h"
  6. #if CROWN_PLATFORM_LINUX && CROWN_COMPILER_GCC
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <cxxabi.h>
  10. #include <execinfo.h>
  11. namespace crown
  12. {
  13. void stacktrace()
  14. {
  15. void* array[50];
  16. int size = backtrace(array, 50);
  17. char** messages = backtrace_symbols(array, size);
  18. // skip first stack frame (points here)
  19. for (int i = 1; i < size && messages != NULL; ++i)
  20. {
  21. char *mangled_name = 0, *offset_begin = 0, *offset_end = 0;
  22. // find parantheses and +address offset surrounding mangled name
  23. for (char *p = messages[i]; *p; ++p)
  24. {
  25. if (*p == '(')
  26. {
  27. mangled_name = p;
  28. }
  29. else if (*p == '+')
  30. {
  31. offset_begin = p;
  32. }
  33. else if (*p == ')')
  34. {
  35. offset_end = p;
  36. break;
  37. }
  38. }
  39. // if the line could be processed, attempt to demangle the symbol
  40. if (mangled_name && offset_begin && offset_end && mangled_name < offset_begin)
  41. {
  42. *mangled_name++ = '\0';
  43. *offset_begin++ = '\0';
  44. *offset_end++ = '\0';
  45. int status;
  46. char* real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
  47. printf("\t[%d] %s: (%s)+%s %s\n", i, messages[i], (status == 0 ? real_name : mangled_name), offset_begin, offset_end);
  48. free(real_name);
  49. }
  50. // otherwise, print the whole line
  51. else
  52. {
  53. printf("\t[%d] %s\n", i, messages[i]);
  54. }
  55. }
  56. free(messages);
  57. }
  58. } // namespace crown
  59. #endif // CROWN_PLATFORM_LINUX && CROWN_COMPILER_GCC