1 /* $NetBSD: assertions.c,v 1.3 2019/02/24 20:01:31 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 15 /*! \file */ 16 17 #include <config.h> 18 19 #include <stdio.h> 20 #include <stdlib.h> 21 22 #include <isc/assertions.h> 23 #include <isc/backtrace.h> 24 #include <isc/print.h> 25 #include <isc/result.h> 26 27 /* 28 * The maximum number of stack frames to dump on assertion failure. 29 */ 30 #ifndef BACKTRACE_MAXFRAME 31 #define BACKTRACE_MAXFRAME 128 32 #endif 33 34 /*% 35 * Forward. 36 */ 37 static void 38 default_callback(const char *, int, isc_assertiontype_t, const char *); 39 40 static isc_assertioncallback_t isc_assertion_failed_cb = default_callback; 41 42 /*% 43 * Public. 44 */ 45 46 /*% assertion failed handler */ 47 /* coverity[+kill] */ 48 void 49 isc_assertion_failed(const char *file, int line, isc_assertiontype_t type, 50 const char *cond) 51 { 52 isc_assertion_failed_cb(file, line, type, cond); 53 abort(); 54 /* NOTREACHED */ 55 } 56 57 /*% Set callback. */ 58 void 59 isc_assertion_setcallback(isc_assertioncallback_t cb) { 60 if (cb == NULL) 61 isc_assertion_failed_cb = default_callback; 62 else 63 isc_assertion_failed_cb = cb; 64 } 65 66 /*% Type to Text */ 67 const char * 68 isc_assertion_typetotext(isc_assertiontype_t type) { 69 const char *result; 70 71 /* 72 * These strings have purposefully not been internationalized 73 * because they are considered to essentially be keywords of 74 * the ISC development environment. 75 */ 76 switch (type) { 77 case isc_assertiontype_require: 78 result = "REQUIRE"; 79 break; 80 case isc_assertiontype_ensure: 81 result = "ENSURE"; 82 break; 83 case isc_assertiontype_insist: 84 result = "INSIST"; 85 break; 86 case isc_assertiontype_invariant: 87 result = "INVARIANT"; 88 break; 89 default: 90 result = NULL; 91 } 92 return (result); 93 } 94 95 /* 96 * Private. 97 */ 98 99 /* coverity[+kill] */ 100 static void 101 default_callback(const char *file, int line, isc_assertiontype_t type, 102 const char *cond) 103 { 104 void *tracebuf[BACKTRACE_MAXFRAME]; 105 int i, nframes; 106 const char *logsuffix = "."; 107 const char *fname; 108 isc_result_t result; 109 110 result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, &nframes); 111 if (result == ISC_R_SUCCESS && nframes > 0) { 112 logsuffix = ", back trace"; 113 } 114 115 fprintf(stderr, "%s:%d: %s(%s) failed%s\n", 116 file, line, isc_assertion_typetotext(type), cond, logsuffix); 117 118 if (result == ISC_R_SUCCESS) { 119 for (i = 0; i < nframes; i++) { 120 unsigned long offset; 121 122 fname = NULL; 123 result = isc_backtrace_getsymbol(tracebuf[i], &fname, 124 &offset); 125 if (result == ISC_R_SUCCESS) { 126 fprintf(stderr, "#%d %p in %s()+0x%lx\n", i, 127 tracebuf[i], fname, offset); 128 } else { 129 fprintf(stderr, "#%d %p in ??\n", i, 130 tracebuf[i]); 131 } 132 } 133 } 134 fflush(stderr); 135 } 136