libunwind.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #ifndef LIBUNWIND_H
  7. #define LIBUNWIND_H
  8. #include "sdkconfig.h"
  9. #include <stddef.h>
  10. #include <stdint.h>
  11. #if CONFIG_IDF_TARGET_ARCH_RISCV
  12. #include "libunwind-riscv.h"
  13. #elif CONFIG_IDF_TARGET_X86
  14. #include "libunwind-x86.h"
  15. #else
  16. /* This header must be a standalone one, so, it shall not trigger an error when
  17. * pre-processed without including any of the architecture header above.
  18. * The implementation can trigger a compile error if UNW_UNKNOWN_TARGET
  19. * macro is defined. */
  20. #define UNW_UNKNOWN_TARGET 1
  21. typedef void* ExecutionFrame;
  22. #endif
  23. #ifdef __cplusplus
  24. extern "C" {
  25. #endif
  26. /* Error codes returned by the functions defined below */
  27. #define UNW_ESUCCESS 0
  28. #define UNW_EUNSPEC 1 /* General failure */
  29. #define UNW_EBADREG 3 /* Register given is wrong */
  30. #define UNW_ESTOPUNWIND 5
  31. #define UNW_EINVAL 8 /* Bad parameter or unimplemented operation */
  32. #define UNW_EBADVERSION 9
  33. #define UNW_ENOINFO 10
  34. /* A libunwind context is the equivalent of an ESP-IDF ExecutionFrame */
  35. typedef ExecutionFrame unw_context_t;
  36. /* A register number is an unsigned word in our case */
  37. typedef uint32_t unw_regnum_t;
  38. /* In our current implementation, a cursor is the same as a context */
  39. typedef unw_context_t unw_cursor_t;
  40. /* long should represent the size of a CPU register */
  41. typedef unsigned long unw_word_t;
  42. /* At the moment, we don't support the operations using the following types,
  43. * so just set them to void* */
  44. typedef void* unw_addr_space_t;
  45. typedef void* unw_fpreg_t;
  46. /**
  47. * @brief Get the current CPU context.
  48. *
  49. * @param[out] ctx Pointer to `unw_context_t` structure. It must not be NULL
  50. * as it will be filled with the CPU registers value
  51. *
  52. * @return UNW_ESUCCESS on success, -UNW_EUNSPEC if ctx is NULL
  53. *
  54. * @note This function MUST be inlined. Marking it as "static inline" or
  55. * __attribute__((always_inline)) does not guarantee that it will inlined by
  56. * the compiler for all the architectures. Thus, define this function as a macro.
  57. * @note If the caller of this function returns, all the pointers, contexts, cursors
  58. * generated out of the initial returned context shall be considered invalid and
  59. * thus, must **not** be used.
  60. */
  61. #define unw_getcontext(ctx) ({ int retval; \
  62. if (ctx == NULL) { \
  63. retval = -UNW_EUNSPEC; \
  64. } else { \
  65. UNW_GET_CONTEXT(ctx); \
  66. retval = UNW_ESUCCESS; \
  67. } \
  68. retval; \
  69. })
  70. /**
  71. * @brief Initialize a cursor on a local context. Multiple cursor can be initialized on
  72. * a given CPU context, they can then be manipulated independently.
  73. *
  74. * @param[out] c Pointer on cursor to be returned. Must not be NULL
  75. * @param[in] ctx Pointer on the context returned by the function `unw_getcontext`
  76. *
  77. * @return UNW_ESUCCESS on success, -UNW_EUNSPEC if one of the parameter is NULL.
  78. */
  79. int unw_init_local(unw_cursor_t* c, unw_context_t* ctx);
  80. /**
  81. * @brief Perform a step "up" on the given cursor. After calling this function, the
  82. * cursor will point to the caller's CPU context. Thus, it is then possible
  83. * to retrieve the caller's address by getting the PC register out of the cursor.
  84. * Check `unw_get_reg` function for this.
  85. *
  86. * @param[in] cp Current cursor
  87. *
  88. * @returns 0 if the previous frame was the last one
  89. * @returns Positive value on success
  90. * @returns -UNW_EBADVERSION if the DWARF information's version is not compatible with the eh_frame_parser implementation
  91. * @returns -UNW_ENOINFO if the caller information are not present in the binary. (if the caller is in ROM for example)
  92. * @returns -UNW_ESTOPUNWIND if unwinding is terminated
  93. */
  94. int unw_step(unw_cursor_t* cp);
  95. /**
  96. * @brief Get the value of a CPU register from a given cursor.
  97. *
  98. * @param[in] cp Pointer to the cursor
  99. * @param reg Register number to retrieve the value of
  100. * @param[out] valp Pointer that will be filled with the register value
  101. *
  102. * @returns UNW_ESUCCESS on success
  103. * @returns -UNW_EUNSPEC if any pointer passed is NULL
  104. * @returns -UNW_EBADREG if the register number is invalid
  105. */
  106. int unw_get_reg(unw_cursor_t* cp, unw_regnum_t reg, unw_word_t* valp);
  107. /**
  108. * @brief Set the value of a CPU register in a given cursor.
  109. *
  110. * @param[in]cp Pointer to the cursor
  111. * @param reg Register number to set the value of
  112. * @param val New register value
  113. *
  114. * @returns UNW_ESUCCESS on success
  115. * @returns -UNW_EUNSPEC if the pointer passed is NULL
  116. * @returns -UNW_EBADREG if the register number is invalid
  117. */
  118. int unw_set_reg(unw_cursor_t* cp, unw_regnum_t reg, unw_word_t val);
  119. #endif // LIBUNWIND_H