The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_stack.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 2c127bc9bb5597a4ae4ac6c68883de10


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.