4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2024, Rob Norris <robn@despairlabs.com>
23 * Copyright (c) 2024, Klara Inc.
26 #include <sys/backtrace.h>
27 #include <sys/types.h>
31 * libspl_backtrace() must be safe to call from inside a signal hander. This
32 * mostly means it must not allocate, and so we can't use things like printf.
35 #if defined(HAVE_LIBUNWIND)
36 #define UNW_LOCAL_ONLY
37 #include <libunwind.h>
40 libspl_u64_to_hex_str(uint64_t v
, size_t digits
, char *buf
, size_t buflen
)
42 static const char hexdigits
[] = {
43 '0', '1', '2', '3', '4', '5', '6', '7',
44 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
48 boolean_t want
= (digits
== 0);
49 for (int i
= 15; i
>= 0; i
--) {
50 const uint64_t d
= v
>> (i
* 4) & 0xf;
51 if (!want
&& (d
!= 0 || digits
> i
))
54 buf
[pos
++] = hexdigits
[d
];
63 libspl_backtrace(int fd
)
65 ssize_t ret
__attribute__((unused
));
72 ret
= write(fd
, "Call trace:\n", 12);
74 unw_init_local(&cp
, &uc
);
75 while (unw_step(&cp
) > 0) {
76 unw_get_reg(&cp
, UNW_REG_IP
, &loc
);
77 ret
= write(fd
, " [0x", 5);
78 n
= libspl_u64_to_hex_str(loc
, 10, buf
, sizeof (buf
));
79 ret
= write(fd
, buf
, n
);
80 ret
= write(fd
, "] ", 2);
81 unw_get_proc_name(&cp
, buf
, sizeof (buf
), &loc
);
82 for (n
= 0; n
< sizeof (buf
) && buf
[n
] != '\0'; n
++) {}
83 ret
= write(fd
, buf
, n
);
84 ret
= write(fd
, "+0x", 3);
85 n
= libspl_u64_to_hex_str(loc
, 2, buf
, sizeof (buf
));
86 ret
= write(fd
, buf
, n
);
87 #ifdef HAVE_LIBUNWIND_ELF
88 ret
= write(fd
, " (in ", 5);
89 unw_get_elf_filename(&cp
, buf
, sizeof (buf
), &loc
);
90 for (n
= 0; n
< sizeof (buf
) && buf
[n
] != '\0'; n
++) {}
91 ret
= write(fd
, buf
, n
);
92 ret
= write(fd
, " +0x", 4);
93 n
= libspl_u64_to_hex_str(loc
, 2, buf
, sizeof (buf
));
94 ret
= write(fd
, buf
, n
);
95 ret
= write(fd
, ")", 1);
97 ret
= write(fd
, "\n", 1);
100 #elif defined(HAVE_BACKTRACE)
101 #include <execinfo.h>
104 libspl_backtrace(int fd
)
106 ssize_t ret
__attribute__((unused
));
108 size_t nptrs
= backtrace(btptrs
, 64);
109 ret
= write(fd
, "Call trace:\n", 12);
110 backtrace_symbols_fd(btptrs
, nptrs
, fd
);
113 #include <sys/debug.h>
116 libspl_backtrace(int fd __maybe_unused
)