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$");
   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 #include <sys/sysctl.h>
   43 
   44 FEATURE(stack, "Support for capturing kernel stack");
   45 
   46 static MALLOC_DEFINE(M_STACK, "stack", "Stack Traces");
   47 
   48 static int stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen,
   49             long *offset);
   50 static int stack_symbol_ddb(vm_offset_t pc, const char **name, long *offset);
   51 
   52 struct stack *
   53 stack_create(void)
   54 {
   55         struct stack *st;
   56 
   57         st = malloc(sizeof *st, M_STACK, M_WAITOK | M_ZERO);
   58         return (st);
   59 }
   60 
   61 void
   62 stack_destroy(struct stack *st)
   63 {
   64 
   65         free(st, M_STACK);
   66 }
   67 
   68 int
   69 stack_put(struct stack *st, vm_offset_t pc)
   70 {
   71 
   72         if (st->depth < STACK_MAX) {
   73                 st->pcs[st->depth++] = pc;
   74                 return (0);
   75         } else
   76                 return (-1);
   77 }
   78 
   79 void
   80 stack_copy(const struct stack *src, struct stack *dst)
   81 {
   82 
   83         *dst = *src;
   84 }
   85 
   86 void
   87 stack_zero(struct stack *st)
   88 {
   89 
   90         bzero(st, sizeof *st);
   91 }
   92 
   93 void
   94 stack_print(const struct stack *st)
   95 {
   96         char namebuf[64];
   97         long offset;
   98         int i;
   99 
  100         KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
  101         for (i = 0; i < st->depth; i++) {
  102                 (void)stack_symbol(st->pcs[i], namebuf, sizeof(namebuf),
  103                     &offset);
  104                 printf("#%d %p at %s+%#lx\n", i, (void *)st->pcs[i],
  105                     namebuf, offset);
  106         }
  107 }
  108 
  109 void
  110 stack_print_short(const struct stack *st)
  111 {
  112         char namebuf[64];
  113         long offset;
  114         int i;
  115 
  116         KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
  117         for (i = 0; i < st->depth; i++) {
  118                 if (i > 0)
  119                         printf(" ");
  120                 if (stack_symbol(st->pcs[i], namebuf, sizeof(namebuf),
  121                     &offset) == 0)
  122                         printf("%s+%#lx", namebuf, offset);
  123                 else
  124                         printf("%p", (void *)st->pcs[i]);
  125         }
  126         printf("\n");
  127 }
  128 
  129 void
  130 stack_print_ddb(const 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 #if defined(DDB) || defined(WITNESS)
  145 void
  146 stack_print_short_ddb(const struct stack *st)
  147 {
  148         const char *name;
  149         long offset;
  150         int i;
  151 
  152         KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
  153         for (i = 0; i < st->depth; i++) {
  154                 if (i > 0)
  155                         printf(" ");
  156                 if (stack_symbol_ddb(st->pcs[i], &name, &offset) == 0)
  157                         printf("%s+%#lx", name, offset);
  158                 else
  159                         printf("%p", (void *)st->pcs[i]);
  160         }
  161         printf("\n");
  162 }
  163 #endif
  164 
  165 /*
  166  * Two print routines -- one for use from DDB and DDB-like contexts, the
  167  * other for use in the live kernel.
  168  */
  169 void
  170 stack_sbuf_print(struct sbuf *sb, const struct stack *st)
  171 {
  172         char namebuf[64];
  173         long offset;
  174         int i;
  175 
  176         KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
  177         for (i = 0; i < st->depth; i++) {
  178                 (void)stack_symbol(st->pcs[i], namebuf, sizeof(namebuf),
  179                     &offset);
  180                 sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i],
  181                     namebuf, offset);
  182         }
  183 }
  184 
  185 #if defined(DDB) || defined(WITNESS)
  186 void
  187 stack_sbuf_print_ddb(struct sbuf *sb, const struct stack *st)
  188 {
  189         const char *name;
  190         long offset;
  191         int i;
  192 
  193         KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
  194         for (i = 0; i < st->depth; i++) {
  195                 (void)stack_symbol_ddb(st->pcs[i], &name, &offset);
  196                 sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i],
  197                     name, offset);
  198         }
  199 }
  200 #endif
  201 
  202 #ifdef KTR
  203 void
  204 stack_ktr(u_int mask, const char *file, int line, const struct stack *st,
  205     u_int depth, int cheap)
  206 {
  207 #ifdef DDB
  208         const char *name;
  209         long offset;
  210         int i;
  211 #endif
  212 
  213         KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
  214         if (cheap) {
  215                 ktr_tracepoint(mask, file, line, "#0 %p %p %p %p %p %p",
  216                     st->pcs[0], st->pcs[1], st->pcs[2], st->pcs[3],
  217                     st->pcs[4], st->pcs[5]);
  218                 if (st->depth <= 6)
  219                         return;
  220                 ktr_tracepoint(mask, file, line, "#1 %p %p %p %p %p %p",
  221                     st->pcs[6], st->pcs[7], st->pcs[8], st->pcs[9],
  222                     st->pcs[10], st->pcs[11]);
  223                 if (st->depth <= 12)
  224                         return;
  225                 ktr_tracepoint(mask, file, line, "#2 %p %p %p %p %p %p",
  226                     st->pcs[12], st->pcs[13], st->pcs[14], st->pcs[15],
  227                     st->pcs[16], st->pcs[17]);
  228 #ifdef DDB
  229         } else {
  230                 if (depth == 0 || st->depth < depth)
  231                         depth = st->depth;
  232                 for (i = 0; i < depth; i++) {
  233                         (void)stack_symbol_ddb(st->pcs[i], &name, &offset);
  234                         ktr_tracepoint(mask, file, line, "#%d %p at %s+%#lx",
  235                             i, st->pcs[i], (u_long)name, offset, 0, 0);
  236                 }
  237 #endif
  238         }
  239 }
  240 #endif
  241 
  242 /*
  243  * Two variants of stack symbol lookup -- one that uses the DDB interfaces
  244  * and bypasses linker locking, and the other that doesn't.
  245  */
  246 static int
  247 stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen, long *offset)
  248 {
  249 
  250         if (linker_search_symbol_name((caddr_t)pc, namebuf, buflen,
  251             offset) != 0) {
  252                 *offset = 0;
  253                 strlcpy(namebuf, "??", buflen);
  254                 return (ENOENT);
  255         } else
  256                 return (0);
  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 }

Cache object: 8a0cb1546a0367df62ec32c8decdcedc


[ 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.