1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2005 Antoine Brodin 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "opt_ddb.h" 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/kernel.h> 36 #ifdef KTR 37 #include <sys/ktr.h> 38 #endif 39 #include <sys/linker.h> 40 #include <sys/malloc.h> 41 #include <sys/sbuf.h> 42 #include <sys/stack.h> 43 #include <sys/systm.h> 44 #include <sys/sysctl.h> 45 46 FEATURE(stack, "Support for capturing kernel stack"); 47 48 static MALLOC_DEFINE(M_STACK, "stack", "Stack Traces"); 49 50 static int stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen, 51 long *offset, int flags); 52 static int stack_symbol_ddb(vm_offset_t pc, const char **name, long *offset); 53 54 struct stack * 55 stack_create(int flags) 56 { 57 struct stack *st; 58 59 st = malloc(sizeof(*st), M_STACK, flags | M_ZERO); 60 return (st); 61 } 62 63 void 64 stack_destroy(struct stack *st) 65 { 66 67 free(st, M_STACK); 68 } 69 70 int 71 stack_put(struct stack *st, vm_offset_t pc) 72 { 73 74 if (st->depth < STACK_MAX) { 75 st->pcs[st->depth++] = pc; 76 return (0); 77 } else 78 return (-1); 79 } 80 81 void 82 stack_copy(const struct stack *src, struct stack *dst) 83 { 84 85 *dst = *src; 86 } 87 88 void 89 stack_zero(struct stack *st) 90 { 91 92 bzero(st, sizeof *st); 93 } 94 95 void 96 stack_print(const struct stack *st) 97 { 98 char namebuf[64]; 99 long offset; 100 int i; 101 102 KASSERT(st->depth <= STACK_MAX, ("bogus stack")); 103 for (i = 0; i < st->depth; i++) { 104 (void)stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), 105 &offset, M_WAITOK); 106 printf("#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], 107 namebuf, offset); 108 } 109 } 110 111 void 112 stack_print_short(const struct stack *st) 113 { 114 char namebuf[64]; 115 long offset; 116 int i; 117 118 KASSERT(st->depth <= STACK_MAX, ("bogus stack")); 119 for (i = 0; i < st->depth; i++) { 120 if (i > 0) 121 printf(" "); 122 if (stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), 123 &offset, M_WAITOK) == 0) 124 printf("%s+%#lx", namebuf, offset); 125 else 126 printf("%p", (void *)st->pcs[i]); 127 } 128 printf("\n"); 129 } 130 131 void 132 stack_print_ddb(const struct stack *st) 133 { 134 const char *name; 135 long offset; 136 int i; 137 138 KASSERT(st->depth <= STACK_MAX, ("bogus stack")); 139 for (i = 0; i < st->depth; i++) { 140 stack_symbol_ddb(st->pcs[i], &name, &offset); 141 printf("#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], 142 name, offset); 143 } 144 } 145 146 #if defined(DDB) || defined(WITNESS) 147 void 148 stack_print_short_ddb(const struct stack *st) 149 { 150 const char *name; 151 long offset; 152 int i; 153 154 KASSERT(st->depth <= STACK_MAX, ("bogus stack")); 155 for (i = 0; i < st->depth; i++) { 156 if (i > 0) 157 printf(" "); 158 if (stack_symbol_ddb(st->pcs[i], &name, &offset) == 0) 159 printf("%s+%#lx", name, offset); 160 else 161 printf("%p", (void *)st->pcs[i]); 162 } 163 printf("\n"); 164 } 165 #endif 166 167 /* 168 * Format stack into sbuf from live kernel. 169 * 170 * flags - M_WAITOK or M_NOWAIT (EWOULDBLOCK). 171 */ 172 int 173 stack_sbuf_print_flags(struct sbuf *sb, const struct stack *st, int flags) 174 { 175 char namebuf[64]; 176 long offset; 177 int i, error; 178 179 KASSERT(st->depth <= STACK_MAX, ("bogus stack")); 180 for (i = 0; i < st->depth; i++) { 181 error = stack_symbol(st->pcs[i], namebuf, sizeof(namebuf), 182 &offset, flags); 183 if (error == EWOULDBLOCK) 184 return (error); 185 sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], 186 namebuf, offset); 187 } 188 return (0); 189 } 190 191 void 192 stack_sbuf_print(struct sbuf *sb, const struct stack *st) 193 { 194 195 (void)stack_sbuf_print_flags(sb, st, M_WAITOK); 196 } 197 198 #if defined(DDB) || defined(WITNESS) 199 void 200 stack_sbuf_print_ddb(struct sbuf *sb, const struct stack *st) 201 { 202 const char *name; 203 long offset; 204 int i; 205 206 KASSERT(st->depth <= STACK_MAX, ("bogus stack")); 207 for (i = 0; i < st->depth; i++) { 208 (void)stack_symbol_ddb(st->pcs[i], &name, &offset); 209 sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], 210 name, offset); 211 } 212 } 213 #endif 214 215 #ifdef KTR 216 void 217 stack_ktr(u_int mask, const char *file, int line, const struct stack *st, 218 u_int depth) 219 { 220 #ifdef DDB 221 const char *name; 222 long offset; 223 int i; 224 #endif 225 226 KASSERT(st->depth <= STACK_MAX, ("bogus stack")); 227 #ifdef DDB 228 if (depth == 0 || st->depth < depth) 229 depth = st->depth; 230 for (i = 0; i < depth; i++) { 231 (void)stack_symbol_ddb(st->pcs[i], &name, &offset); 232 ktr_tracepoint(mask, file, line, "#%d %p at %s+%#lx", 233 i, st->pcs[i], (u_long)name, offset, 0, 0); 234 } 235 #endif 236 } 237 #endif 238 239 /* 240 * Two variants of stack symbol lookup -- one that uses the DDB interfaces 241 * and bypasses linker locking, and the other that doesn't. 242 */ 243 static int 244 stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen, long *offset, 245 int flags) 246 { 247 int error; 248 249 error = linker_search_symbol_name_flags((caddr_t)pc, namebuf, buflen, 250 offset, flags); 251 if (error == 0 || error == EWOULDBLOCK) 252 return (error); 253 254 *offset = 0; 255 strlcpy(namebuf, "??", buflen); 256 return (ENOENT); 257 } 258 259 static int 260 stack_symbol_ddb(vm_offset_t pc, const char **name, long *offset) 261 { 262 linker_symval_t symval; 263 c_linker_sym_t sym; 264 265 if (linker_ddb_search_symbol((caddr_t)pc, &sym, offset) != 0) 266 goto out; 267 if (linker_ddb_symbol_values(sym, &symval) != 0) 268 goto out; 269 if (symval.name != NULL) { 270 *name = symval.name; 271 return (0); 272 } 273 out: 274 *offset = 0; 275 *name = "??"; 276 return (ENOENT); 277 } 278