mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 09:20:25 +00:00
Merge pull request #3189 from opensourcerouting/libunwind
lib: add libunwind support for backtraces
This commit is contained in:
commit
20c11b1b96
@ -4,6 +4,7 @@ AUTOMAKE_OPTIONS = subdir-objects 1.12
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(UNWIND_CFLAGS) \
|
||||
$(SAN_FLAGS) \
|
||||
$(WERROR) \
|
||||
# end
|
||||
|
32
configure.ac
32
configure.ac
@ -958,10 +958,6 @@ case "$host_os" in
|
||||
AC_CHECK_LIB(socket, main)
|
||||
AC_CHECK_LIB(nsl, main)
|
||||
AC_CHECK_LIB(umem, main)
|
||||
AC_CHECK_FUNCS([printstack], [
|
||||
AC_DEFINE([HAVE_PRINTSTACK],1,[Solaris printstack])
|
||||
AC_DEFINE([HAVE_STACK_TRACE],1,[Stack symbols decode functionality])
|
||||
])
|
||||
CURSES=-lcurses
|
||||
SOLARIS="solaris"
|
||||
;;
|
||||
@ -1811,17 +1807,31 @@ dnl check for glibc 'backtrace'
|
||||
dnl ---------------------------
|
||||
if test x"${enable_backtrace}" != x"no" ; then
|
||||
backtrace_ok=no
|
||||
AC_CHECK_HEADER([execinfo.h], [
|
||||
AC_SEARCH_LIBS([backtrace], [execinfo], [
|
||||
AC_DEFINE(HAVE_GLIBC_BACKTRACE,,[Glibc backtrace])
|
||||
AC_DEFINE(HAVE_STACK_TRACE,,[Stack symbol decoding])
|
||||
backtrace_ok=yes
|
||||
],, [-lm])
|
||||
PKG_CHECK_MODULES([UNWIND], [libunwind], [
|
||||
AC_DEFINE(HAVE_LIBUNWIND, 1, [libunwind])
|
||||
backtrace_ok=yes
|
||||
], [
|
||||
case "$host_os" in
|
||||
sunos* | solaris2*)
|
||||
AC_CHECK_FUNCS([printstack], [
|
||||
AC_DEFINE([HAVE_PRINTSTACK], 1, [Solaris printstack])
|
||||
backtrace_ok=yes
|
||||
])
|
||||
;;
|
||||
esac
|
||||
if test "$backtrace_ok" = no; then
|
||||
AC_CHECK_HEADER([execinfo.h], [
|
||||
AC_SEARCH_LIBS([backtrace], [execinfo], [
|
||||
AC_DEFINE(HAVE_GLIBC_BACKTRACE, 1, [Glibc backtrace])
|
||||
backtrace_ok=yes
|
||||
],, [-lm])
|
||||
])
|
||||
fi
|
||||
])
|
||||
|
||||
if test x"${enable_backtrace}" = x"yes" -a x"${backtrace_ok}" = x"no"; then
|
||||
dnl user explicitly requested backtrace but we failed to find support
|
||||
AC_MSG_FAILURE([failed to find backtrace support])
|
||||
AC_MSG_FAILURE([failed to find backtrace or libunwind support])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
81
lib/log.c
81
lib/log.c
@ -38,6 +38,12 @@
|
||||
#include <ucontext.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBUNWIND
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
DEFINE_MTYPE_STATIC(LIB, ZLOG, "Logging")
|
||||
|
||||
static int logfile_fd = -1; /* Used in signal handler. */
|
||||
@ -313,7 +319,9 @@ static char *num_append(char *s, int len, unsigned long x)
|
||||
return str_append(s, len, t);
|
||||
}
|
||||
|
||||
#if defined(SA_SIGINFO) || defined(HAVE_STACK_TRACE)
|
||||
#if defined(SA_SIGINFO) \
|
||||
|| defined(HAVE_PRINTSTACK) \
|
||||
|| defined(HAVE_GLIBC_BACKTRACE)
|
||||
static char *hex_append(char *s, int len, unsigned long x)
|
||||
{
|
||||
char buf[30];
|
||||
@ -533,7 +541,37 @@ void zlog_signal(int signo, const char *action
|
||||
Needs to be enhanced to support syslog logging. */
|
||||
void zlog_backtrace_sigsafe(int priority, void *program_counter)
|
||||
{
|
||||
#ifdef HAVE_STACK_TRACE
|
||||
#ifdef HAVE_LIBUNWIND
|
||||
char buf[100];
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t uc;
|
||||
unw_word_t ip, off, sp;
|
||||
Dl_info dlinfo;
|
||||
|
||||
unw_getcontext(&uc);
|
||||
unw_init_local(&cursor, &uc);
|
||||
while (unw_step(&cursor) > 0) {
|
||||
char name[128] = "?";
|
||||
|
||||
unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||
unw_get_reg(&cursor, UNW_REG_SP, &sp);
|
||||
|
||||
if (unw_is_signal_frame(&cursor))
|
||||
dprintf(2, " ---- signal ----\n");
|
||||
|
||||
if (!unw_get_proc_name(&cursor, buf, sizeof(buf), &off)) {
|
||||
snprintf(name, sizeof(name), "%s+%#lx",
|
||||
buf, (long)off);
|
||||
}
|
||||
dprintf(2, "%-30s %16lx %16lx", name, (long)ip, (long)sp);
|
||||
if (dladdr((void *)ip, &dlinfo)) {
|
||||
dprintf(2, " %s (mapped at %p)",
|
||||
dlinfo.dli_fname, dlinfo.dli_fbase);
|
||||
}
|
||||
dprintf(2, "\n");
|
||||
|
||||
}
|
||||
#elif defined(HAVE_GLIBC_BACKTRACE) || defined(HAVE_PRINTSTACK)
|
||||
static const char pclabel[] = "Program counter: ";
|
||||
void *array[64];
|
||||
int size;
|
||||
@ -624,9 +662,38 @@ void zlog_backtrace_sigsafe(int priority, void *program_counter)
|
||||
|
||||
void zlog_backtrace(int priority)
|
||||
{
|
||||
#ifndef HAVE_GLIBC_BACKTRACE
|
||||
zlog(priority, "No backtrace available on this platform.");
|
||||
#else
|
||||
#ifdef HAVE_LIBUNWIND
|
||||
char buf[100];
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t uc;
|
||||
unw_word_t ip, off, sp;
|
||||
Dl_info dlinfo;
|
||||
|
||||
unw_getcontext(&uc);
|
||||
unw_init_local(&cursor, &uc);
|
||||
zlog(priority, "Backtrace:");
|
||||
while (unw_step(&cursor) > 0) {
|
||||
char name[128] = "?";
|
||||
|
||||
unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||
unw_get_reg(&cursor, UNW_REG_SP, &sp);
|
||||
|
||||
if (unw_is_signal_frame(&cursor))
|
||||
zlog(priority, " ---- signal ----");
|
||||
|
||||
if (!unw_get_proc_name(&cursor, buf, sizeof(buf), &off))
|
||||
snprintf(name, sizeof(name), "%s+%#lx",
|
||||
buf, (long)off);
|
||||
|
||||
if (dladdr((void *)ip, &dlinfo))
|
||||
zlog(priority, "%-30s %16lx %16lx %s (mapped at %p)",
|
||||
name, (long)ip, (long)sp,
|
||||
dlinfo.dli_fname, dlinfo.dli_fbase);
|
||||
else
|
||||
zlog(priority, "%-30s %16lx %16lx",
|
||||
name, (long)ip, (long)sp);
|
||||
}
|
||||
#elif defined(HAVE_GLIBC_BACKTRACE)
|
||||
void *array[20];
|
||||
int size, i;
|
||||
char **strings;
|
||||
@ -651,7 +718,9 @@ void zlog_backtrace(int priority)
|
||||
zlog(priority, "[bt %d] %s", i, strings[i]);
|
||||
free(strings);
|
||||
}
|
||||
#endif /* HAVE_GLIBC_BACKTRACE */
|
||||
#else /* !HAVE_GLIBC_BACKTRACE && !HAVE_LIBUNWIND */
|
||||
zlog(priority, "No backtrace available on this platform.");
|
||||
#endif
|
||||
}
|
||||
|
||||
void zlog(int priority, const char *format, ...)
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
lib_LTLIBRARIES += lib/libfrr.la
|
||||
lib_libfrr_la_LDFLAGS = -version-info 0:0:0 -Xlinker -e_libfrr_version
|
||||
lib_libfrr_la_LIBADD = @LIBCAP@
|
||||
lib_libfrr_la_LIBADD = @LIBCAP@ $(UNWIND_LIBS)
|
||||
|
||||
lib_libfrr_la_SOURCES = \
|
||||
lib/agg_table.c \
|
||||
|
@ -32,10 +32,39 @@ struct quagga_signal_t sigs[] = {};
|
||||
|
||||
struct thread_master *master;
|
||||
|
||||
static int threadfunc(struct thread *thread)
|
||||
void func1(int *arg);
|
||||
void func3(void);
|
||||
|
||||
void func1(int *arg)
|
||||
{
|
||||
int *null = NULL;
|
||||
*null += 1;
|
||||
*arg = 1;
|
||||
}
|
||||
|
||||
static void func2(size_t depth, int *arg)
|
||||
{
|
||||
/* variable stack frame size */
|
||||
int buf[depth];
|
||||
for (size_t i = 0; i < depth; i++)
|
||||
buf[i] = arg[i] + 1;
|
||||
if (depth > 0)
|
||||
func2(depth - 1, buf);
|
||||
else
|
||||
func1(&buf[0]);
|
||||
for (size_t i = 0; i < depth; i++)
|
||||
buf[i] = arg[i] + 2;
|
||||
}
|
||||
|
||||
void func3(void)
|
||||
{
|
||||
int buf[6];
|
||||
func2(6, buf);
|
||||
}
|
||||
|
||||
static int threadfunc(struct thread *thread)
|
||||
{
|
||||
func3();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user