xref: /minix3/external/bsd/bind/dist/lib/isc/assertions.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1 /*	$NetBSD: assertions.c,v 1.6 2014/12/10 04:37:59 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 1997-2001  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* Id: assertions.c,v 1.26 2009/09/29 15:06:07 fdupont Exp  */
21 
22 /*! \file */
23 
24 #include <config.h>
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 
29 #include <isc/assertions.h>
30 #include <isc/backtrace.h>
31 #include <isc/msgs.h>
32 #include <isc/result.h>
33 
34 /*
35  * The maximum number of stack frames to dump on assertion failure.
36  */
37 #ifndef BACKTRACE_MAXFRAME
38 #define BACKTRACE_MAXFRAME 128
39 #endif
40 
41 /*%
42  * Forward.
43  */
44 static void
45 default_callback(const char *, int, isc_assertiontype_t, const char *);
46 
47 static isc_assertioncallback_t isc_assertion_failed_cb = default_callback;
48 
49 /*%
50  * Public.
51  */
52 
53 /*% assertion failed handler */
54 /* coverity[+kill] */
55 void
isc_assertion_failed(const char * file,int line,isc_assertiontype_t type,const char * cond)56 isc_assertion_failed(const char *file, int line, isc_assertiontype_t type,
57 		     const char *cond)
58 {
59 	isc_assertion_failed_cb(file, line, type, cond);
60 	abort();
61 	/* NOTREACHED */
62 }
63 
64 /*% Set callback. */
65 void
isc_assertion_setcallback(isc_assertioncallback_t cb)66 isc_assertion_setcallback(isc_assertioncallback_t cb) {
67 	if (cb == NULL)
68 		isc_assertion_failed_cb = default_callback;
69 	else
70 		isc_assertion_failed_cb = cb;
71 }
72 
73 /*% Type to Text */
74 const char *
isc_assertion_typetotext(isc_assertiontype_t type)75 isc_assertion_typetotext(isc_assertiontype_t type) {
76 	const char *result;
77 
78 	/*
79 	 * These strings have purposefully not been internationalized
80 	 * because they are considered to essentially be keywords of
81 	 * the ISC development environment.
82 	 */
83 	switch (type) {
84 	case isc_assertiontype_require:
85 		result = "REQUIRE";
86 		break;
87 	case isc_assertiontype_ensure:
88 		result = "ENSURE";
89 		break;
90 	case isc_assertiontype_insist:
91 		result = "INSIST";
92 		break;
93 	case isc_assertiontype_invariant:
94 		result = "INVARIANT";
95 		break;
96 	default:
97 		result = NULL;
98 	}
99 	return (result);
100 }
101 
102 /*
103  * Private.
104  */
105 
106 /* coverity[+kill] */
107 static void
default_callback(const char * file,int line,isc_assertiontype_t type,const char * cond)108 default_callback(const char *file, int line, isc_assertiontype_t type,
109 		 const char *cond)
110 {
111 	void *tracebuf[BACKTRACE_MAXFRAME];
112 	int i, nframes;
113 	const char *logsuffix = ".";
114 	const char *fname;
115 	isc_result_t result;
116 
117 	result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, &nframes);
118 		if (result == ISC_R_SUCCESS && nframes > 0)
119 			logsuffix = ", back trace";
120 
121 	fprintf(stderr, "%s:%d: %s(%s) %s%s\n",
122 		file, line, isc_assertion_typetotext(type), cond,
123 		isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
124 			       ISC_MSG_FAILED, "failed"), logsuffix);
125 	if (result == ISC_R_SUCCESS) {
126 		for (i = 0; i < nframes; i++) {
127 			unsigned long offset;
128 
129 			fname = NULL;
130 			result = isc_backtrace_getsymbol(tracebuf[i], &fname,
131 							 &offset);
132 			if (result == ISC_R_SUCCESS) {
133 				fprintf(stderr, "#%d %p in %s()+0x%lx\n", i,
134 					tracebuf[i], fname, offset);
135 			} else {
136 				fprintf(stderr, "#%d %p in ??\n", i,
137 					tracebuf[i]);
138 			}
139 		}
140 	}
141 	fflush(stderr);
142 }
143