forked from wolfSSL/wolfssl
add --enable-debug-trace-errcodes=backtrace.
* uses libbacktrace to enhance existing "ERR TRACE" messages with backtraces, rendered in same format as the sanitizers. * adds wc_backtrace_render() and some related callbacks to wolfcrypt/src/logging.c. * adds an overrideable WOLFSSL_DEBUG_BACKTRACE_RENDER_CLAUSE to the WC_ERR_TRACE() mechanism in wolfssl/wolfcrypt/error-crypt.h.
This commit is contained in:
10
configure.ac
10
configure.ac
@ -217,11 +217,17 @@ AC_ARG_ENABLE([debug-trace-errcodes],
|
|||||||
[ ENABLED_DEBUG_TRACE_ERRCODES=no ]
|
[ ENABLED_DEBUG_TRACE_ERRCODES=no ]
|
||||||
)
|
)
|
||||||
|
|
||||||
if test "$ENABLED_DEBUG_TRACE_ERRCODES" = "yes"
|
if test "$ENABLED_DEBUG_TRACE_ERRCODES" != "no"
|
||||||
then
|
then
|
||||||
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEBUG_TRACE_ERROR_CODES"
|
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEBUG_TRACE_ERROR_CODES"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$ENABLED_DEBUG_TRACE_ERRCODES" = "backtrace"
|
||||||
|
then
|
||||||
|
AM_CFLAGS="$AM_CFLAGS -g -funwind-tables -DWOLFSSL_DEBUG_BACKTRACE_ERROR_CODES"
|
||||||
|
AM_LDFLAGS="$AM_LDFLAGS -lbacktrace"
|
||||||
|
fi
|
||||||
|
|
||||||
# Start without certificates enabled and enable if a certificate algorithm is
|
# Start without certificates enabled and enable if a certificate algorithm is
|
||||||
# enabled
|
# enabled
|
||||||
ENABLED_CERTS="no"
|
ENABLED_CERTS="no"
|
||||||
@ -9981,7 +9987,7 @@ echo "" >> $OPTION_FILE
|
|||||||
echo "#endif /* WOLFSSL_OPTIONS_H */" >> $OPTION_FILE
|
echo "#endif /* WOLFSSL_OPTIONS_H */" >> $OPTION_FILE
|
||||||
echo "" >> $OPTION_FILE
|
echo "" >> $OPTION_FILE
|
||||||
|
|
||||||
if test "$ENABLED_DEBUG_TRACE_ERRCODES" = "yes"
|
if test "$ENABLED_DEBUG_TRACE_ERRCODES" != "no"
|
||||||
then
|
then
|
||||||
support/gen-debug-trace-error-codes.sh || AC_MSG_ERROR([Header generation for debug-trace-errcodes failed.])
|
support/gen-debug-trace-error-codes.sh || AC_MSG_ERROR([Header generation for debug-trace-errcodes failed.])
|
||||||
fi
|
fi
|
||||||
|
@ -1674,3 +1674,130 @@ void WOLFSSL_ERROR_MSG(const char* msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
|
#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES
|
||||||
|
|
||||||
|
#include <backtrace-supported.h>
|
||||||
|
|
||||||
|
#if BACKTRACE_SUPPORTED != 1
|
||||||
|
#error WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES is defined but BACKTRACE_SUPPORTED is 0.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(WOLFSSL_MUTEX_INITIALIZER) && defined(WOLFSSL_NO_ATOMICS)
|
||||||
|
#error WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES requires WOLFSSL_MUTEX_INITIALIZER or wolfSSL_Atomic_Ints.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <backtrace.h>
|
||||||
|
|
||||||
|
static int backtrace_callback(void *data, uintptr_t pc, const char *filename,
|
||||||
|
int lineno, const char *function)
|
||||||
|
{
|
||||||
|
if (function == NULL)
|
||||||
|
return 0;
|
||||||
|
/* the first callback is for the call to wc_print_backtrace() -- skip it. */
|
||||||
|
if (*(int *)data == 0) {
|
||||||
|
*(int *)data = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#ifdef NO_STDIO_FILESYSTEM
|
||||||
|
printf(" #%d %p in %s %s:%d\n", (*(int *)data)++, (void *)pc,
|
||||||
|
function, filename, lineno);
|
||||||
|
#else
|
||||||
|
fprintf(stderr, " #%d %p in %s %s:%d\n", (*(int *)data)++, (void *)pc,
|
||||||
|
function, filename, lineno);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void backtrace_error(void *data, const char *msg, int errnum) {
|
||||||
|
(void)data;
|
||||||
|
#ifdef NO_STDIO_FILESYSTEM
|
||||||
|
printf("ERR TRACE: error %d while backtracing: %s", errnum, msg);
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "ERR TRACE: error %d while backtracing: %s", errnum, msg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void backtrace_creation_error(void *data, const char *msg, int errnum) {
|
||||||
|
(void)data;
|
||||||
|
#ifdef NO_STDIO_FILESYSTEM
|
||||||
|
printf("ERR TRACE: internal error %d "
|
||||||
|
"while initializing backtrace facility: %s", errnum, msg);
|
||||||
|
printf("ERR TRACE: internal error "
|
||||||
|
"while initializing backtrace facility");
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "ERR TRACE: internal error %d "
|
||||||
|
"while initializing backtrace facility: %s", errnum, msg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int backtrace_init(struct backtrace_state **backtrace_state) {
|
||||||
|
#ifdef WOLFSSL_MUTEX_INITIALIZER
|
||||||
|
static wolfSSL_Mutex backtrace_create_state_mutex =
|
||||||
|
WOLFSSL_MUTEX_INITIALIZER(backtrace_create_state_mutex);
|
||||||
|
if (wc_LockMutex(&backtrace_create_state_mutex) != 0)
|
||||||
|
return -1;
|
||||||
|
#elif defined(WOLFSSL_ATOMIC_OPS)
|
||||||
|
static wolfSSL_Atomic_Int init_count = 0;
|
||||||
|
if (wolfSSL_Atomic_Int_FetchAdd(&init_count, 1) != 1)
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
if (*backtrace_state == NULL) {
|
||||||
|
/* passing a NULL filename to backtrace_create_state() tells
|
||||||
|
* libbacktrace to use a target-specific strategy to determine the
|
||||||
|
* executable. "libbacktrace supports ELF, PE/COFF, Mach-O, and XCOFF
|
||||||
|
* executables with DWARF debugging information. In other words, it
|
||||||
|
* supports GNU/Linux, *BSD, macOS, Windows, and AIX."
|
||||||
|
*/
|
||||||
|
*backtrace_state = backtrace_create_state(
|
||||||
|
NULL, 0, backtrace_creation_error, NULL);
|
||||||
|
}
|
||||||
|
#ifdef WOLFSSL_MUTEX_INITIALIZER
|
||||||
|
wc_UnLockMutex(&backtrace_create_state_mutex);
|
||||||
|
#endif
|
||||||
|
if (*backtrace_state == NULL)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wc_backtrace_render(void) {
|
||||||
|
static wolfSSL_Mutex backtrace_mutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(backtrace_mutex);
|
||||||
|
static struct backtrace_state *backtrace_state = NULL;
|
||||||
|
int depth = 0;
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_MUTEX_INITIALIZER
|
||||||
|
static wolfSSL_Atomic_Int init_count = 0;
|
||||||
|
if (init_count != 1) {
|
||||||
|
if (wolfSSL_Atomic_Int_FetchSub(&init_count, 1) != -1)
|
||||||
|
return;
|
||||||
|
if (wc_InitMutex(&backtrace_mutex) != 0)
|
||||||
|
return;
|
||||||
|
init_count = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* backtrace_state can't be shared between threads even when
|
||||||
|
* BACKTRACE_SUPPORTS_THREADS == 1, so we serialize the render op. this
|
||||||
|
* helpfully mutexes the initialization too.
|
||||||
|
*/
|
||||||
|
if (wc_LockMutex(&backtrace_mutex) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (backtrace_state == NULL) {
|
||||||
|
if (backtrace_init(&backtrace_state) < 0) {
|
||||||
|
wc_UnLockMutex(&backtrace_mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* note that the optimizer can produce misleading backtraces, even with
|
||||||
|
* -funwind-tables. in contrast, the macro-generated "ERR TRACE" message
|
||||||
|
* from WC_ERR_TRACE() always accurately identifies the error code point.
|
||||||
|
*/
|
||||||
|
backtrace_full(backtrace_state, 0, backtrace_callback, backtrace_error,
|
||||||
|
(void *)&depth);
|
||||||
|
|
||||||
|
wc_UnLockMutex(&backtrace_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES */
|
||||||
|
@ -298,17 +298,31 @@ WOLFSSL_ABI WOLFSSL_API const char* wc_GetErrorString(int error);
|
|||||||
#undef WOLFSSL_DEBUG_TRACE_ERROR_CODES
|
#undef WOLFSSL_DEBUG_TRACE_ERROR_CODES
|
||||||
#endif
|
#endif
|
||||||
#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES
|
#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES
|
||||||
|
extern void wc_backtrace_render(void);
|
||||||
#define WC_NO_ERR_TRACE(label) (CONST_NUM_ERR_ ## label)
|
#define WC_NO_ERR_TRACE(label) (CONST_NUM_ERR_ ## label)
|
||||||
|
#ifndef WOLFSSL_DEBUG_BACKTRACE_RENDER_CLAUSE
|
||||||
|
#ifdef WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES
|
||||||
|
#define WOLFSSL_DEBUG_BACKTRACE_RENDER_CLAUSE wc_backtrace_render()
|
||||||
|
#else
|
||||||
|
#define WOLFSSL_DEBUG_BACKTRACE_RENDER_CLAUSE (void)0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#ifndef WC_ERR_TRACE
|
#ifndef WC_ERR_TRACE
|
||||||
#ifdef NO_STDIO_FILESYSTEM
|
#ifdef NO_STDIO_FILESYSTEM
|
||||||
#define WC_ERR_TRACE(label) \
|
#define WC_ERR_TRACE(label) \
|
||||||
( printf("ERR TRACE: %s L %d " #label " (%d)\n", \
|
( printf("ERR TRACE: %s L %d %s (%d)\n", \
|
||||||
__FILE__, __LINE__, label), label)
|
__FILE__, __LINE__, #label, label), \
|
||||||
|
WOLFSSL_DEBUG_BACKTRACE_RENDER_CLAUSE, \
|
||||||
|
label \
|
||||||
|
)
|
||||||
#else
|
#else
|
||||||
#define WC_ERR_TRACE(label) \
|
#define WC_ERR_TRACE(label) \
|
||||||
( fprintf(stderr, \
|
( fprintf(stderr, \
|
||||||
"ERR TRACE: %s L %d " #label " (%d)\n", \
|
"ERR TRACE: %s L %d %s (%d)\n", \
|
||||||
__FILE__, __LINE__, label), label)
|
__FILE__, __LINE__, #label, label), \
|
||||||
|
WOLFSSL_DEBUG_BACKTRACE_RENDER_CLAUSE, \
|
||||||
|
label \
|
||||||
|
)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#include <wolfssl/debug-trace-error-codes.h>
|
#include <wolfssl/debug-trace-error-codes.h>
|
||||||
|
Reference in New Issue
Block a user