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/sparc64/sparc64/db_trace.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) 2001 Jake Burkholder.
    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  * $FreeBSD: releng/5.2/sys/sparc64/sparc64/db_trace.c 119291 2003-08-22 07:39:05Z imp $
   27  */
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/linker_set.h>
   32 #include <sys/proc.h>
   33 #include <sys/sysent.h>
   34 #include <sys/user.h>
   35 
   36 #include <vm/vm.h>
   37 #include <vm/vm_page.h>
   38 #include <vm/vm_map.h>
   39 
   40 #include <machine/cpu.h>
   41 #include <machine/trap.h>
   42 #include <machine/vmparam.h>
   43 
   44 #include <ddb/ddb.h>
   45 #include <ddb/db_access.h>
   46 #include <ddb/db_sym.h>
   47 #include <ddb/db_variables.h>
   48 #include <ddb/db_watch.h>
   49 
   50 static int db_print_trap(struct thread *td, struct trapframe *);
   51 static void db_utrace(struct thread *td, struct trapframe *tf);
   52 
   53 #define INKERNEL(va) \
   54         ((va) >= VM_MIN_KERNEL_ADDRESS && (va) <= VM_MAX_KERNEL_ADDRESS)
   55 
   56 struct  db_variable db_regs[] = {
   57         { "g0", &ddb_regs.tf_global[0], FCN_NULL },
   58         { "g1", &ddb_regs.tf_global[1], FCN_NULL },
   59         { "g2", &ddb_regs.tf_global[2], FCN_NULL },
   60         { "g3", &ddb_regs.tf_global[3], FCN_NULL },
   61         { "g4", &ddb_regs.tf_global[4], FCN_NULL },
   62         { "g5", &ddb_regs.tf_global[5], FCN_NULL },
   63         { "g6", &ddb_regs.tf_global[6], FCN_NULL },
   64         { "g7", &ddb_regs.tf_global[7], FCN_NULL },
   65         { "i0", &ddb_regs.tf_out[0], FCN_NULL },
   66         { "i1", &ddb_regs.tf_out[1], FCN_NULL },
   67         { "i2", &ddb_regs.tf_out[2], FCN_NULL },
   68         { "i3", &ddb_regs.tf_out[3], FCN_NULL },
   69         { "i4", &ddb_regs.tf_out[4], FCN_NULL },
   70         { "i5", &ddb_regs.tf_out[5], FCN_NULL },
   71         { "i6", &ddb_regs.tf_out[6], FCN_NULL },
   72         { "i7", &ddb_regs.tf_out[7], FCN_NULL },
   73         { "tnpc", &ddb_regs.tf_tnpc, FCN_NULL },
   74         { "tpc", &ddb_regs.tf_tpc, FCN_NULL },
   75         { "tstate", &ddb_regs.tf_tstate, FCN_NULL },
   76 };
   77 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
   78 
   79 void
   80 db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
   81                    char *modif)
   82 {
   83         struct trapframe *tf;
   84         struct frame *fp;
   85         struct proc *p;
   86         struct thread *td;
   87         const char *name;
   88         c_db_sym_t sym;
   89         db_expr_t offset;
   90         db_expr_t value;
   91         db_addr_t npc;
   92         db_addr_t pc;
   93         int trap;
   94         int user;
   95         pid_t pid;
   96 
   97         trap = 0;
   98         user = 0;
   99         npc = 0;
  100         if (count == -1)
  101                 count = 1024;
  102         td = curthread;
  103         p = td->td_proc;
  104         /*
  105          * Provide an /a modifier to pass the stack address instead of a PID
  106          * as argument.
  107          * Note that, if this address is not on the stack of curthread, the
  108          * printed data may be wrong (at the moment, this applies only to the
  109          * sysent list).
  110          */
  111         if (!have_addr)
  112                 addr = DDB_REGS->tf_out[6];
  113         else if (strcmp(modif, "a") != 0) {
  114                 /*
  115                  * addr was parsed as hex, convert so it is interpreted as
  116                  * decimal (ugh).
  117                  */
  118                 pid = (addr % 16) + ((addr >> 4) % 16) * 10 +
  119                     ((addr >> 8) % 16) * 100 + ((addr >> 12) % 16) * 1000 +
  120                     ((addr >> 16) % 16) * 10000;
  121                 /*
  122                  * The pcb for curproc is not valid at this point,
  123                  * so fall back to the default case.
  124                  */
  125                 if (pid == curthread->td_proc->p_pid) {
  126                         td = curthread;
  127                         p = td->td_proc;
  128                         addr = DDB_REGS->tf_out[6];
  129                 } else {
  130                         /* sx_slock(&allproc_lock); */
  131                         LIST_FOREACH(p, &allproc, p_list) {
  132                                 if (p->p_pid == pid)
  133                                         break;
  134                         }
  135                         /* sx_sunlock(&allproc_lock); */
  136                         if (p == NULL) {
  137                                 db_printf("pid %d not found\n", pid);
  138                                 return;
  139                         }
  140                         if ((p->p_sflag & PS_INMEM) == 0) {
  141                                 db_printf("pid %d swapped out\n", pid);
  142                                 return;
  143                         }
  144                         td = FIRST_THREAD_IN_PROC(p);   /* XXXKSE */
  145                         addr = td->td_pcb->pcb_sp;
  146                 }
  147         }
  148         fp = (struct frame *)(addr + SPOFF);
  149 
  150         while (count-- && !user) {
  151                 pc = (db_addr_t)db_get_value((db_addr_t)&fp->fr_pc,
  152                     sizeof(fp->fr_pc), FALSE);
  153                 if (trap) {
  154                         pc = npc;
  155                         trap = 0;
  156                 }
  157                 if (!INKERNEL((vm_offset_t)pc))
  158                         break;
  159                 sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
  160                 if (sym == C_DB_SYM_NULL) {
  161                         value = 0;
  162                         name = NULL;
  163                 } else
  164                         db_symbol_values(sym, &name, &value);
  165                 if (name == NULL)
  166                         name = "(null)";
  167                 fp = (struct frame *)(db_get_value((db_addr_t)&fp->fr_fp,
  168                    sizeof(fp->fr_fp), FALSE) + SPOFF);
  169                 if (bcmp(name, "tl0_", 4) == 0 ||
  170                     bcmp(name, "tl1_", 4) == 0) {
  171                         tf = (struct trapframe *)(fp + 1);
  172                         npc = db_get_value((db_addr_t)&tf->tf_tpc,
  173                             sizeof(tf->tf_tpc), FALSE);
  174                         user = db_print_trap(td, tf);
  175                         trap = 1;
  176                 } else {
  177                         db_printf("%s() at ", name);
  178                         db_printsym(pc, DB_STGY_PROC);
  179                         db_printf("\n");
  180                 }
  181         }
  182 }
  183 
  184 static int
  185 db_print_trap(struct thread *td, struct trapframe *tf)
  186 {
  187         struct proc *p;
  188         const char *symname;
  189         c_db_sym_t sym;
  190         db_expr_t diff;
  191         db_addr_t func;
  192         db_addr_t tpc;
  193         u_long type;
  194         u_long sfar;
  195         u_long sfsr;
  196         u_long tar;
  197         u_long level;
  198         u_long pil;
  199         u_long code;
  200         u_long o7;
  201         int user;
  202 
  203         p = td->td_proc;
  204         type = db_get_value((db_addr_t)&tf->tf_type,
  205             sizeof(tf->tf_type), FALSE);
  206         db_printf("-- %s", trap_msg[type & ~T_KERNEL]);
  207         switch (type & ~T_KERNEL) {
  208         case T_DATA_PROTECTION:
  209                 tar = (u_long)db_get_value((db_addr_t)&tf->tf_tar,
  210                     sizeof(tf->tf_tar), FALSE);
  211                 db_printf(" tar=%#lx", tar);
  212                 /* fall through */
  213         case T_DATA_EXCEPTION:
  214         case T_INSTRUCTION_EXCEPTION:
  215         case T_MEM_ADDRESS_NOT_ALIGNED:
  216                 sfar = (u_long)db_get_value((db_addr_t)&tf->tf_sfar,
  217                     sizeof(tf->tf_sfar), FALSE);
  218                 sfsr = (u_long)db_get_value((db_addr_t)&tf->tf_sfsr,
  219                     sizeof(tf->tf_sfsr), FALSE);
  220                 db_printf(" sfar=%#lx sfsr=%#lx", sfar, sfsr);
  221                 break;
  222         case T_DATA_MISS:
  223         case T_INSTRUCTION_MISS:
  224                 tar = (u_long)db_get_value((db_addr_t)&tf->tf_tar,
  225                     sizeof(tf->tf_tar), FALSE);
  226                 db_printf(" tar=%#lx", tar);
  227                 break;
  228         case T_SYSCALL:
  229                 code = db_get_value((db_addr_t)&tf->tf_global[1],
  230                     sizeof(tf->tf_global[1]), FALSE);
  231                 db_printf(" (%ld", code);
  232                 if (code >= 0 && code < p->p_sysent->sv_size) {
  233                         func = (db_addr_t)p->p_sysent->sv_table[code].sy_call;
  234                         sym = db_search_symbol(func, DB_STGY_ANY, &diff);
  235                         if (sym != DB_SYM_NULL && diff == 0) {
  236                                 db_symbol_values(sym, &symname, NULL);
  237                                 db_printf(", %s, %s", p->p_sysent->sv_name,
  238                                     symname);
  239                         }
  240                         db_printf(")");
  241                 }
  242                 break;
  243         case T_INTERRUPT:
  244                 level = (u_long)db_get_value((db_addr_t)&tf->tf_level,
  245                     sizeof(tf->tf_level), FALSE);
  246                 pil = (u_long)db_get_value((db_addr_t)&tf->tf_pil,
  247                     sizeof(tf->tf_pil), FALSE);
  248                 db_printf(" level=%#lx pil=%#lx", level, pil);
  249                 break;
  250         default:
  251                 break;
  252         }
  253         o7 = (u_long)db_get_value((db_addr_t)&tf->tf_out[7],
  254             sizeof(tf->tf_out[7]), FALSE);
  255         db_printf(" %%o7=%#lx --\n", o7);
  256         user = (type & T_KERNEL) == 0;
  257         if (user) {
  258                 tpc = db_get_value((db_addr_t)&tf->tf_tpc,
  259                     sizeof(tf->tf_tpc), FALSE);
  260                 db_printf("userland() at ");
  261                 db_printsym(tpc, DB_STGY_PROC);
  262                 db_printf("\n");
  263                 db_utrace(td, tf);
  264         }
  265         return (user);
  266 }
  267 
  268 /*
  269  * User stack trace (debugging aid).
  270  */
  271 static void
  272 db_utrace(struct thread *td, struct trapframe *tf)
  273 {
  274         struct pcb *pcb;
  275         db_addr_t sp, rsp, o7, pc;
  276         int i, found;
  277 
  278         pcb = td->td_pcb;
  279         sp = db_get_value((db_addr_t)&tf->tf_sp, sizeof(tf->tf_sp), FALSE);
  280         o7 = db_get_value((db_addr_t)&tf->tf_out[7], sizeof(tf->tf_out[7]),
  281             FALSE);
  282         pc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(tf->tf_tpc), FALSE);
  283         db_printf("user trace: trap %%o7=%#lx\n", o7);
  284         while (sp != 0) {
  285                 db_printf("pc %#lx, sp %#lx\n", pc, sp);
  286                 /* First, check whether the frame is in the pcb. */
  287                 found = 0;
  288                 for (i = 0; i < pcb->pcb_nsaved; i++) {
  289                         if (pcb->pcb_rwsp[i] == sp) {
  290                                 found = 1;
  291                                 sp = pcb->pcb_rw[i].rw_in[6];
  292                                 pc = pcb->pcb_rw[i].rw_in[7];
  293                                 break;
  294                         }
  295                 }
  296                 if (!found) {
  297                         rsp = sp + SPOFF;
  298                         sp = NULL;
  299                         if (copyin((void *)(rsp + offsetof(struct frame, fr_fp)),
  300                             &sp, sizeof(sp)) != 0 ||
  301                             copyin((void *)(rsp + offsetof(struct frame, fr_pc)),
  302                             &pc, sizeof(pc)) != 0)
  303                                 break;
  304                 }
  305         }
  306         db_printf("done\n");
  307 }
  308 
  309 void
  310 db_print_backtrace(void)
  311 {
  312         u_long *sp;
  313 
  314         sp = __builtin_frame_address(1);
  315         db_stack_trace_cmd((db_expr_t)sp, TRUE, -1, "a");
  316 }

Cache object: 384eb369ed426824c3e98ee4fb6fdf8d


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