stack.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * stack related functions
  3. *
  4. * This code is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU Library General Public License version 2.
  6. */
  7. #include <libcflat.h>
  8. #include <stack.h>
  9. #define MAX_DEPTH 20
  10. static void print_stack(const void **return_addrs, int depth,
  11. bool top_is_return_address)
  12. {
  13. int i = 0;
  14. printf("\tSTACK:");
  15. /* @addr indicates a non-return address, as expected by the stack
  16. * pretty printer script. */
  17. if (depth > 0 && !top_is_return_address) {
  18. printf(" @%lx", (unsigned long) return_addrs[0]);
  19. i++;
  20. }
  21. for (; i < depth; i++) {
  22. printf(" %lx", (unsigned long) return_addrs[i]);
  23. }
  24. printf("\n");
  25. }
  26. void dump_stack(void)
  27. {
  28. const void *return_addrs[MAX_DEPTH];
  29. int depth;
  30. depth = backtrace(return_addrs, MAX_DEPTH);
  31. print_stack(&return_addrs[1], depth ? depth - 1 : 0, true);
  32. }
  33. void dump_frame_stack(const void *instruction, const void *frame)
  34. {
  35. const void *return_addrs[MAX_DEPTH];
  36. int depth;
  37. return_addrs[0] = instruction;
  38. depth = backtrace_frame(frame, &return_addrs[1], MAX_DEPTH - 1);
  39. print_stack(return_addrs, depth + 1, false);
  40. }
  41. #ifndef HAVE_ARCH_BACKTRACE
  42. int backtrace(const void **return_addrs, int max_depth)
  43. {
  44. static int walking;
  45. int depth = 0;
  46. void *addr;
  47. if (walking) {
  48. printf("RECURSIVE STACK WALK!!!\n");
  49. return 0;
  50. }
  51. walking = 1;
  52. /* __builtin_return_address requires a compile-time constant argument */
  53. #define GET_RETURN_ADDRESS(i) \
  54. if (max_depth == i) \
  55. goto done; \
  56. addr = __builtin_return_address(i); \
  57. if (!addr) \
  58. goto done; \
  59. return_addrs[i] = __builtin_extract_return_addr(addr); \
  60. depth = i + 1; \
  61. GET_RETURN_ADDRESS(0)
  62. GET_RETURN_ADDRESS(1)
  63. GET_RETURN_ADDRESS(2)
  64. GET_RETURN_ADDRESS(3)
  65. GET_RETURN_ADDRESS(4)
  66. GET_RETURN_ADDRESS(5)
  67. GET_RETURN_ADDRESS(6)
  68. GET_RETURN_ADDRESS(7)
  69. GET_RETURN_ADDRESS(8)
  70. GET_RETURN_ADDRESS(9)
  71. GET_RETURN_ADDRESS(10)
  72. GET_RETURN_ADDRESS(11)
  73. GET_RETURN_ADDRESS(12)
  74. GET_RETURN_ADDRESS(13)
  75. GET_RETURN_ADDRESS(14)
  76. GET_RETURN_ADDRESS(15)
  77. GET_RETURN_ADDRESS(16)
  78. GET_RETURN_ADDRESS(17)
  79. GET_RETURN_ADDRESS(18)
  80. GET_RETURN_ADDRESS(19)
  81. GET_RETURN_ADDRESS(20)
  82. #undef GET_RETURN_ADDRESS
  83. done:
  84. walking = 0;
  85. return depth;
  86. }
  87. #endif /* HAVE_ARCH_BACKTRACE */