diff options
author | Gregory LEOCADIE <gregory.leocadie@datadoghq.com> | 2022-09-21 21:25:31 +0200 |
---|---|---|
committer | Dave Watson <dade.watson@gmail.com> | 2023-01-11 08:56:12 -0800 |
commit | 4fdee8080912fe6dd76e98526457125e9ee8ec03 (patch) | |
tree | 091bf806fb79e9a3b1a9fd880f3202765d64f806 | |
parent | 3adec79a2a8be71ed384096dda7f00b143cc47f7 (diff) | |
download | libunwind-4fdee8080912fe6dd76e98526457125e9ee8ec03.tar.gz |
Add unw_backtrace2 implementation
-rw-r--r-- | include/libunwind-common.h.in | 1 | ||||
-rw-r--r-- | src/mi/backtrace.c | 33 |
2 files changed, 31 insertions, 3 deletions
diff --git a/include/libunwind-common.h.in b/include/libunwind-common.h.in index 9d62aa91..3f04a1c4 100644 --- a/include/libunwind-common.h.in +++ b/include/libunwind-common.h.in @@ -316,5 +316,6 @@ extern int unw_get_proc_name_by_ip (unw_addr_space_t, unw_word_t, char *, size_t, unw_word_t *, void *); extern const char *unw_strerror (int); extern int unw_backtrace (void **, int); +extern int unw_backtrace2 (void **, int, unw_context_t*); extern unw_addr_space_t unw_local_addr_space; diff --git a/src/mi/backtrace.c b/src/mi/backtrace.c index b2815137..b6c7457f 100644 --- a/src/mi/backtrace.c +++ b/src/mi/backtrace.c @@ -33,15 +33,16 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* See glibc manual for a description of this function. */ static ALWAYS_INLINE int -slow_backtrace (void **buffer, int size, unw_context_t *uc) +slow_backtrace (void **buffer, int size, unw_context_t *uc, int flag) { unw_cursor_t cursor; unw_word_t ip; int n = 0; - if (unlikely (unw_init_local (&cursor, uc) < 0)) + if (unlikely (unw_init_local2 (&cursor, uc, flag) < 0)) return 0; + while (unw_step (&cursor) > 0) { if (n >= size) @@ -69,7 +70,33 @@ unw_backtrace (void **buffer, int size) if (unlikely (tdep_trace (&cursor, buffer, &n) < 0)) { unw_getcontext (&uc); - return slow_backtrace (buffer, size, &uc); + return slow_backtrace (buffer, size, &uc, 0); + } + + return n; +} + +int +unw_backtrace2 (void **buffer, int size, unw_context_t* uc2) +{ + if (size == 0) + return 0; + + if (uc2 == NULL) + return unw_backtrace(buffer, size); + + unw_cursor_t cursor; + // need to copy, because the context will be modified by tdep_trace + unw_context_t uc = *(unw_context_t*)uc2; + + if (unlikely (unw_init_local2 (&cursor, &uc, UNW_INIT_SIGNAL_FRAME) < 0)) + return 0; + + int n = size; + + if (unlikely (tdep_trace (&cursor, buffer, &n) < 0)) + { + return slow_backtrace (buffer, n, &uc, UNW_INIT_SIGNAL_FRAME); } return n; |