From dffb03a562e633aad87f2722ab8c2cfde671ab92 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Sun, 11 Aug 2019 19:02:50 -0700 Subject: [PATCH] ircd: Cleanup / simplify assert related interface. --- configure.ac | 4 +++ include/ircd/assert.h | 58 ++++++++++++++++++++++++++++--------------- ircd/assert.cc | 49 ++++++++++++++---------------------- 3 files changed, 61 insertions(+), 50 deletions(-) diff --git a/configure.ac b/configure.ac index 6a804fb79..465e1143d 100644 --- a/configure.ac +++ b/configure.ac @@ -227,6 +227,10 @@ AM_COND_IF(ASSERT, if [[ ! -z "$assert_type" ]]; then RB_DEFINE_UNQUOTED([ASSERT], ["$assert_type"], [Assertion behavior]) fi + + if [ "$assert_type" == "trap" ]; then + RB_DEFINE([ASSERT_INTRINSIC], [1], [Intrinsic assertion behavior]) + fi ]) dnl diff --git a/include/ircd/assert.h b/include/ircd/assert.h index 18813abb5..70293589e 100644 --- a/include/ircd/assert.h +++ b/include/ircd/assert.h @@ -19,43 +19,61 @@ #pragma once #define HAVE_IRCD_ASSERT_H -namespace ircd -{ - void debugtrap(); -} - +/// This file has to be included prior to the standard library assert headers #if defined(RB_ASSERT) && defined(_ASSERT_H_DECLS) && defined(RB_DEBUG) #error "Do not include or first." #endif +/// Define an indicator for whether we override standard assert() behavior in +/// this build if the conditions are appropriate. #if defined(RB_ASSERT) && !defined(NDEBUG) -#define _ASSERT_H_DECLS + #define IRCD_ASSERT_OVERRIDE + #define _ASSERT_H_DECLS +#endif +// Our utils +namespace ircd +{ + void print_assertion(const char *const &, const char *const &, const unsigned &, const char *const &) noexcept; + void debugtrap() noexcept; +} + +/// Override the standard assert behavior, if enabled, to trap into the +/// debugger as close as possible to the offending site. +/// +#if defined(IRCD_ASSERT_OVERRIDE) && defined(RB_ASSERT_INTRINSIC) +extern "C" inline void +__attribute__((flatten, always_inline, gnu_inline, artificial)) +__assert_fail(const char *__assertion, + const char *__file, + unsigned int __line, + const char *__function) +{ + ircd::print_assertion(__assertion, __file, __line, __function); + ircd::debugtrap(); +} +#endif + +/// Override the standard assert behavior to take one of several different +/// actions as defined in our internal assert.cc unit. When trapping assert +/// is disabled this path will be used instead. +/// +#if defined(IRCD_ASSERT_OVERRIDE) && !defined(RB_ASSERT_INTRINSIC) extern "C" void __attribute__((visibility("default"))) __assert_fail(const char *__assertion, const char *__file, unsigned int __line, const char *__function); - -extern "C" void -__attribute__((visibility("default"))) -__assert_perror_fail(int __errnum, - const char *__file, - unsigned int __line, - const char *__function); - -extern "C" void -__attribute__((visibility("default"))) -__assert(const char *__assertion, - const char *__file, - int __line); - #endif +/// Intrinsic to halt execution for examination by a tracing debugger without +/// aborting the program. +/// extern inline void __attribute__((always_inline, gnu_inline, artificial)) ircd::debugtrap() +noexcept { #if defined(__clang__) static_assert(__has_builtin(__builtin_debugtrap)); diff --git a/ircd/assert.cc b/ircd/assert.cc index 703d47459..09f65ce13 100644 --- a/ircd/assert.cc +++ b/ircd/assert.cc @@ -10,30 +10,7 @@ #include "); -} -#endif - -#if !defined(NDEBUG) && defined(RB_ASSERT) -void -__assert_perror_fail(int __errnum, - const char *__file, - unsigned int __line, - const char *__function) -{ - char buf[32]; - snprintf(buf, sizeof(buf), "perror #%d: ", __errnum); - __assert_fail(buf, __file, __line, __function); -} -#endif - -#if !defined(NDEBUG) && defined(RB_ASSERT) +#ifdef IRCD_ASSERT_OVERRIDE #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" @@ -44,12 +21,7 @@ __assert_fail(const char *__assertion, unsigned int __line, const char *__function) { - if(strcmp(__assertion, "critical") != 0) - fprintf(stderr, "\nassertion failed [%s +%u] %s :%s\n", - __file, - __line, - __function, - __assertion); + ircd::print_assertion(__assertion, __file, __line, __function); if(ircd::soft_assert) return; @@ -97,3 +69,20 @@ __assert_fail(const char *__assertion, #pragma clang diagnostic pop #endif __clang__ #endif + +void +ircd::print_assertion(const char *const &__assertion, + const char *const &__file, + const unsigned &__line, + const char *const &__function) +noexcept +{ + if(strcmp(__assertion, "critical") == 0) + return; + + fprintf(stderr, "\nassertion failed [%s +%u] %s :%s\n", + __file, + __line, + __function, + __assertion); +}