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/osfmk/i386/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) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  * @OSF_COPYRIGHT@
   27  */
   28 /* 
   29  * Mach Operating System
   30  * Copyright (c) 1991,1990 Carnegie Mellon University
   31  * All Rights Reserved.
   32  * 
   33  * Permission to use, copy, modify and distribute this software and its
   34  * documentation is hereby granted, provided that both the copyright
   35  * notice and this permission notice appear in all copies of the
   36  * software, derivative works or modified versions, and any portions
   37  * thereof, and that both notices appear in supporting documentation.
   38  * 
   39  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   40  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   41  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   42  * 
   43  * Carnegie Mellon requests users of this software to return to
   44  * 
   45  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   46  *  School of Computer Science
   47  *  Carnegie Mellon University
   48  *  Pittsburgh PA 15213-3890
   49  * 
   50  * any improvements or extensions that they make and grant Carnegie Mellon
   51  * the rights to redistribute these changes.
   52  */
   53 /*
   54  */
   55 
   56 #include <string.h>
   57 
   58 #include <mach/boolean.h>
   59 #include <vm/vm_map.h>
   60 #include <kern/thread.h>
   61 #include <kern/task.h>
   62 
   63 #include <machine/asm.h>
   64 #include <machine/db_machdep.h>
   65 #include <machine/setjmp.h>
   66 #include <mach/machine.h>
   67 
   68 #include <ddb/db_access.h>
   69 #include <ddb/db_sym.h>
   70 #include <ddb/db_variables.h>
   71 #include <ddb/db_command.h>
   72 #include <ddb/db_task_thread.h>
   73 #include <ddb/db_output.h>
   74 
   75 extern jmp_buf_t *db_recover;
   76 extern struct i386_saved_state *saved_state[];
   77 
   78 struct i386_kernel_state ddb_null_kregs;
   79 
   80 /*
   81  * Stack trace.
   82  */
   83 
   84 extern vm_offset_t vm_min_inks_addr;    /* set by db_clone_symtabXXX */
   85 #define INKSERVER(va)   (((vm_offset_t)(va)) >= vm_min_inks_addr)
   86 
   87 #if     NCPUS > 1
   88 extern vm_offset_t interrupt_stack[];
   89 #define ININTSTACK(va)                                          \
   90         (((vm_offset_t)(va)) >= interrupt_stack[cpu_number()] &&\
   91          (((vm_offset_t)(va)) < interrupt_stack[cpu_number()] + \
   92                                 INTSTACK_SIZE))
   93 #else   /* NCPUS > 1 */
   94 extern  char intstack[];
   95 #define ININTSTACK(va)                                          \
   96         (((vm_offset_t)(va)) >= (vm_offset_t)intstack &&        \
   97          (((vm_offset_t)(va)) < ((vm_offset_t)&intstack) +      \
   98                                 INTSTACK_SIZE))
   99 #endif  /* NCPUS > 1 */
  100 
  101 #define INKERNELSTACK(va, th)                                   \
  102         (th == THR_ACT_NULL ||                          \
  103          (((vm_offset_t)(va)) >= th->thread->kernel_stack &&    \
  104           (((vm_offset_t)(va)) < th->thread->kernel_stack +     \
  105                                  KERNEL_STACK_SIZE)) ||         \
  106          ININTSTACK(va))
  107 
  108 struct i386_frame {
  109         struct i386_frame       *f_frame;
  110         int                     f_retaddr;
  111         int                     f_arg0;
  112 };
  113 
  114 #define TRAP            1
  115 #define INTERRUPT       2
  116 #define SYSCALL         3
  117 
  118 db_addr_t       db_user_trap_symbol_value = 0;
  119 db_addr_t       db_kernel_trap_symbol_value = 0;
  120 db_addr_t       db_interrupt_symbol_value = 0;
  121 db_addr_t       db_return_to_iret_symbol_value = 0;
  122 db_addr_t       db_syscall_symbol_value = 0;
  123 boolean_t       db_trace_symbols_found = FALSE;
  124 
  125 struct i386_kregs {
  126         char    *name;
  127         int     offset;
  128 } i386_kregs[] = {
  129         { "ebx", (int)(&((struct i386_kernel_state *)0)->k_ebx) },
  130         { "esp", (int)(&((struct i386_kernel_state *)0)->k_esp) },
  131         { "ebp", (int)(&((struct i386_kernel_state *)0)->k_ebp) },
  132         { "edi", (int)(&((struct i386_kernel_state *)0)->k_edi) },
  133         { "esi", (int)(&((struct i386_kernel_state *)0)->k_esi) },
  134         { "eip", (int)(&((struct i386_kernel_state *)0)->k_eip) },
  135         { 0 },
  136 };
  137 
  138 /* Forward */
  139 
  140 extern int *    db_lookup_i386_kreg(
  141                         char                    *name,
  142                         int                     *kregp);
  143 extern int      db_i386_reg_value(
  144                         struct db_variable      * vp,
  145                         db_expr_t               * val,
  146                         int                     flag,
  147                         db_var_aux_param_t      ap);
  148 extern void     db_find_trace_symbols(void);
  149 extern int      db_numargs(
  150                         struct i386_frame       *fp,
  151                         task_t                  task);
  152 extern void     db_nextframe(
  153                         struct i386_frame       **lfp,
  154                         struct i386_frame       **fp,
  155                         db_addr_t               *ip,
  156                         int                     frame_type,
  157                         thread_act_t            thr_act);
  158 extern int      _setjmp(
  159                         jmp_buf_t               * jb);
  160 
  161 /*
  162  * Machine register set.
  163  */
  164 struct db_variable db_regs[] = {
  165         { "cs", (int *)&ddb_regs.cs,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
  166         { "ds", (int *)&ddb_regs.ds,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
  167         { "es", (int *)&ddb_regs.es,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
  168         { "fs", (int *)&ddb_regs.fs,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
  169         { "gs", (int *)&ddb_regs.gs,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
  170         { "ss", (int *)&ddb_regs.ss,  db_i386_reg_value, 0, 0, 0, 0, TRUE },
  171         { "eax",(int *)&ddb_regs.eax, db_i386_reg_value, 0, 0, 0, 0, TRUE },
  172         { "ecx",(int *)&ddb_regs.ecx, db_i386_reg_value, 0, 0, 0, 0, TRUE },
  173         { "edx",(int *)&ddb_regs.edx, db_i386_reg_value, 0, 0, 0, 0, TRUE },
  174         { "ebx",(int *)&ddb_regs.ebx, db_i386_reg_value, 0, 0, 0, 0, TRUE },
  175         { "esp",(int *)&ddb_regs.uesp,db_i386_reg_value, 0, 0, 0, 0, TRUE },
  176         { "ebp",(int *)&ddb_regs.ebp, db_i386_reg_value, 0, 0, 0, 0, TRUE },
  177         { "esi",(int *)&ddb_regs.esi, db_i386_reg_value, 0, 0, 0, 0, TRUE },
  178         { "edi",(int *)&ddb_regs.edi, db_i386_reg_value, 0, 0, 0, 0, TRUE },
  179         { "eip",(int *)&ddb_regs.eip, db_i386_reg_value, 0, 0, 0, 0, TRUE },
  180         { "efl",(int *)&ddb_regs.efl, db_i386_reg_value, 0, 0, 0, 0, TRUE },
  181 };
  182 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
  183 
  184 int *
  185 db_lookup_i386_kreg(
  186         char    *name,
  187         int     *kregp)
  188 {
  189         register struct i386_kregs *kp;
  190 
  191         for (kp = i386_kregs; kp->name; kp++) {
  192             if (strcmp(name, kp->name) == 0)
  193                 return((int *)((int)kregp + kp->offset));
  194         }
  195         return(0);
  196 }
  197         
  198 int
  199 db_i386_reg_value(
  200         struct  db_variable     *vp,
  201         db_expr_t               *valuep,
  202         int                     flag,
  203         db_var_aux_param_t      ap)
  204 {
  205         extern char             etext;
  206         int                     *dp = 0;
  207         db_expr_t               null_reg = 0;
  208         register thread_act_t   thr_act = ap->thr_act;
  209         extern unsigned         int_stack_high;
  210         int                     cpu;
  211 
  212         if (db_option(ap->modif, 'u')) {
  213             if (thr_act == THR_ACT_NULL) {
  214                 if ((thr_act = current_act()) == THR_ACT_NULL)
  215                     db_error("no user registers\n");
  216             }
  217             if (thr_act == current_act()) {
  218                 if (IS_USER_TRAP(&ddb_regs, &etext))
  219                     dp = vp->valuep;
  220                 else if (ddb_regs.ebp < int_stack_high)
  221                     db_error("cannot get/set user registers in nested interrupt\n");
  222             }
  223         } else {
  224             if (thr_act == THR_ACT_NULL || thr_act == current_act()) {
  225                 dp = vp->valuep;
  226             } else {
  227               if (thr_act->thread &&
  228                   !(thr_act->thread->state & TH_STACK_HANDOFF) && 
  229                         thr_act->thread->kernel_stack) {
  230                 int cpu;
  231 
  232                 for (cpu = 0; cpu < NCPUS; cpu++) {
  233                     if (machine_slot[cpu].running == TRUE &&
  234                         cpu_data[cpu].active_thread == thr_act->thread && saved_state[cpu]) {
  235                         dp = (int *) (((int)saved_state[cpu]) +
  236                                       (((int) vp->valuep) -
  237                                        (int) &ddb_regs));
  238                         break;
  239                     }
  240                 }
  241                 if (dp == 0 && thr_act && thr_act->thread)
  242                     dp = db_lookup_i386_kreg(vp->name,
  243                          (int *)(STACK_IKS(thr_act->thread->kernel_stack)));
  244                 if (dp == 0)
  245                     dp = &null_reg;
  246               } else if (thr_act->thread &&
  247                          (thr_act->thread->state&TH_STACK_HANDOFF)){
  248                 /* only EIP is valid */
  249                 if (vp->valuep == (int *) &ddb_regs.eip) {
  250                     dp = (int *)(&thr_act->thread->continuation);
  251                 } else {
  252                     dp = &null_reg;
  253                 }
  254               }
  255             }
  256         }
  257         if (dp == 0) {
  258             int cpu;
  259 
  260             if (!db_option(ap->modif, 'u')) {
  261                 for (cpu = 0; cpu < NCPUS; cpu++) {
  262                     if (machine_slot[cpu].running == TRUE &&
  263                         cpu_data[cpu].active_thread == thr_act->thread && saved_state[cpu]) {
  264                             dp = (int *) (((int)saved_state[cpu]) +
  265                                           (((int) vp->valuep) -
  266                                            (int) &ddb_regs));
  267                             break;
  268                     }
  269                 }
  270             }
  271             if (dp == 0) {
  272                 if (!thr_act || thr_act->mact.pcb == 0)
  273                     db_error("no pcb\n");
  274                 dp = (int *)((int)(&thr_act->mact.pcb->iss) + 
  275                              ((int)vp->valuep - (int)&ddb_regs));
  276             }
  277         }
  278         if (flag == DB_VAR_SET)
  279             *dp = *valuep;
  280         else
  281             *valuep = *dp;
  282         return(0);
  283 }
  284 
  285 void
  286 db_find_trace_symbols(void)
  287 {
  288         db_expr_t       value;
  289         boolean_t       found_some;
  290 
  291         found_some = FALSE;
  292         if (db_value_of_name(CC_SYM_PREFIX "user_trap", &value)) {
  293             db_user_trap_symbol_value = (db_addr_t) value;
  294             found_some = TRUE;
  295         }
  296         if (db_value_of_name(CC_SYM_PREFIX "kernel_trap", &value)) {
  297             db_kernel_trap_symbol_value = (db_addr_t) value;
  298             found_some = TRUE;
  299         }
  300         if (db_value_of_name(CC_SYM_PREFIX "interrupt", &value)) {
  301             db_interrupt_symbol_value = (db_addr_t) value;
  302             found_some = TRUE;
  303         }
  304         if (db_value_of_name(CC_SYM_PREFIX "return_to_iret", &value)) {
  305             db_return_to_iret_symbol_value = (db_addr_t) value;
  306             found_some = TRUE;
  307         }
  308         if (db_value_of_name(CC_SYM_PREFIX "syscall", &value)) {
  309             db_syscall_symbol_value = (db_addr_t) value;
  310             found_some = TRUE;
  311         }
  312         if (found_some) 
  313             db_trace_symbols_found = TRUE;
  314 }
  315 
  316 /*
  317  * Figure out how many arguments were passed into the frame at "fp".
  318  */
  319 int db_numargs_default = 5;
  320 
  321 int
  322 db_numargs(
  323         struct i386_frame       *fp,
  324         task_t                  task)
  325 {
  326         int     *argp;
  327         int     inst;
  328         int     args;
  329         extern char     etext;
  330 
  331         argp = (int *)db_get_task_value((int)&fp->f_retaddr, 4, FALSE, task);
  332         if (argp < (int *)VM_MIN_KERNEL_ADDRESS || (char *)argp > &etext)
  333             args = db_numargs_default;
  334         else if (!DB_CHECK_ACCESS((int)argp, 4, task))
  335             args = db_numargs_default;
  336         else {
  337             inst = db_get_task_value((int)argp, 4, FALSE, task);
  338             if ((inst & 0xff) == 0x59)  /* popl %ecx */
  339                 args = 1;
  340             else if ((inst & 0xffff) == 0xc483) /* addl %n, %esp */
  341                 args = ((inst >> 16) & 0xff) / 4;
  342             else
  343                 args = db_numargs_default;
  344         }
  345         return (args);
  346 }
  347 
  348 struct interrupt_frame {
  349         struct i386_frame *if_frame;    /* point to next frame */
  350         int               if_retaddr;   /* return address to _interrupt */
  351         int               if_unit;      /* unit number */
  352         int               if_spl;       /* saved spl */
  353         int               if_iretaddr;  /* _return_to_{iret,iret_i} */
  354         int               if_edx;       /* old sp(iret) or saved edx(iret_i) */
  355         int               if_ecx;       /* saved ecx(iret_i) */
  356         int               if_eax;       /* saved eax(iret_i) */
  357         int               if_eip;       /* saved eip(iret_i) */
  358         int               if_cs;        /* saved cs(iret_i) */
  359         int               if_efl;       /* saved efl(iret_i) */
  360 };
  361 
  362 /* 
  363  * Figure out the next frame up in the call stack.  
  364  * For trap(), we print the address of the faulting instruction and 
  365  *   proceed with the calling frame.  We return the ip that faulted.
  366  *   If the trap was caused by jumping through a bogus pointer, then
  367  *   the next line in the backtrace will list some random function as 
  368  *   being called.  It should get the argument list correct, though.  
  369  *   It might be possible to dig out from the next frame up the name
  370  *   of the function that faulted, but that could get hairy.
  371  */
  372 void
  373 db_nextframe(
  374         struct i386_frame       **lfp,          /* in/out */
  375         struct i386_frame       **fp,           /* in/out */
  376         db_addr_t               *ip,            /* out */
  377         int                     frame_type,     /* in */
  378         thread_act_t            thr_act)        /* in */
  379 {
  380         extern char *   trap_type[];
  381         extern int      TRAP_TYPES;
  382 
  383         struct i386_saved_state *saved_regs;
  384         struct interrupt_frame *ifp;
  385         struct i386_interrupt_state *isp;
  386         task_t task = (thr_act != THR_ACT_NULL)? thr_act->task: TASK_NULL;
  387 
  388         switch(frame_type) {
  389         case TRAP:
  390             /*
  391              * We know that trap() has 1 argument and we know that
  392              * it is an (strcut i386_saved_state *).
  393              */
  394             saved_regs = (struct i386_saved_state *)
  395                         db_get_task_value((int)&((*fp)->f_arg0),4,FALSE,task);
  396             if (saved_regs->trapno >= 0 && saved_regs->trapno < TRAP_TYPES) {
  397                 db_printf(">>>>> %s trap at ",
  398                         trap_type[saved_regs->trapno]);
  399             } else {
  400                 db_printf(">>>>> trap (number %d) at ",
  401                         saved_regs->trapno & 0xffff);
  402             }
  403             db_task_printsym(saved_regs->eip, DB_STGY_PROC, task);
  404             db_printf(" <<<<<\n");
  405             *fp = (struct i386_frame *)saved_regs->ebp;
  406             *ip = (db_addr_t)saved_regs->eip;
  407             break;
  408         case INTERRUPT:
  409             if (*lfp == 0) {
  410                 db_printf(">>>>> interrupt <<<<<\n");
  411                 goto miss_frame;
  412             }
  413             db_printf(">>>>> interrupt at "); 
  414             ifp = (struct interrupt_frame *)(*lfp);
  415             *fp = ifp->if_frame;
  416             if (ifp->if_iretaddr == db_return_to_iret_symbol_value)
  417                 *ip = ((struct i386_interrupt_state *) ifp->if_edx)->eip;
  418             else
  419                 *ip = (db_addr_t) ifp->if_eip;
  420             db_task_printsym(*ip, DB_STGY_PROC, task);
  421             db_printf(" <<<<<\n");
  422             break;
  423         case SYSCALL:
  424             if (thr_act != THR_ACT_NULL && thr_act->mact.pcb) {
  425                 *ip = (db_addr_t) thr_act->mact.pcb->iss.eip;
  426                 *fp = (struct i386_frame *) thr_act->mact.pcb->iss.ebp;
  427                 break;
  428             }
  429             /* falling down for unknown case */
  430         default:
  431         miss_frame:
  432             *ip = (db_addr_t)
  433                 db_get_task_value((int)&(*fp)->f_retaddr, 4, FALSE, task);
  434             *lfp = *fp;
  435             *fp = (struct i386_frame *)
  436                 db_get_task_value((int)&(*fp)->f_frame, 4, FALSE, task);
  437             break;
  438         }
  439 }
  440 
  441 void
  442 db_stack_trace_cmd(
  443         db_expr_t       addr,
  444         boolean_t       have_addr,
  445         db_expr_t       count,
  446         char            *modif)
  447 {
  448         struct i386_frame *frame, *lastframe;
  449         int             *argp;
  450         db_addr_t       callpc, lastcallpc;
  451         int             frame_type;
  452         boolean_t       kernel_only = TRUE;
  453         boolean_t       trace_thread = FALSE;
  454         boolean_t       trace_all_threads = FALSE;
  455         int             thcount = 0;
  456         char            *filename;
  457         int             linenum;
  458         task_t          task;
  459         thread_act_t    th, top_act;
  460         int             user_frame;
  461         int             frame_count;
  462         jmp_buf_t       *prev;
  463         jmp_buf_t       db_jmp_buf;
  464         queue_entry_t   act_list;
  465 
  466         if (!db_trace_symbols_found)
  467             db_find_trace_symbols();
  468 
  469         {
  470             register char *cp = modif;
  471             register char c;
  472 
  473             while ((c = *cp++) != 0) {
  474                 if (c == 't')
  475                     trace_thread = TRUE;
  476                 if (c == 'T') {
  477                     trace_all_threads = TRUE;
  478                     trace_thread = TRUE;
  479                 }
  480                 if (c == 'u')
  481                     kernel_only = FALSE;
  482             }
  483         }
  484 
  485         if (trace_all_threads) {
  486             if (!have_addr && !trace_thread) {
  487                 have_addr = TRUE;
  488                 trace_thread = TRUE;
  489                 act_list = &(current_task()->thr_acts);
  490                 addr = (db_expr_t) queue_first(act_list);
  491             } else if (trace_thread) {
  492                 if (have_addr) {
  493                     if (!db_check_act_address_valid((thread_act_t)addr)) {
  494                         if (db_lookup_task((task_t)addr) == -1)
  495                             return;
  496                         act_list = &(((task_t)addr)->thr_acts);
  497                         addr = (db_expr_t) queue_first(act_list);
  498                     } else {
  499                         act_list = &(((thread_act_t)addr)->task->thr_acts);
  500                         thcount = db_lookup_task_act(((thread_act_t)addr)->task,
  501                                                         (thread_act_t)addr);
  502                     }
  503                 } else {
  504                     th = db_default_act;
  505                     if (th == THR_ACT_NULL)
  506                         th = current_act();
  507                     if (th == THR_ACT_NULL) {
  508                         db_printf("no active thr_act\n");
  509                         return;
  510                     }
  511                     have_addr = TRUE;
  512                     act_list = &th->task->thr_acts;
  513                     addr = (db_expr_t) queue_first(act_list);
  514                 }
  515             }
  516         }
  517 
  518         if (count == -1)
  519             count = 65535;
  520 
  521     next_thread:
  522         top_act = THR_ACT_NULL;
  523 
  524         user_frame = 0;
  525         frame_count = count;
  526 
  527         if (!have_addr && !trace_thread) {
  528             frame = (struct i386_frame *)ddb_regs.ebp;
  529             callpc = (db_addr_t)ddb_regs.eip;
  530             th = current_act();
  531             task = (th != THR_ACT_NULL)? th->task: TASK_NULL;
  532         } else if (trace_thread) {
  533             if (have_addr) {
  534                 th = (thread_act_t) addr;
  535                 if (!db_check_act_address_valid(th))
  536                     return;
  537             } else {
  538                 th = db_default_act;
  539                 if (th == THR_ACT_NULL)
  540                    th = current_act();
  541                 if (th == THR_ACT_NULL) {
  542                    db_printf("no active thread\n");
  543                    return;
  544                 }
  545             }
  546             if (trace_all_threads)
  547                 db_printf("---------- Thread 0x%x (#%d of %d) ----------\n",
  548                       addr, thcount, th->task->thr_act_count);
  549 
  550         next_activation:
  551             user_frame = 0;
  552 
  553             task = th->task;
  554             if (th == current_act()) {
  555                 frame = (struct i386_frame *)ddb_regs.ebp;
  556                 callpc = (db_addr_t)ddb_regs.eip;
  557             } else {
  558                 if (th->mact.pcb == 0) {
  559                     db_printf("thread has no pcb\n");
  560                     return;
  561                 }
  562                 if (!th->thread) {
  563                     register struct i386_saved_state *iss =
  564                                                 &th->mact.pcb->iss;
  565 
  566                     db_printf("thread has no shuttle\n");
  567 #if 0
  568                     frame = (struct i386_frame *) (iss->ebp);
  569                     callpc = (db_addr_t) (iss->eip);
  570 #else
  571                     goto thread_done;
  572 #endif
  573                 }
  574                 else if ((th->thread->state & TH_STACK_HANDOFF) ||
  575                           th->thread->kernel_stack == 0) {
  576                     register struct i386_saved_state *iss =
  577                                                 &th->mact.pcb->iss;
  578 
  579                     db_printf("Continuation ");
  580                     db_task_printsym((db_expr_t)th->thread->continuation,
  581                                                         DB_STGY_PROC, task);
  582                     db_printf("\n");
  583                     frame = (struct i386_frame *) (iss->ebp);
  584                     callpc = (db_addr_t) (iss->eip);
  585                 } else {
  586                     int cpu;
  587 
  588                     for (cpu = 0; cpu < NCPUS; cpu++) {
  589                         if (machine_slot[cpu].running == TRUE &&
  590                             cpu_data[cpu].active_thread == th->thread &&
  591                             saved_state[cpu]) {
  592                             break;
  593                         }
  594                     }
  595                     if (top_act != THR_ACT_NULL) {
  596                             /*
  597                              * Trying to get the backtrace of an activation
  598                              * which is not the top_most one in the RPC chain:
  599                              * use the activation's pcb.
  600                              */
  601                             register struct i386_saved_state *iss =
  602                                 &th->mact.pcb->iss;
  603                             frame = (struct i386_frame *) (iss->ebp);
  604                             callpc = (db_addr_t) (iss->eip);
  605                     } else {
  606                         if (cpu == NCPUS) {
  607                             register struct i386_kernel_state *iks;
  608                             int r;
  609 
  610                             iks = STACK_IKS(th->thread->kernel_stack);
  611                             prev = db_recover;
  612                             if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
  613                                 frame = (struct i386_frame *) (iks->k_ebp);
  614                                 callpc = (db_addr_t) (iks->k_eip);
  615                             } else {
  616                                 /*
  617                                  * The kernel stack has probably been
  618                                  * paged out (swapped out activation).
  619                                  */
  620                                 db_recover = prev;
  621                                 if (r == 2)     /* 'q' from db_more() */
  622                                     db_error(0);
  623                                 db_printf("<kernel stack (0x%x) error "
  624                                           "(probably swapped out)>\n",
  625                                           iks);
  626                                 goto thread_done;
  627                             }
  628                             db_recover = prev;
  629                         } else {
  630                             db_printf(">>>>> active on cpu %d <<<<<\n",
  631                                       cpu);
  632                             frame = (struct i386_frame *)
  633                                 saved_state[cpu]->ebp;
  634                             callpc = (db_addr_t) saved_state[cpu]->eip;
  635                         }
  636                     }
  637                 }
  638             }
  639         } else {
  640             frame = (struct i386_frame *)addr;
  641             th = (db_default_act)? db_default_act: current_act();
  642             task = (th != THR_ACT_NULL)? th->task: TASK_NULL;
  643             callpc = (db_addr_t)db_get_task_value((int)&frame->f_retaddr,
  644                                                   4, 
  645                                                   FALSE, 
  646                                                   (user_frame) ? task : 0);
  647         }
  648 
  649         if (!INKERNELSTACK((unsigned)frame, th)) {
  650             db_printf(">>>>> user space <<<<<\n");
  651             if (kernel_only)
  652                 goto thread_done;
  653             user_frame++;
  654         } else if (INKSERVER(callpc) && INKSERVER(frame)) {
  655             db_printf(">>>>> INKserver space <<<<<\n");
  656         }
  657 
  658         lastframe = 0;
  659         lastcallpc = (db_addr_t) 0;
  660         while (frame_count-- && frame != 0) {
  661             int narg;
  662             char *      name;
  663             db_expr_t   offset;
  664             db_addr_t call_func = 0;
  665             int r;
  666 
  667             db_symbol_values(NULL,
  668                              db_search_task_symbol_and_line(
  669                                         callpc,
  670                                         DB_STGY_XTRN, 
  671                                         &offset,
  672                                         &filename,
  673                                         &linenum,
  674                                         (user_frame) ? task : 0,
  675                                         &narg),
  676                              &name, (db_expr_t *)&call_func);
  677             if (user_frame == 0) {
  678                 if (call_func == db_user_trap_symbol_value ||
  679                     call_func == db_kernel_trap_symbol_value) {
  680                     frame_type = TRAP;
  681                     narg = 1;
  682                 } else if (call_func == db_interrupt_symbol_value) {
  683                     frame_type = INTERRUPT;
  684                     goto next_frame;
  685                 } else if (call_func == db_syscall_symbol_value) {
  686                     frame_type = SYSCALL;
  687                     goto next_frame;
  688                 } else {
  689                     frame_type = 0;
  690                     prev = db_recover;
  691                     if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
  692                         if (narg < 0)
  693                             narg = db_numargs(frame,
  694                                               (user_frame) ? task : 0);
  695                         db_recover = prev;
  696                     } else {
  697                         db_recover = prev;
  698                         goto thread_done;
  699                     }
  700                 }
  701             } else {
  702                 frame_type = 0;
  703                 prev = db_recover;
  704                 if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
  705                     if (narg < 0)
  706                         narg = db_numargs(frame,
  707                                           (user_frame) ? task : 0);
  708                     db_recover = prev;
  709                 } else {
  710                     db_recover = prev;
  711                     goto thread_done;
  712                 }
  713             }
  714 
  715             if (name == 0 || offset > db_maxoff) {
  716                 db_printf("0x%x 0x%x(", frame, callpc);
  717                 offset = 0;
  718             } else
  719                 db_printf("0x%x %s(", frame, name);
  720 
  721             argp = &frame->f_arg0;
  722             while (narg > 0) {
  723                 int value;
  724 
  725                 prev = db_recover;
  726                 if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
  727                     value = db_get_task_value((int)argp,
  728                                               4,
  729                                               FALSE,
  730                                               (user_frame) ? task : 0);
  731                 } else {
  732                     db_recover = prev;
  733                     if (r == 2)         /* 'q' from db_more() */
  734                         db_error(0);
  735                     db_printf("... <stack error>)");
  736                     if (offset)
  737                         db_printf("+%x", offset);
  738                     if (filename) {
  739                         db_printf(" [%s", filename);
  740                         if (linenum > 0)
  741                             db_printf(":%d", linenum);
  742                         db_printf("]");
  743                     }
  744                     db_printf("\n");
  745                     goto thread_done;
  746                 }
  747                 db_recover = prev;
  748                 db_printf("%x", value);
  749                 argp++;
  750                 if (--narg != 0)
  751                     db_printf(",");
  752             }
  753             if (narg < 0)
  754                 db_printf("...");
  755             db_printf(")");
  756             if (offset) {
  757                 db_printf("+%x", offset);
  758             }
  759             if (filename) {
  760                 db_printf(" [%s", filename);
  761                 if (linenum > 0)
  762                     db_printf(":%d", linenum);
  763                 db_printf("]");
  764             }
  765             db_printf("\n");
  766 
  767         next_frame:
  768             lastcallpc = callpc;
  769             db_nextframe(&lastframe, &frame, &callpc, frame_type,
  770                          (user_frame) ? th : THR_ACT_NULL);
  771 
  772             if (frame == 0) {
  773                 if (th->lower != THR_ACT_NULL) {
  774                     if (top_act == THR_ACT_NULL)
  775                         top_act = th;
  776                     th = th->lower;
  777                     db_printf(">>>>> next activation 0x%x ($task%d.%d) <<<<<\n",
  778                               th,
  779                               db_lookup_task(th->task),
  780                               db_lookup_task_act(th->task, th));
  781                     goto next_activation;
  782                 }
  783                 /* end of chain */
  784                 break;
  785             }
  786             if (!INKERNELSTACK(lastframe, th) ||
  787                 !INKERNELSTACK((unsigned)frame, th))
  788                 user_frame++;
  789             if (user_frame == 1) {
  790                 db_printf(">>>>> user space <<<<<\n");
  791                 if (kernel_only)
  792                     break;
  793             } else if ((!INKSERVER(lastframe) || !INKSERVER(lastcallpc)) &&
  794                         (INKSERVER(callpc) && INKSERVER(frame))) {
  795                 db_printf(">>>>> inkserver space <<<<<\n");
  796             }
  797             if (frame <= lastframe) {
  798                 if ((INKERNELSTACK(lastframe, th) &&
  799                      !INKERNELSTACK(frame, th)) ||
  800                     (INKSERVER(lastframe) ^ INKSERVER(frame)))
  801                     continue;
  802                 db_printf("Bad frame pointer: 0x%x\n", frame);
  803                 break;
  804             }
  805         }
  806 
  807     thread_done:
  808         if (trace_all_threads) {
  809             if (top_act != THR_ACT_NULL)
  810                 th = top_act;
  811             th = (thread_act_t) queue_next(&th->thr_acts);
  812             if (! queue_end(act_list, (queue_entry_t) th)) {
  813                 db_printf("\n");
  814                 addr = (db_expr_t) th;
  815                 thcount++;
  816                 goto next_thread;
  817 
  818             }
  819         }
  820 }

Cache object: bde8d907ea3f887ee80d1ae174dd4711


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