1 /* $NetBSD: assertions.c,v 1.5 2020/08/03 17:23:42 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 */ 13 14 /*! \file */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 19 #include <isc/assertions.h> 20 #include <isc/backtrace.h> 21 #include <isc/print.h> 22 #include <isc/result.h> 23 24 /* 25 * The maximum number of stack frames to dump on assertion failure. 26 */ 27 #ifndef BACKTRACE_MAXFRAME 28 #define BACKTRACE_MAXFRAME 128 29 #endif /* ifndef BACKTRACE_MAXFRAME */ 30 31 /*% 32 * Forward. 33 */ 34 static void 35 default_callback(const char *, int, isc_assertiontype_t, const char *); 36 37 static isc_assertioncallback_t isc_assertion_failed_cb = default_callback; 38 39 /*% 40 * Public. 41 */ 42 43 /*% assertion failed handler */ 44 /* coverity[+kill] */ 45 void 46 isc_assertion_failed(const char *file, int line, isc_assertiontype_t type, 47 const char *cond) { 48 isc_assertion_failed_cb(file, line, type, cond); 49 abort(); 50 /* NOTREACHED */ 51 } 52 53 /*% Set callback. */ 54 void 55 isc_assertion_setcallback(isc_assertioncallback_t cb) { 56 if (cb == NULL) { 57 isc_assertion_failed_cb = default_callback; 58 } else { 59 isc_assertion_failed_cb = cb; 60 } 61 } 62 63 /*% Type to Text */ 64 const char * 65 isc_assertion_typetotext(isc_assertiontype_t type) { 66 const char *result; 67 68 /* 69 * These strings have purposefully not been internationalized 70 * because they are considered to essentially be keywords of 71 * the ISC development environment. 72 */ 73 switch (type) { 74 case isc_assertiontype_require: 75 result = "REQUIRE"; 76 break; 77 case isc_assertiontype_ensure: 78 result = "ENSURE"; 79 break; 80 case isc_assertiontype_insist: 81 result = "INSIST"; 82 break; 83 case isc_assertiontype_invariant: 84 result = "INVARIANT"; 85 break; 86 default: 87 result = "UNKNOWN"; 88 } 89 return (result); 90 } 91 92 /* 93 * Private. 94 */ 95 96 /* coverity[+kill] */ 97 static void 98 default_callback(const char *file, int line, isc_assertiontype_t type, 99 const char *cond) { 100 void *tracebuf[BACKTRACE_MAXFRAME]; 101 int i, nframes; 102 const char *logsuffix = "."; 103 const char *fname; 104 isc_result_t result; 105 106 result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, &nframes); 107 if (result == ISC_R_SUCCESS && nframes > 0) { 108 logsuffix = ", back trace"; 109 } 110 111 fprintf(stderr, "%s:%d: %s(%s) failed%s\n", file, line, 112 isc_assertion_typetotext(type), cond, logsuffix); 113 114 if (result == ISC_R_SUCCESS) { 115 for (i = 0; i < nframes; i++) { 116 unsigned long offset; 117 118 fname = NULL; 119 result = isc_backtrace_getsymbol(tracebuf[i], &fname, 120 &offset); 121 if (result == ISC_R_SUCCESS) { 122 fprintf(stderr, "#%d %p in %s()+0x%lx\n", i, 123 tracebuf[i], fname, offset); 124 } else { 125 fprintf(stderr, "#%d %p in ??\n", i, 126 tracebuf[i]); 127 } 128 } 129 } 130 fflush(stderr); 131 } 132