xref: /netbsd-src/external/mpl/bind/dist/lib/isc/backtrace.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: backtrace.c,v 1.8 2025/01/26 16:25:36 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 /*! \file */
17 
18 #include <stdlib.h>
19 #include <string.h>
20 #ifdef HAVE_BACKTRACE_SYMBOLS
21 #include <execinfo.h>
22 #endif /* HAVE_BACKTRACE_SYMBOLS */
23 
24 #include <isc/backtrace.h>
25 #include <isc/log.h>
26 #include <isc/result.h>
27 #include <isc/util.h>
28 
29 #if HAVE_BACKTRACE_SYMBOLS
30 int
31 isc_backtrace(void **addrs, int maxaddrs) {
32 	int n;
33 
34 	/*
35 	 * Validate the arguments: intentionally avoid using REQUIRE().
36 	 * See notes in backtrace.h.
37 	 */
38 	if (addrs == NULL || maxaddrs <= 0) {
39 		return -1;
40 	}
41 
42 	/*
43 	 * backtrace(3) includes this function itself in the address array,
44 	 * which should be eliminated from the returned sequence.
45 	 */
46 	n = backtrace(addrs, maxaddrs);
47 	if (n < 2) {
48 		return -1;
49 	}
50 	n--;
51 	memmove(addrs, &addrs[1], sizeof(addrs[0]) * n);
52 
53 	return n;
54 }
55 
56 char **
57 isc_backtrace_symbols(void *const *buffer, int size) {
58 	return backtrace_symbols(buffer, size);
59 }
60 
61 void
62 isc_backtrace_symbols_fd(void *const *buffer, int size, int fd) {
63 	backtrace_symbols_fd(buffer, size, fd);
64 }
65 
66 void
67 isc_backtrace_log(isc_log_t *lctx, isc_logcategory_t *category,
68 		  isc_logmodule_t *module, int level) {
69 	void *tracebuf[ISC_BACKTRACE_MAXFRAME];
70 	int nframes;
71 	char **strs;
72 
73 	nframes = isc_backtrace(tracebuf, ISC_BACKTRACE_MAXFRAME);
74 	if (nframes <= 0) {
75 		return;
76 	}
77 	strs = isc_backtrace_symbols(tracebuf, nframes);
78 	if (strs == NULL) {
79 		return;
80 	}
81 	for (int i = 0; i < nframes; i++) {
82 		isc_log_write(lctx, category, module, level, "%s", strs[i]);
83 	}
84 }
85 
86 #else /* HAVE_BACKTRACE_SYMBOLS */
87 
88 int
89 isc_backtrace(void **addrs, int maxaddrs) {
90 	UNUSED(addrs);
91 	UNUSED(maxaddrs);
92 
93 	return -1;
94 }
95 
96 char **
97 isc_backtrace_symbols(void *const *buffer, int size) {
98 	UNUSED(buffer);
99 	UNUSED(size);
100 
101 	return NULL;
102 }
103 
104 void
105 isc_backtrace_symbols_fd(void *const *buffer, int size, int fd) {
106 	UNUSED(buffer);
107 	UNUSED(size);
108 	UNUSED(fd);
109 }
110 
111 void
112 isc_backtrace_log(isc_log_t *lctx, isc_logcategory_t *category,
113 		  isc_logmodule_t *module, int level) {
114 	UNUSED(lctx);
115 	UNUSED(category);
116 	UNUSED(module);
117 	UNUSED(level);
118 }
119 
120 #endif /* HAVE_BACKTRACE_SYMBOLS */
121