backtrace.c 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /* Return backtrace of current program state.
  2. Copyright (C) 2008-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library. If not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <execinfo.h>
  16. #include <stdlib.h>
  17. #include <unwind-link.h>
  18. struct trace_arg
  19. {
  20. void **array;
  21. struct unwind_link *unwind_link;
  22. int cnt, size;
  23. };
  24. #ifdef SHARED
  25. /* This function is identical to "_Unwind_GetGR", except that it uses
  26. "unwind_vrs_get" instead of "_Unwind_VRS_Get". */
  27. static inline _Unwind_Word
  28. unwind_getgr (struct unwind_link *unwind_link,
  29. _Unwind_Context *context, int regno)
  30. {
  31. _uw val;
  32. UNWIND_LINK_PTR (unwind_link, _Unwind_VRS_Get)
  33. (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
  34. return val;
  35. }
  36. /* This macro is identical to the _Unwind_GetIP macro, except that it
  37. uses "unwind_getgr" instead of "_Unwind_GetGR". */
  38. #define unwind_getip(context) \
  39. (unwind_getgr (arg->unwind_link, context, 15) & ~(_Unwind_Word)1)
  40. #else /* !SHARED */
  41. # define unwind_getip _Unwind_GetIP
  42. #endif
  43. static _Unwind_Reason_Code
  44. backtrace_helper (struct _Unwind_Context *ctx, void *a)
  45. {
  46. struct trace_arg *arg = a;
  47. /* We are first called with address in the __backtrace function.
  48. Skip it. */
  49. if (arg->cnt != -1)
  50. arg->array[arg->cnt] = (void *) unwind_getip (ctx);
  51. if (++arg->cnt == arg->size)
  52. return _URC_END_OF_STACK;
  53. return _URC_NO_REASON;
  54. }
  55. int
  56. __backtrace (void **array, int size)
  57. {
  58. struct trace_arg arg =
  59. {
  60. .array = array,
  61. .unwind_link = __libc_unwind_link_get (),
  62. .size = size,
  63. .cnt = -1
  64. };
  65. if (size <= 0 || arg.unwind_link == NULL)
  66. return 0;
  67. UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
  68. (backtrace_helper, &arg);
  69. if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
  70. --arg.cnt;
  71. return arg.cnt != -1 ? arg.cnt : 0;
  72. }
  73. weak_alias (__backtrace, backtrace)
  74. libc_hidden_def (__backtrace)