backtrace.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
  2. *
  3. * libgearman client library.
  4. *
  5. * Copyright (C) 2012 Data Differential, http://datadifferential.com/
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions are
  10. * met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above
  16. * copyright notice, this list of conditions and the following disclaimer
  17. * in the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * * The names of its contributors may not be used to endorse or
  21. * promote products derived from this software without specific prior
  22. * written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  27. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  28. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  29. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  30. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  31. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  32. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  33. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  34. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35. *
  36. */
  37. #include <config.h>
  38. #include <libgearman/common.h>
  39. #include <cstring>
  40. #include <cstdlib>
  41. #ifdef HAVE_EXECINFO_H
  42. #include <execinfo.h>
  43. #endif
  44. #ifdef HAVE_CXXABI_H
  45. #include <cxxabi.h>
  46. #endif
  47. #ifdef HAVE_GCC_ABI_DEMANGLE
  48. # define USE_DEMANGLE 1
  49. #else
  50. # define USE_DEMANGLE 0
  51. #endif
  52. void custom_backtrace(void)
  53. {
  54. #ifdef HAVE_EXECINFO_H
  55. void *array[50];
  56. size_t size= backtrace(array, 50);
  57. char **strings= backtrace_symbols(array, size);
  58. if (strings == NULL)
  59. {
  60. return;
  61. }
  62. fprintf(stderr, "Number of stack frames obtained: %lu\n", (unsigned long)size);
  63. char *named_function= (char *)::realloc(NULL, 1024);
  64. if (named_function == NULL)
  65. {
  66. ::free(strings);
  67. return;
  68. }
  69. for (size_t x= 1; x < size; x++)
  70. {
  71. if (USE_DEMANGLE)
  72. {
  73. size_t sz= 200;
  74. char *named_function_ptr= (char *)::realloc(named_function, sz);
  75. if (named_function_ptr == NULL)
  76. {
  77. continue;
  78. }
  79. named_function= named_function_ptr;
  80. char *begin_name= 0;
  81. char *begin_offset= 0;
  82. char *end_offset= 0;
  83. for (char *j= strings[x]; *j; ++j)
  84. {
  85. if (*j == '(')
  86. {
  87. begin_name= j;
  88. }
  89. else if (*j == '+')
  90. {
  91. begin_offset= j;
  92. }
  93. else if (*j == ')' and begin_offset)
  94. {
  95. end_offset= j;
  96. break;
  97. }
  98. }
  99. if (begin_name and begin_offset and end_offset and begin_name < begin_offset)
  100. {
  101. *begin_name++= '\0';
  102. *begin_offset++= '\0';
  103. *end_offset= '\0';
  104. int status;
  105. char *ret= abi::__cxa_demangle(begin_name, named_function, &sz, &status);
  106. if (ret) // realloc()'ed string
  107. {
  108. named_function= ret;
  109. fprintf(stderr, " %s : %s()+%s\n", strings[x], begin_name, begin_offset);
  110. }
  111. else
  112. {
  113. fprintf(stderr, " %s : %s()+%s\n", strings[x], begin_name, begin_offset);
  114. }
  115. }
  116. else
  117. {
  118. fprintf(stderr, " %s\n", strings[x]);
  119. }
  120. }
  121. else
  122. {
  123. fprintf(stderr, " unmangled: %s\n", strings[x]);
  124. }
  125. }
  126. ::free(named_function);
  127. ::free(strings);
  128. #endif // HAVE_EXECINFO_H
  129. }