Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/lib/libspl/backtrace.c
48378 views
1
// SPDX-License-Identifier: CDDL-1.0
2
/*
3
* CDDL HEADER START
4
*
5
* The contents of this file are subject to the terms of the
6
* Common Development and Distribution License (the "License").
7
* You may not use this file except in compliance with the License.
8
*
9
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
* or https://opensource.org/licenses/CDDL-1.0.
11
* See the License for the specific language governing permissions
12
* and limitations under the License.
13
*
14
* When distributing Covered Code, include this CDDL HEADER in each
15
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
* If applicable, add the following below this CDDL HEADER, with the
17
* fields enclosed by brackets "[]" replaced with your own identifying
18
* information: Portions Copyright [yyyy] [name of copyright owner]
19
*
20
* CDDL HEADER END
21
*/
22
/*
23
* Copyright (c) 2024, Rob Norris <[email protected]>
24
* Copyright (c) 2024, Klara Inc.
25
*/
26
27
#include <sys/backtrace.h>
28
#include <sys/types.h>
29
#include <sys/debug.h>
30
#include <unistd.h>
31
32
/*
33
* Output helpers. libspl_backtrace() must not block, must be thread-safe and
34
* must be safe to call from a signal handler. At least, that means not having
35
* printf, so we end up having to call write() directly on the fd. That's
36
* awkward, as we always have to pass through a length, and some systems will
37
* complain if we don't consume the return. So we have some macros to make
38
* things a little more palatable.
39
*/
40
#define spl_bt_write_n(fd, s, n) \
41
do { ssize_t r __maybe_unused = write(fd, s, n); } while (0)
42
#define spl_bt_write(fd, s) spl_bt_write_n(fd, s, sizeof (s)-1)
43
44
#ifdef HAVE_LIBUNWIND
45
/*
46
* libunwind-gcc and libunwind-llvm both list registers using an enum,
47
* unw_regnum_t, however they indicate the highest numbered register for
48
* a given architecture in different ways. We can check which one is defined
49
* and mark which libunwind is in use
50
*/
51
#ifdef IS_LIBUNWIND_LLVM
52
#include <libunwind.h>
53
#define LAST_REG_INDEX _LIBUNWIND_HIGHEST_DWARF_REGISTER
54
#else
55
/*
56
* Need to define UNW_LOCAL_ONLY before importing libunwind.h
57
* if using libgcc libunwind.
58
*/
59
#define UNW_LOCAL_ONLY
60
#include <libunwind.h>
61
#define LAST_REG_INDEX UNW_TDEP_LAST_REG
62
#endif
63
64
65
/*
66
* Convert `v` to ASCII hex characters. The bottom `n` nybbles (4-bits ie one
67
* hex digit) will be written, up to `buflen`. The buffer will not be
68
* null-terminated. Returns the number of digits written.
69
*/
70
static size_t
71
spl_bt_u64_to_hex_str(uint64_t v, size_t n, char *buf, size_t buflen)
72
{
73
static const char hexdigits[] = {
74
'0', '1', '2', '3', '4', '5', '6', '7',
75
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
76
};
77
78
size_t pos = 0;
79
boolean_t want = (n == 0);
80
for (int i = 15; i >= 0; i--) {
81
const uint64_t d = v >> (i * 4) & 0xf;
82
if (!want && (d != 0 || n > i))
83
want = B_TRUE;
84
if (want) {
85
buf[pos++] = hexdigits[d];
86
if (pos == buflen)
87
break;
88
}
89
}
90
return (pos);
91
}
92
93
void
94
libspl_backtrace(int fd)
95
{
96
unw_context_t uc;
97
unw_cursor_t cp;
98
unw_word_t v;
99
char buf[128];
100
size_t n;
101
int err;
102
103
/* Snapshot the current frame and state. */
104
unw_getcontext(&uc);
105
106
/*
107
* TODO: walk back to the frame that tripped the assertion / the place
108
* where the signal was recieved.
109
*/
110
111
/*
112
* Register dump. We're going to loop over all the registers in the
113
* top frame, and show them, with names, in a nice three-column
114
* layout, which keeps us within 80 columns.
115
*/
116
spl_bt_write(fd, "Registers:\n");
117
118
/* Initialise a frame cursor, starting at the current frame */
119
unw_init_local(&cp, &uc);
120
121
/*
122
* Iterate over all registers for the architecture. We've figured
123
* out the highest number above, however, not all register numbers in
124
* this range are defined by the architecture, and not all defined
125
* registers will be present on every implementation of that
126
* architecture. Moreover, libunwind provides nice names for most, but
127
* not all registers, but these are hardcoded; a name being available
128
* does not mean that register is available.
129
*
130
* So, we have to pull this all together here. We try to get the value
131
* of every possible register. If we get a value for it, then the
132
* register must exist, and so we get its name. If libunwind has no
133
* name for it, we synthesize something. These cases should be rare,
134
* and they're usually for uninteresting or niche registers, so it
135
* shouldn't really matter. We can see the value, and that's the main
136
* thing.
137
*/
138
uint_t cols = 0;
139
for (uint_t regnum = 0; regnum <= LAST_REG_INDEX; regnum++) {
140
/*
141
* Get the value. Any error probably means the register
142
* doesn't exist, and we skip it. LLVM libunwind iterates over
143
* fp registers in the same list, however they have to be
144
* accessed using unw_get_fpreg instead. Here, we just ignore
145
* them.
146
*/
147
#ifdef IS_LIBUNWIND_LLVM
148
if (unw_is_fpreg(&cp, regnum) ||
149
unw_get_reg(&cp, regnum, &v) < 0)
150
continue;
151
#else
152
if (unw_get_reg(&cp, regnum, &v) < 0)
153
continue;
154
#endif
155
156
/*
157
* Register name. If GCC libunwind doesn't have a name for it,
158
* it will return "???". As a shortcut, we just treat '?'
159
* is an alternate end-of-string character. LLVM libunwind will
160
* return the string 'unknown register', which we detect by
161
* checking if the register name is longer than 5 characters.
162
*/
163
#ifdef IS_LIBUNWIND_LLVM
164
const char *name = unw_regname(&cp, regnum);
165
#else
166
const char *name = unw_regname(regnum);
167
#endif
168
for (n = 0; name[n] != '\0' && name[n] != '?'; n++) {}
169
if (n == 0 || n > 5) {
170
/*
171
* No valid name, or likely llvm_libunwind returned
172
* unknown_register, so make one of the form "?xx",
173
* where "xx" is the two-char hex of libunwind's
174
* register number.
175
*/
176
buf[0] = '?';
177
n = spl_bt_u64_to_hex_str(regnum, 2,
178
&buf[1], sizeof (buf)-1) + 1;
179
name = buf;
180
}
181
182
/*
183
* Two spaces of padding before each column, plus extra
184
* spaces to align register names shorter than three chars.
185
*/
186
spl_bt_write_n(fd, " ", 5-MIN(n, 3));
187
188
/* Register name and column punctuation */
189
spl_bt_write_n(fd, name, n);
190
spl_bt_write(fd, ": 0x");
191
192
/*
193
* Convert register value (from unw_get_reg()) to hex. We're
194
* assuming that all registers are 64-bits wide, which is
195
* probably fine for any general-purpose registers on any
196
* machine currently in use. A more generic way would be to
197
* look at the width of unw_word_t, but that would also
198
* complicate the column code a bit. This is fine.
199
*/
200
n = spl_bt_u64_to_hex_str(v, 16, buf, sizeof (buf));
201
spl_bt_write_n(fd, buf, n);
202
203
/* Every third column, emit a newline */
204
if (!(++cols % 3))
205
spl_bt_write(fd, "\n");
206
}
207
208
/* If we finished before the third column, emit a newline. */
209
if (cols % 3)
210
spl_bt_write(fd, "\n");
211
212
/* Now the main event, the backtrace. */
213
spl_bt_write(fd, "Call trace:\n");
214
215
/* Reset the cursor to the top again. */
216
unw_init_local(&cp, &uc);
217
218
do {
219
/*
220
* Getting the IP should never fail; libunwind handles it
221
* specially, because its used a lot internally. Still, no
222
* point being silly about it, as the last thing we want is
223
* our crash handler to crash. So if it ever does fail, we'll
224
* show an error line, but keep going to the next frame.
225
*/
226
if (unw_get_reg(&cp, UNW_REG_IP, &v) < 0) {
227
spl_bt_write(fd, " [couldn't get IP register; "
228
"corrupt frame?]");
229
continue;
230
}
231
232
/* IP & punctuation */
233
n = spl_bt_u64_to_hex_str(v, 16, buf, sizeof (buf));
234
spl_bt_write(fd, " [0x");
235
spl_bt_write_n(fd, buf, n);
236
spl_bt_write(fd, "] ");
237
238
/*
239
* Function ("procedure") name for the current frame. `v`
240
* receives the offset from the named function to the IP, which
241
* we show as a "+offset" suffix.
242
*
243
* If libunwind can't determine the name, we just show "???"
244
* instead. We've already displayed the IP above; that will
245
* have to do.
246
*
247
* unw_get_proc_name() will return ENOMEM if the buffer is too
248
* small, instead truncating the name. So we treat that as a
249
* success and use whatever is in the buffer.
250
*/
251
err = unw_get_proc_name(&cp, buf, sizeof (buf), &v);
252
if (err == 0 || err == -UNW_ENOMEM) {
253
for (n = 0; n < sizeof (buf) && buf[n] != '\0'; n++) {}
254
spl_bt_write_n(fd, buf, n);
255
256
/* Offset from proc name */
257
spl_bt_write(fd, "+0x");
258
n = spl_bt_u64_to_hex_str(v, 2, buf, sizeof (buf));
259
spl_bt_write_n(fd, buf, n);
260
} else
261
spl_bt_write(fd, "???");
262
263
#ifdef HAVE_LIBUNWIND_ELF
264
/*
265
* Newer libunwind has unw_get_elf_filename(), which gets
266
* the name of the ELF object that the frame was executing in.
267
* Like `unw_get_proc_name()`, `v` recieves the offset within
268
* the file, and UNW_ENOMEM indicates that a truncate filename
269
* was left in the buffer.
270
*/
271
err = unw_get_elf_filename(&cp, buf, sizeof (buf), &v);
272
if (err == 0 || err == -UNW_ENOMEM) {
273
for (n = 0; n < sizeof (buf) && buf[n] != '\0'; n++) {}
274
spl_bt_write(fd, " (in ");
275
spl_bt_write_n(fd, buf, n);
276
277
/* Offset within file */
278
spl_bt_write(fd, " +0x");
279
n = spl_bt_u64_to_hex_str(v, 2, buf, sizeof (buf));
280
spl_bt_write_n(fd, buf, n);
281
spl_bt_write(fd, ")");
282
}
283
#endif
284
spl_bt_write(fd, "\n");
285
} while (unw_step(&cp) > 0);
286
}
287
#elif defined(HAVE_BACKTRACE)
288
#include <execinfo.h>
289
290
void
291
libspl_backtrace(int fd)
292
{
293
void *btptrs[64];
294
size_t nptrs = backtrace(btptrs, 64);
295
spl_bt_write(fd, "Call trace:\n");
296
backtrace_symbols_fd(btptrs, nptrs, fd);
297
}
298
#else
299
void
300
libspl_backtrace(int fd __maybe_unused)
301
{
302
}
303
#endif
304
305