Home | History | Annotate | Line # | Download | only in isc
      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