subr_stack.c revision 159022
119370Spst/*- 298944Sobrien * Copyright (c) 2005 Antoine Brodin 3130803Smarcel * All rights reserved. 419370Spst * 519370Spst * Redistribution and use in source and binary forms, with or without 698944Sobrien * modification, are permitted provided that the following conditions 719370Spst * are met: 898944Sobrien * 1. Redistributions of source code must retain the above copyright 998944Sobrien * notice, this list of conditions and the following disclaimer. 1098944Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1198944Sobrien * notice, this list of conditions and the following disclaimer in the 1219370Spst * documentation and/or other materials provided with the distribution. 1398944Sobrien * 1498944Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1598944Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1698944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1719370Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1898944Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1998944Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2098944Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2198944Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2219370Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2319370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24130803Smarcel * SUCH DAMAGE. 2519370Spst */ 2619370Spst 2719370Spst#include <sys/cdefs.h> 2819370Spst__FBSDID("$FreeBSD: head/sys/kern/subr_stack.c 159022 2006-05-28 22:15:28Z kris $"); 2919370Spst 3019370Spst#include <sys/param.h> 3119370Spst#include <sys/kernel.h> 3219370Spst#ifdef KTR 3319370Spst#include <sys/ktr.h> 3419370Spst#endif 3519370Spst#include <sys/linker.h> 3698944Sobrien#include <sys/malloc.h> 3719370Spst#include <sys/sbuf.h> 3819370Spst#include <sys/stack.h> 3919370Spst#include <sys/systm.h> 4019370Spst 4146283SdfrMALLOC_DEFINE(M_STACK, "stack", "Stack Traces"); 4246283Sdfr 4346283Sdfrstatic void stack_symbol(vm_offset_t pc, const char **name, long *offset); 44130803Smarcel 4598944Sobrienstruct stack * 4698944Sobrienstack_create(void) 4719370Spst{ 4898944Sobrien struct stack *st; 4919370Spst 5098944Sobrien st = malloc(sizeof *st, M_STACK, M_WAITOK | M_ZERO); 5119370Spst return (st); 52130803Smarcel} 53130803Smarcel 5446283Sdfrvoid 5598944Sobrienstack_destroy(struct stack *st) 5698944Sobrien{ 5798944Sobrien 5819370Spst free(st, M_STACK); 5919370Spst} 6019370Spst 6119370Spstint 6219370Spststack_put(struct stack *st, vm_offset_t pc) 6319370Spst{ 6419370Spst 6598944Sobrien if (st->depth < STACK_MAX) { 6698944Sobrien st->pcs[st->depth++] = pc; 6719370Spst return (0); 68130803Smarcel } else 6919370Spst return (-1); 70130803Smarcel} 7119370Spst 7219370Spstvoid 7319370Spststack_copy(struct stack *src, struct stack *dst) 7419370Spst{ 7519370Spst 7619370Spst *dst = *src; 7719370Spst} 7819370Spst 7998944Sobrienvoid 8098944Sobrienstack_zero(struct stack *st) 8119370Spst{ 8219370Spst 8319370Spst bzero(st, sizeof *st); 8419370Spst} 8519370Spst 8619370Spstvoid 8719370Spststack_print(struct stack *st) 8819370Spst{ 89130803Smarcel const char *name; 90130803Smarcel long offset; 9119370Spst int i; 9246283Sdfr 9346283Sdfr KASSERT(st->depth <= STACK_MAX, ("bogus stack")); 9446283Sdfr for (i = 0; i < st->depth; i++) { 9519370Spst stack_symbol(st->pcs[i], &name, &offset); 9646283Sdfr printf("#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], 9798944Sobrien name, offset); 9819370Spst } 9998944Sobrien} 10046283Sdfr 10119370Spstvoid 10219370Spststack_sbuf_print(struct sbuf *sb, struct stack *st) 10398944Sobrien{ 10419370Spst const char *name; 10519370Spst long offset; 10619370Spst int i; 10719370Spst 10898944Sobrien KASSERT(st->depth <= STACK_MAX, ("bogus stack")); 10998944Sobrien for (i = 0; i < st->depth; i++) { 11098944Sobrien stack_symbol(st->pcs[i], &name, &offset); 11119370Spst sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i], 11219370Spst name, offset); 11319370Spst } 11498944Sobrien} 11598944Sobrien 11698944Sobrien#ifdef KTR 11719370Spstvoid 11819370Spststack_ktr(u_int mask, const char *file, int line, struct stack *st, u_int depth, 11919370Spst int cheap) 12019370Spst{ 12198944Sobrien const char *name; 12298944Sobrien long offset; 12398944Sobrien int i; 12419370Spst 12519370Spst KASSERT(st->depth <= STACK_MAX, ("bogus stack")); 12646283Sdfr if (cheap) { 12746283Sdfr ktr_tracepoint(mask, file, line, "#0 %p %p %p %p %p %p", 12846283Sdfr st->pcs[0], st->pcs[1], st->pcs[2], st->pcs[3], 12946283Sdfr st->pcs[4], st->pcs[5]); 13019370Spst if (st->depth <= 6) 13119370Spst return; 13298944Sobrien ktr_tracepoint(mask, file, line, "#1 %p %p %p %p %p %p", 13319370Spst st->pcs[6], st->pcs[7], st->pcs[8], st->pcs[9], 13419370Spst st->pcs[10], st->pcs[11]); 13519370Spst if (st->depth <= 12) 13619370Spst return; 13719370Spst ktr_tracepoint(mask, file, line, "#2 %p %p %p %p %p %p", 13819370Spst st->pcs[12], st->pcs[13], st->pcs[14], st->pcs[15], 13919370Spst st->pcs[16], st->pcs[17]); 14019370Spst } else { 14198944Sobrien if (depth == 0 || st->depth < depth) 14298944Sobrien depth = st->depth; 14398944Sobrien for (i = 0; i < depth; i++) { 14419370Spst stack_symbol(st->pcs[i], &name, &offset); 14519370Spst ktr_tracepoint(mask, file, line, "#%d %p at %s+%#lx", 14619370Spst i, st->pcs[i], (u_long)name, offset, 0, 0); 14719370Spst } 14819370Spst } 14919370Spst} 15019370Spst#endif 15119370Spst 152130803Smarcelstatic void 15346283Sdfrstack_symbol(vm_offset_t pc, const char **name, long *offset) 15498944Sobrien{ 15598944Sobrien linker_symval_t symval; 156130803Smarcel c_linker_sym_t sym; 15798944Sobrien 15846283Sdfr if (linker_ddb_search_symbol((caddr_t)pc, &sym, offset) != 0) 159130803Smarcel goto out; 160130803Smarcel if (linker_ddb_symbol_values(sym, &symval) != 0) 161130803Smarcel goto out; 16246283Sdfr if (symval.name != NULL) { 16398944Sobrien *name = symval.name; 16446283Sdfr return; 16546283Sdfr } 16646283Sdfrout: 167130803Smarcel *offset = 0; 168130803Smarcel *name = "Unknown func"; 169130803Smarcel} 170130803Smarcel