blob: e366abfbab1792e990273df29b5ac310a73c0449 (
plain) (
tree)
|
|
/* See LICENSE file for copyright and license details. */
#include "internal.h"
#define UNW_LOCAL_ONLY
#include <libunwind.h>
struct partial {
uintptr_t rips[8];
struct partial *next;
};
int
liberror_save_backtrace(struct liberror_error *error)
{
struct liberror_backtrace *backtrace = NULL;
unw_word_t rip;
unw_cursor_t cursor;
unw_context_t context;
size_t i = 0;
struct partial *current, head;
int saved_errno = errno;
int ret = -1;
if (unw_getcontext(&context))
goto out;
if (unw_init_local(&cursor, &context))
goto out;
current = &head;
for (; unw_step(&cursor) > 0; i++) {
if (!(i & 7))
current = current->next = alloca(sizeof(*current));
if (unw_get_reg(&cursor, UNW_REG_IP, &rip))
goto out;
current->rips[i & 7] = (uintptr_t)rip;
}
backtrace = malloc(offsetof(struct liberror_backtrace, rips) + i * sizeof(*backtrace->rips));
if (!backtrace)
goto out;
backtrace->refcount = 1;
backtrace->n = i;
current = &head;
for (i = 0; i < backtrace->n; i++) {
if (!(i & 7))
current = current->next;
backtrace->rips[i] = current->rips[i & 7];
}
ret = 0;
out:
if (error->backtrace && !--error->backtrace->refcount)
free(error->backtrace);
error->backtrace = backtrace;
errno = saved_errno;
return ret;
}
|