subr_stack.c revision 148666
1148666Sjeff/*- 2148666Sjeff * Copyright (c) 2005 Antoine Brodin 3148666Sjeff * All rights reserved. 4148666Sjeff * 5148666Sjeff * Redistribution and use in source and binary forms, with or without 6148666Sjeff * modification, are permitted provided that the following conditions 7148666Sjeff * are met: 8148666Sjeff * 1. Redistributions of source code must retain the above copyright 9148666Sjeff * notice, this list of conditions and the following disclaimer. 10148666Sjeff * 2. Redistributions in binary form must reproduce the above copyright 11148666Sjeff * notice, this list of conditions and the following disclaimer in the 12148666Sjeff * documentation and/or other materials provided with the distribution. 13148666Sjeff * 14148666Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15148666Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16148666Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17148666Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18148666Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19148666Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20148666Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21148666Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22148666Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23148666Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24148666Sjeff * SUCH DAMAGE. 25148666Sjeff */ 26148666Sjeff 27148666Sjeff#include <sys/cdefs.h> 28148666Sjeff__FBSDID("$FreeBSD: head/sys/kern/subr_stack.c 148666 2005-08-03 04:27:40Z jeff $"); 29148666Sjeff 30148666Sjeff#include <sys/param.h> 31148666Sjeff#include <sys/kernel.h> 32148666Sjeff#ifdef KTR 33148666Sjeff#include <sys/ktr.h> 34148666Sjeff#endif 35148666Sjeff#include <sys/linker.h> 36148666Sjeff#include <sys/malloc.h> 37148666Sjeff#include <sys/sbuf.h> 38148666Sjeff#include <sys/stack.h> 39148666Sjeff#include <sys/systm.h> 40148666Sjeff 41148666SjeffMALLOC_DEFINE(M_STACK, "stack", "Stack Traces"); 42148666Sjeff 43148666Sjeffstatic void stack_symbol(vm_offset_t pc, const char **name, long *offset); 44148666Sjeff 45148666Sjeffstruct stack * 46148666Sjeffstack_create(void) 47148666Sjeff{ 48148666Sjeff struct stack *st; 49148666Sjeff 50148666Sjeff st = malloc(sizeof *st, M_STACK, M_WAITOK | M_ZERO); 51148666Sjeff return (st); 52148666Sjeff} 53148666Sjeff 54148666Sjeffvoid 55148666Sjeffstack_destroy(struct stack *st) 56148666Sjeff{ 57148666Sjeff 58148666Sjeff free(st, M_STACK); 59148666Sjeff} 60148666Sjeff 61148666Sjeffint 62148666Sjeffstack_put(struct stack *st, vm_offset_t pc) 63148666Sjeff{ 64148666Sjeff 65148666Sjeff if (st->depth < STACK_MAX) { 66148666Sjeff st->pcs[st->depth++] = pc; 67148666Sjeff return (0); 68148666Sjeff } else 69148666Sjeff return (-1); 70148666Sjeff} 71148666Sjeff 72148666Sjeffvoid 73148666Sjeffstack_copy(struct stack *src, struct stack *dst) 74148666Sjeff{ 75148666Sjeff 76148666Sjeff *dst = *src; 77148666Sjeff} 78148666Sjeff 79148666Sjeffvoid 80148666Sjeffstack_zero(struct stack *st) 81148666Sjeff{ 82148666Sjeff 83148666Sjeff bzero(st, sizeof *st); 84148666Sjeff} 85148666Sjeff 86148666Sjeffvoid 87148666Sjeffstack_print(struct stack *st) 88148666Sjeff{ 89148666Sjeff const char *name; 90148666Sjeff long offset; 91148666Sjeff int i; 92148666Sjeff 93148666Sjeff KASSERT(st->depth <= STACK_MAX, ("bogous stack")); 94148666Sjeff for (i = 0; i < st->depth; i++) { 95148666Sjeff stack_symbol(st->pcs[i], &name, &offset); 96148666Sjeff printf("#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], 97148666Sjeff name, offset); 98148666Sjeff } 99148666Sjeff} 100148666Sjeff 101148666Sjeffvoid 102148666Sjeffstack_sbuf_print(struct sbuf *sb, struct stack *st) 103148666Sjeff{ 104148666Sjeff const char *name; 105148666Sjeff long offset; 106148666Sjeff int i; 107148666Sjeff 108148666Sjeff KASSERT(st->depth <= STACK_MAX, ("bogous stack")); 109148666Sjeff for (i = 0; i < st->depth; i++) { 110148666Sjeff stack_symbol(st->pcs[i], &name, &offset); 111148666Sjeff sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], 112148666Sjeff name, offset); 113148666Sjeff } 114148666Sjeff} 115148666Sjeff 116148666Sjeff#ifdef KTR 117148666Sjeffvoid 118148666Sjeffstack_ktr(u_int mask, const char *file, int line, struct stack *st, int cheap) 119148666Sjeff{ 120148666Sjeff const char *name; 121148666Sjeff long offset; 122148666Sjeff int i; 123148666Sjeff 124148666Sjeff KASSERT(st->depth <= STACK_MAX, ("bogous stack")); 125148666Sjeff if (cheap) { 126148666Sjeff ktr_tracepoint(mask, file, line, "#0 %p %p %p %p %p %p", 127148666Sjeff st->pcs[0], st->pcs[1], st->pcs[2], st->pcs[3], 128148666Sjeff st->pcs[4], st->pcs[5]); 129148666Sjeff if (st->depth <= 6) 130148666Sjeff return; 131148666Sjeff ktr_tracepoint(mask, file, line, "#1 %p %p %p %p %p %p", 132148666Sjeff st->pcs[6], st->pcs[7], st->pcs[8], st->pcs[9], 133148666Sjeff st->pcs[10], st->pcs[11]); 134148666Sjeff if (st->depth <= 12) 135148666Sjeff return; 136148666Sjeff ktr_tracepoint(mask, file, line, "#2 %p %p %p %p %p %p", 137148666Sjeff st->pcs[12], st->pcs[13], st->pcs[14], st->pcs[15], 138148666Sjeff st->pcs[16], st->pcs[17]); 139148666Sjeff } else 140148666Sjeff for (i = 0; i < st->depth; i++) { 141148666Sjeff stack_symbol(st->pcs[i], &name, &offset); 142148666Sjeff ktr_tracepoint(mask, file, line, "#%d %p at %s+%#lx", 143148666Sjeff i, st->pcs[i], (u_long)name, offset, 0, 0); 144148666Sjeff } 145148666Sjeff} 146148666Sjeff#endif 147148666Sjeff 148148666Sjeffstatic void 149148666Sjeffstack_symbol(vm_offset_t pc, const char **name, long *offset) 150148666Sjeff{ 151148666Sjeff linker_symval_t symval; 152148666Sjeff c_linker_sym_t sym; 153148666Sjeff 154148666Sjeff if (linker_ddb_search_symbol((caddr_t)pc, &sym, offset) != 0) 155148666Sjeff goto out; 156148666Sjeff if (linker_ddb_symbol_values(sym, &symval) != 0) 157148666Sjeff goto out; 158148666Sjeff if (symval.name != NULL) { 159148666Sjeff *name = symval.name; 160148666Sjeff return; 161148666Sjeff } 162148666Sjeffout: 163148666Sjeff *offset = 0; 164148666Sjeff *name = "Unknown func"; 165148666Sjeff} 166