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  * 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);
   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);
  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) == 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  * Two print routines -- one for use from DDB and DDB-like contexts, the
  169  * other for use in the live kernel.
  170  */
  171 void
  172 stack_sbuf_print(struct sbuf *sb, const struct stack *st)
  173 {
  174         char namebuf[64];
  175         long offset;
  176         int i;
  177 
  178         KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
  179         for (i = 0; i < st->depth; i++) {
  180                 (void)stack_symbol(st->pcs[i], namebuf, sizeof(namebuf),
  181                     &offset);
  182                 sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i],
  183                     namebuf, offset);
  184         }
  185 }
  186 
  187 #if defined(DDB) || defined(WITNESS)
  188 void
  189 stack_sbuf_print_ddb(struct sbuf *sb, const struct stack *st)
  190 {
  191         const char *name;
  192         long offset;
  193         int i;
  194 
  195         KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
  196         for (i = 0; i < st->depth; i++) {
  197                 (void)stack_symbol_ddb(st->pcs[i], &name, &offset);
  198                 sbuf_printf(sb, "#%d %p at %s+%#lx\n", i, (void *)st->pcs[i],
  199                     name, offset);
  200         }
  201 }
  202 #endif
  203 
  204 #ifdef KTR
  205 void
  206 stack_ktr(u_int mask, const char *file, int line, const struct stack *st,
  207     u_int depth, int cheap)
  208 {
  209 #ifdef DDB
  210         const char *name;
  211         long offset;
  212         int i;
  213 #endif
  214 
  215         KASSERT(st->depth <= STACK_MAX, ("bogus stack"));
  216         if (cheap) {
  217                 ktr_tracepoint(mask, file, line, "#0 %p %p %p %p %p %p",
  218                     st->pcs[0], st->pcs[1], st->pcs[2], st->pcs[3],
  219                     st->pcs[4], st->pcs[5]);
  220                 if (st->depth <= 6)
  221                         return;
  222                 ktr_tracepoint(mask, file, line, "#1 %p %p %p %p %p %p",
  223                     st->pcs[6], st->pcs[7], st->pcs[8], st->pcs[9],
  224                     st->pcs[10], st->pcs[11]);
  225                 if (st->depth <= 12)
  226                         return;
  227                 ktr_tracepoint(mask, file, line, "#2 %p %p %p %p %p %p",
  228                     st->pcs[12], st->pcs[13], st->pcs[14], st->pcs[15],
  229                     st->pcs[16], st->pcs[17]);
  230 #ifdef DDB
  231         } else {
  232                 if (depth == 0 || st->depth < depth)
  233                         depth = st->depth;
  234                 for (i = 0; i < depth; i++) {
  235                         (void)stack_symbol_ddb(st->pcs[i], &name, &offset);
  236                         ktr_tracepoint(mask, file, line, "#%d %p at %s+%#lx",
  237                             i, st->pcs[i], (u_long)name, offset, 0, 0);
  238                 }
  239 #endif
  240         }
  241 }
  242 #endif
  243 
  244 /*
  245  * Two variants of stack symbol lookup -- one that uses the DDB interfaces
  246  * and bypasses linker locking, and the other that doesn't.
  247  */
  248 static int
  249 stack_symbol(vm_offset_t pc, char *namebuf, u_int buflen, long *offset)
  250 {
  251 
  252         if (linker_search_symbol_name((caddr_t)pc, namebuf, buflen,
  253             offset) != 0) {
  254                 *offset = 0;
  255                 strlcpy(namebuf, "??", buflen);
  256                 return (ENOENT);
  257         } else
  258                 return (0);
  259 }
  260 
  261 static int
  262 stack_symbol_ddb(vm_offset_t pc, const char **name, long *offset)
  263 {
  264         linker_symval_t symval;
  265         c_linker_sym_t sym;
  266 
  267         if (linker_ddb_search_symbol((caddr_t)pc, &sym, offset) != 0)
  268                 goto out;
  269         if (linker_ddb_symbol_values(sym, &symval) != 0)
  270                 goto out;
  271         if (symval.name != NULL) {
  272                 *name = symval.name;
  273                 return (0);
  274         }
  275  out:
  276         *offset = 0;
  277         *name = "??";
  278         return (ENOENT);
  279 }

Cache object: da077aa782117ef069b6b2855e6c7516


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