stacktrace_linux.cpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /*
  2. * Copyright (c) 2012-2015 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 "macros.h"
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <cxxabi.h>
  11. #include <execinfo.h>
  12. #include <string.h> // strchr
  13. #include <unistd.h> // getpid
  14. namespace crown
  15. {
  16. const char* addr2line(const char* addr, char* line, int len)
  17. {
  18. char buf[256];
  19. snprintf(buf, sizeof(buf), "addr2line -e /proc/%u/exe %s", getpid(), addr);
  20. FILE* f = popen(buf, "r");
  21. if (f)
  22. {
  23. fgets(line, len, f);
  24. line[strlen32(line) - 1] = '\0';
  25. pclose(f);
  26. return line;
  27. }
  28. return "<addr2line missing>";
  29. }
  30. void print_callstack()
  31. {
  32. void* array[64];
  33. int size = backtrace(array, CE_COUNTOF(array));
  34. char** messages = backtrace_symbols(array, size);
  35. // skip first stack frame (points here)
  36. for (int i = 1; i < size && messages != NULL; ++i)
  37. {
  38. char* msg = messages[i];
  39. char* mangled_name = strchr(msg, '(');
  40. char* offset_begin = strchr(msg, '+');
  41. char* offset_end = strchr(msg, ')');
  42. char* addr_begin = strchr(msg, '[');
  43. char* addr_end = strchr(msg, ']');
  44. // if the line could be processed, attempt to demangle the symbol
  45. if (mangled_name && offset_begin && offset_end && mangled_name < offset_begin)
  46. {
  47. *mangled_name++ = '\0';
  48. *offset_begin++ = '\0';
  49. *offset_end++ = '\0';
  50. *addr_begin++ = '\0';
  51. *addr_end++ = '\0';
  52. int demangle_ok;
  53. char* real_name = abi::__cxa_demangle(mangled_name, 0, 0, &demangle_ok);
  54. char line[256];
  55. memset(line, 0, sizeof(line));
  56. printf("\t[%d] %s: (%s)+%s in %s\n"
  57. , i
  58. , msg
  59. , (demangle_ok == 0 ? real_name : mangled_name)
  60. , offset_begin
  61. , addr2line(addr_begin, line, sizeof(line))
  62. );
  63. free(real_name);
  64. }
  65. // otherwise, print the whole line
  66. else
  67. {
  68. printf("\t[%d] %s\n", i, msg);
  69. }
  70. }
  71. free(messages);
  72. }
  73. } // namespace crown
  74. #endif // CROWN_PLATFORM_LINUX && CROWN_COMPILER_GCC