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 <robn@despairlabs.com> 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