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