1120586Sbms/*	$NetBSD: assertions.c,v 1.7 2020/09/07 00:48:45 mrg Exp $	*/
2120586Sbms
3120586Sbms/*
4120586Sbms * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
5120586Sbms * Copyright (C) 1997-2001  Internet Software Consortium.
6120586Sbms *
7120586Sbms * Permission to use, copy, modify, and/or distribute this software for any
8120586Sbms * purpose with or without fee is hereby granted, provided that the above
9120586Sbms * copyright notice and this permission notice appear in all copies.
10120586Sbms *
11120586Sbms * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12120586Sbms * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13120586Sbms * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14120586Sbms * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15120586Sbms * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16120586Sbms * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17120586Sbms * PERFORMANCE OF THIS SOFTWARE.
18120586Sbms */
19120586Sbms
20120586Sbms/* Id: assertions.c,v 1.26 2009/09/29 15:06:07 fdupont Exp  */
21120586Sbms
22120586Sbms/*! \file */
23120586Sbms
24120586Sbms#include <config.h>
25120586Sbms
26120586Sbms#include <stdio.h>
27120586Sbms#include <stdlib.h>
28120586Sbms
29131680Sru#include <isc/assertions.h>
30131681Sru#include <isc/backtrace.h>
31120586Sbms#include <isc/msgs.h>
32120586Sbms#include <isc/result.h>
33120586Sbms
34120586Sbms/*
35120586Sbms * The maximum number of stack frames to dump on assertion failure.
36120586Sbms */
37120586Sbms#ifndef BACKTRACE_MAXFRAME
38120586Sbms#define BACKTRACE_MAXFRAME 128
39120586Sbms#endif
40120586Sbms
41120586Sbms/*%
42120586Sbms * Forward.
43120586Sbms */
44120586Sbmsstatic void
45120586Sbmsdefault_callback(const char *, int, isc_assertiontype_t, const char *);
46120586Sbms
47120586Sbmsstatic isc_assertioncallback_t isc_assertion_failed_cb = default_callback;
48120586Sbms
49120586Sbms/*%
50120586Sbms * Public.
51120586Sbms */
52120586Sbms
53120586Sbms/*% assertion failed handler */
54120586Sbms/* coverity[+kill] */
55120586Sbmsvoid
56120586Sbmsisc_assertion_failed(const char *file, int line, isc_assertiontype_t type,
57120586Sbms		     const char *cond)
58147647Shmp{
59120586Sbms	isc_assertion_failed_cb(file, line, type, cond);
60	abort();
61	/* NOTREACHED */
62}
63
64/*% Set callback. */
65void
66isc_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 */
74const char *
75isc_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 = "*invalid*";
98	}
99	return (result);
100}
101
102/*
103 * Private.
104 */
105
106static void
107default_callback(const char *file, int line, isc_assertiontype_t type,
108		 const char *cond)
109{
110	void *tracebuf[BACKTRACE_MAXFRAME];
111	int i, nframes;
112	const char *logsuffix = ".";
113	const char *fname;
114	isc_result_t result;
115
116	result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, &nframes);
117		if (result == ISC_R_SUCCESS && nframes > 0)
118			logsuffix = ", back trace";
119
120	fprintf(stderr, "%s:%d: %s(%s) %s%s\n",
121		file, line, isc_assertion_typetotext(type), cond,
122		isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
123			       ISC_MSG_FAILED, "failed"), logsuffix);
124	if (result == ISC_R_SUCCESS) {
125		for (i = 0; i < nframes; i++) {
126			unsigned long offset;
127
128			fname = NULL;
129			result = isc_backtrace_getsymbol(tracebuf[i], &fname,
130							 &offset);
131			if (result == ISC_R_SUCCESS) {
132				fprintf(stderr, "#%d %p in %s()+0x%lx\n", i,
133					tracebuf[i], fname, offset);
134			} else {
135				fprintf(stderr, "#%d %p in ??\n", i,
136					tracebuf[i]);
137			}
138		}
139	}
140	fflush(stderr);
141}
142