mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 22:10:19 +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
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
AM_CFLAGS = \
|
AM_CFLAGS = \
|
||||||
|
$(UNWIND_CFLAGS) \
|
||||||
$(SAN_FLAGS) \
|
$(SAN_FLAGS) \
|
||||||
$(WERROR) \
|
$(WERROR) \
|
||||||
# end
|
# end
|
||||||
|
32
configure.ac
32
configure.ac
@ -958,10 +958,6 @@ case "$host_os" in
|
|||||||
AC_CHECK_LIB(socket, main)
|
AC_CHECK_LIB(socket, main)
|
||||||
AC_CHECK_LIB(nsl, main)
|
AC_CHECK_LIB(nsl, main)
|
||||||
AC_CHECK_LIB(umem, 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
|
CURSES=-lcurses
|
||||||
SOLARIS="solaris"
|
SOLARIS="solaris"
|
||||||
;;
|
;;
|
||||||
@ -1811,17 +1807,31 @@ dnl check for glibc 'backtrace'
|
|||||||
dnl ---------------------------
|
dnl ---------------------------
|
||||||
if test x"${enable_backtrace}" != x"no" ; then
|
if test x"${enable_backtrace}" != x"no" ; then
|
||||||
backtrace_ok=no
|
backtrace_ok=no
|
||||||
AC_CHECK_HEADER([execinfo.h], [
|
PKG_CHECK_MODULES([UNWIND], [libunwind], [
|
||||||
AC_SEARCH_LIBS([backtrace], [execinfo], [
|
AC_DEFINE(HAVE_LIBUNWIND, 1, [libunwind])
|
||||||
AC_DEFINE(HAVE_GLIBC_BACKTRACE,,[Glibc backtrace])
|
backtrace_ok=yes
|
||||||
AC_DEFINE(HAVE_STACK_TRACE,,[Stack symbol decoding])
|
], [
|
||||||
backtrace_ok=yes
|
case "$host_os" in
|
||||||
],, [-lm])
|
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
|
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
|
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
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
81
lib/log.c
81
lib/log.c
@ -38,6 +38,12 @@
|
|||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBUNWIND
|
||||||
|
#define UNW_LOCAL_ONLY
|
||||||
|
#include <libunwind.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
DEFINE_MTYPE_STATIC(LIB, ZLOG, "Logging")
|
DEFINE_MTYPE_STATIC(LIB, ZLOG, "Logging")
|
||||||
|
|
||||||
static int logfile_fd = -1; /* Used in signal handler. */
|
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);
|
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)
|
static char *hex_append(char *s, int len, unsigned long x)
|
||||||
{
|
{
|
||||||
char buf[30];
|
char buf[30];
|
||||||
@ -533,7 +541,37 @@ void zlog_signal(int signo, const char *action
|
|||||||
Needs to be enhanced to support syslog logging. */
|
Needs to be enhanced to support syslog logging. */
|
||||||
void zlog_backtrace_sigsafe(int priority, void *program_counter)
|
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: ";
|
static const char pclabel[] = "Program counter: ";
|
||||||
void *array[64];
|
void *array[64];
|
||||||
int size;
|
int size;
|
||||||
@ -624,9 +662,38 @@ void zlog_backtrace_sigsafe(int priority, void *program_counter)
|
|||||||
|
|
||||||
void zlog_backtrace(int priority)
|
void zlog_backtrace(int priority)
|
||||||
{
|
{
|
||||||
#ifndef HAVE_GLIBC_BACKTRACE
|
#ifdef HAVE_LIBUNWIND
|
||||||
zlog(priority, "No backtrace available on this platform.");
|
char buf[100];
|
||||||
#else
|
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];
|
void *array[20];
|
||||||
int size, i;
|
int size, i;
|
||||||
char **strings;
|
char **strings;
|
||||||
@ -651,7 +718,9 @@ void zlog_backtrace(int priority)
|
|||||||
zlog(priority, "[bt %d] %s", i, strings[i]);
|
zlog(priority, "[bt %d] %s", i, strings[i]);
|
||||||
free(strings);
|
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, ...)
|
void zlog(int priority, const char *format, ...)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#
|
#
|
||||||
lib_LTLIBRARIES += lib/libfrr.la
|
lib_LTLIBRARIES += lib/libfrr.la
|
||||||
lib_libfrr_la_LDFLAGS = -version-info 0:0:0 -Xlinker -e_libfrr_version
|
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_libfrr_la_SOURCES = \
|
||||||
lib/agg_table.c \
|
lib/agg_table.c \
|
||||||
|
@ -32,10 +32,39 @@ struct quagga_signal_t sigs[] = {};
|
|||||||
|
|
||||||
struct thread_master *master;
|
struct thread_master *master;
|
||||||
|
|
||||||
static int threadfunc(struct thread *thread)
|
void func1(int *arg);
|
||||||
|
void func3(void);
|
||||||
|
|
||||||
|
void func1(int *arg)
|
||||||
{
|
{
|
||||||
int *null = NULL;
|
int *null = NULL;
|
||||||
*null += 1;
|
*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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user