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/ppc/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 #include <string.h>
   30 
   31 #include <mach/boolean.h>
   32 #include <vm/vm_map.h>
   33 #include <kern/thread.h>
   34 #include <kern/processor.h>
   35 #include <kern/task.h>
   36 
   37 #include <machine/asm.h>
   38 #include <machine/db_machdep.h>
   39 #include <machine/setjmp.h>
   40 #include <mach/machine.h>
   41 
   42 #include <ddb/db_access.h>
   43 #include <ddb/db_sym.h>
   44 #include <ddb/db_variables.h>
   45 #include <ddb/db_command.h>
   46 #include <ddb/db_task_thread.h>
   47 #include <ddb/db_output.h>
   48 
   49 extern jmp_buf_t *db_recover;
   50 extern struct savearea *saved_state[];
   51 
   52 struct savearea ddb_null_kregs;
   53 
   54 extern vm_offset_t vm_min_inks_addr;    /* set by db_clone_symtabXXX */
   55 
   56 #define DB_NUMARGS_MAX  5
   57 
   58 
   59 extern  char FixedStackStart[], FixedStackEnd[];
   60 #define INFIXEDSTACK(va)                                                        \
   61         ((((vm_offset_t)(va)) >= (vm_offset_t)&FixedStackStart) &&      \
   62         (((vm_offset_t)(va)) < ((vm_offset_t)&FixedStackEnd)))
   63 
   64 #define INKERNELSTACK(va, th) 1
   65 
   66 struct db_ppc_frame {
   67         struct db_ppc_frame     *f_frame;
   68         int                     pad1;
   69         uint32_t        f_retaddr;
   70         int                     pad3;
   71         int                     pad4;
   72         int                     pad5;
   73         uint32_t        f_arg[DB_NUMARGS_MAX];
   74 };
   75 
   76 #define TRAP            1
   77 #define INTERRUPT       2
   78 #define SYSCALL         3
   79 
   80 db_addr_t       db_user_trap_symbol_value = 0;
   81 db_addr_t       db_kernel_trap_symbol_value = 0;
   82 db_addr_t       db_interrupt_symbol_value = 0;
   83 db_addr_t       db_return_to_iret_symbol_value = 0;
   84 db_addr_t       db_syscall_symbol_value = 0;
   85 boolean_t       db_trace_symbols_found = FALSE;
   86 
   87 extern int      db_ppc_reg_value(
   88                         struct db_variable      * vp,
   89                         db_expr_t               * val,
   90                         int                     flag,
   91                         db_var_aux_param_t      ap);
   92 extern void     db_find_trace_symbols(void);
   93 extern int      db_numargs(
   94                         struct db_ppc_frame     *fp,
   95                         task_t                  task);
   96 extern boolean_t db_find_arg(
   97                         struct db_ppc_frame     *frame,
   98                         db_addr_t               calleepc,
   99                         task_t                  task,
  100                         int                     narg,
  101                         db_addr_t               *arg);
  102 extern void     db_nextframe(
  103                         struct db_ppc_frame     **lfp,
  104                         struct db_ppc_frame     **fp,
  105                         db_addr_t               *ip,
  106                         int                     frame_type,
  107                         thread_act_t            thr_act,
  108                         db_addr_t               linkpc);
  109 extern int      _setjmp(
  110                         jmp_buf_t               * jb);
  111 
  112 /*
  113  * Machine register set.
  114  */
  115 struct db_variable db_regs[] = {
  116         /* XXX "pc" is an alias to "srr0"... */
  117   { "pc",       &ddb_regs.save_srr0,    db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  118   { "srr0",     &ddb_regs.save_srr0,    db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  119   { "srr1",     &ddb_regs.save_srr1,    db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  120   { "r0",       &ddb_regs.save_r0,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  121   { "r1",       &ddb_regs.save_r1,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  122   { "r2",       &ddb_regs.save_r2,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  123   { "r3",       &ddb_regs.save_r3,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  124   { "r4",       &ddb_regs.save_r4,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  125   { "r5",       &ddb_regs.save_r5,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  126   { "r6",       &ddb_regs.save_r6,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  127   { "r7",       &ddb_regs.save_r7,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  128   { "r8",       &ddb_regs.save_r8,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  129   { "r9",       &ddb_regs.save_r9,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  130   { "r10",      &ddb_regs.save_r10,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  131   { "r11",      &ddb_regs.save_r11,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  132   { "r12",      &ddb_regs.save_r12,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  133   { "r13",      &ddb_regs.save_r13,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  134   { "r14",      &ddb_regs.save_r14,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  135   { "r15",      &ddb_regs.save_r15,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  136   { "r16",      &ddb_regs.save_r16,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  137   { "r17",      &ddb_regs.save_r17,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  138   { "r18",      &ddb_regs.save_r18,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  139   { "r19",      &ddb_regs.save_r19,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  140   { "r20",      &ddb_regs.save_r20,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  141   { "r21",      &ddb_regs.save_r21,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  142   { "r22",      &ddb_regs.save_r22,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  143   { "r23",      &ddb_regs.save_r23,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  144   { "r24",      &ddb_regs.save_r24,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  145   { "r25",      &ddb_regs.save_r25,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  146   { "r26",      &ddb_regs.save_r26,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  147   { "r27",      &ddb_regs.save_r27,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  148   { "r28",      &ddb_regs.save_r28,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  149   { "r29",      &ddb_regs.save_r29,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  150   { "r30",      &ddb_regs.save_r30,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  151   { "r31",      &ddb_regs.save_r31,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  152   { "cr",       &ddb_regs.save_cr,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  153   { "xer",      &ddb_regs.save_xer,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  154   { "lr",       &ddb_regs.save_lr,      db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  155   { "ctr",      &ddb_regs.save_ctr,     db_ppc_reg_value, 0, 0, 0, 0, TRUE },
  156 };
  157 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
  158 
  159 int
  160 db_ppc_reg_value(
  161         struct  db_variable     *vp,
  162         db_expr_t               *valuep,
  163         int                     flag,
  164         db_var_aux_param_t      ap)
  165 {
  166         db_expr_t *dp = 0;
  167         db_expr_t null_reg = 0;
  168         uint32_t *dp32;
  169         
  170         register thread_act_t   thr_act = ap->thr_act;
  171         int                     cpu;
  172 
  173         if (db_option(ap->modif, 'u')) {
  174             if (thr_act == THR_ACT_NULL) {
  175                 if ((thr_act = current_act()) == THR_ACT_NULL)
  176                     db_error("no user registers\n");
  177             }
  178             if (thr_act == current_act()) {
  179                         if (IS_USER_TRAP((&ddb_regs))) dp = vp->valuep;
  180                         else if (INFIXEDSTACK(ddb_regs.save_r1))
  181                                 db_error("cannot get/set user registers in nested interrupt\n");
  182             }
  183         } 
  184         else {
  185                 if (thr_act == THR_ACT_NULL || thr_act == current_act()) {
  186                         dp = vp->valuep;
  187                 } 
  188                 else {
  189                         if (thr_act->thread &&
  190                                 !(thr_act->thread->state & TH_STACK_HANDOFF) && 
  191                                 thr_act->thread->kernel_stack) {
  192                                 
  193                                 int cpu;
  194 
  195                                 for (cpu = 0; cpu < NCPUS; cpu++) {
  196                                         if (cpu_to_processor(cpu)->state == PROCESSOR_RUNNING &&
  197                                                 cpu_to_processor(cpu)->active_thread == thr_act->thread && saved_state[cpu]) {
  198                                                 
  199                                                 dp = (db_expr_t)(((uint32_t)saved_state[cpu]) +
  200                                                                   (((uint32_t) vp->valuep) -
  201                                                                    (uint32_t) &ddb_regs));
  202                                                 break;
  203                                         }
  204                                 }
  205 
  206                                 if (dp == 0) dp = &null_reg;
  207                         } 
  208                         else if (thr_act->thread && (thr_act->thread->state & TH_STACK_HANDOFF)){
  209                                 /* only PC is valid */
  210                                 if (vp->valuep == (int *) &ddb_regs.save_srr0) {
  211                                         dp = (int *)(&thr_act->thread->continuation);
  212                                 } 
  213                                 else {
  214                                         dp = &null_reg;
  215                                 }
  216                         }
  217             }
  218         }
  219         if (dp == 0) {
  220 
  221             if (!db_option(ap->modif, 'u')) {
  222                         for (cpu = 0; cpu < NCPUS; cpu++) {
  223                             if (cpu_to_processor(cpu)->state == PROCESSOR_RUNNING &&
  224                                 cpu_to_processor(cpu)->active_thread == thr_act->thread && saved_state[cpu]) {
  225                                     dp = (int *) (((int)saved_state[cpu]) +
  226                                                   (((int) vp->valuep) - (int) &ddb_regs));
  227                                         break;
  228                                 }
  229                         }
  230             }
  231             if (dp == 0) {
  232                         if (!thr_act || thr_act->mact.pcb == 0) db_error("no pcb\n");
  233                         dp = (int *)((int)thr_act->mact.pcb + ((int)vp->valuep - (int)&ddb_regs));
  234             }
  235         }
  236 
  237         if(vp->valuep == (int *) &ddb_regs.save_cr) {   /* Is this the CR we are doing? */
  238                 dp32 = (uint32_t *)dp;                                          /* Make this easier */
  239                 if (flag == DB_VAR_SET) *dp32 = *valuep;
  240                 else *valuep = *dp32;
  241         }
  242         else {                                                                                  /* Normal 64-bit registers */
  243                 if (flag == DB_VAR_SET) *dp = *valuep;
  244                 else *valuep = *(unsigned long long *)dp;
  245         }
  246         
  247         return(0);
  248 }
  249 
  250 
  251 void
  252 db_find_trace_symbols(void)
  253 {
  254         db_expr_t       value;
  255         boolean_t       found_some;
  256 
  257         found_some = FALSE;
  258         if (db_value_of_name(CC_SYM_PREFIX "thandler", &value)) {
  259             db_user_trap_symbol_value = (db_addr_t) value;
  260             found_some = TRUE;
  261         }
  262         if (db_value_of_name(CC_SYM_PREFIX "thandler", &value)) {
  263             db_kernel_trap_symbol_value = (db_addr_t) value;
  264             found_some = TRUE;
  265         }
  266         if (db_value_of_name(CC_SYM_PREFIX "ihandler", &value)) {
  267             db_interrupt_symbol_value = (db_addr_t) value;
  268             found_some = TRUE;
  269         }
  270 #if 0
  271         if (db_value_of_name(CC_SYM_PREFIX "return_to_iret", &value)) {
  272             db_return_to_iret_symbol_value = (db_addr_t) value;
  273             found_some = TRUE;
  274         }
  275 #endif
  276         if (db_value_of_name(CC_SYM_PREFIX "thandler", &value)) {
  277             db_syscall_symbol_value = (db_addr_t) value;
  278             found_some = TRUE;
  279         }
  280         if (found_some) 
  281             db_trace_symbols_found = TRUE;
  282 }
  283 
  284 int
  285 db_numargs(
  286         struct db_ppc_frame     *fp,
  287         task_t                  task)
  288 {
  289         return (DB_NUMARGS_MAX);
  290 }
  291 
  292 boolean_t
  293 db_find_arg(
  294         struct db_ppc_frame     *fp,
  295         db_addr_t               calleepc,
  296         task_t                  task,
  297         int                     narg,
  298         db_addr_t               *arg)
  299 {
  300         db_addr_t       argp;
  301         db_addr_t       calleep;
  302         db_addr_t       offset;
  303         int             i;
  304         int             inst;
  305         char            *name;
  306 
  307 #if     XXX_BS
  308         db_find_task_sym_and_offset(calleepc, &name, &offset, task);
  309         calleep = calleepc-offset;
  310 
  311         for (i = 0; calleep < calleepc; i++, calleep++) {
  312                 if (!DB_CHECK_ACCESS((int) calleep, 4, task)) {
  313                         continue;
  314                 }
  315                 inst = db_get_task_value(calleep, 4, FALSE, task);
  316                 if ((inst & 0xffff0000) == (0x907f0000 + (narg << 21)) ||
  317                     (inst & 0xffff0000) == (0x90610000 + (narg << 21))) {
  318                         argp = (db_addr_t) &(fp->f_arg[narg]);
  319                         *arg = argp;
  320                         return TRUE;
  321                 }
  322         }
  323 #endif
  324         return FALSE;
  325 }
  326 
  327 /* 
  328  * Figure out the next frame up in the call stack.  
  329  * For trap(), we print the address of the faulting instruction and 
  330  *   proceed with the calling frame.  We return the ip that faulted.
  331  *   If the trap was caused by jumping through a bogus pointer, then
  332  *   the next line in the backtrace will list some random function as 
  333  *   being called.  It should get the argument list correct, though.  
  334  *   It might be possible to dig out from the next frame up the name
  335  *   of the function that faulted, but that could get hairy.
  336  */
  337 void
  338 db_nextframe(
  339         struct db_ppc_frame     **lfp,          /* in/out */
  340         struct db_ppc_frame     **fp,           /* in/out */
  341         db_addr_t               *ip,            /* out */
  342         int                     frame_type,     /* in */
  343         thread_act_t            thr_act,
  344         db_addr_t               linkpc)         /* in */
  345 {
  346         extern char *   trap_type[];
  347         extern int      TRAP_TYPES;
  348 
  349         struct savearea *saved_regs;
  350 
  351         task_t task = (thr_act != THR_ACT_NULL)? thr_act->task: TASK_NULL;
  352 
  353         switch(frame_type) {
  354         case TRAP:
  355 
  356             db_printf(">>>>> trap <<<<<\n");
  357             goto miss_frame;
  358             break;
  359         case INTERRUPT:
  360             if (*lfp == 0) {
  361                 db_printf(">>>>> interrupt <<<<<\n");
  362                 goto miss_frame;
  363             }
  364             db_printf(">>>>> interrupt <<<<<\n");
  365             goto miss_frame;
  366             break;
  367         case SYSCALL:
  368             if (thr_act != THR_ACT_NULL && thr_act->mact.pcb) {
  369                 *ip = (db_addr_t) thr_act->mact.pcb->save_srr0;
  370                 *fp = (struct db_ppc_frame *) (thr_act->mact.pcb->save_r1);
  371                 break;
  372             }
  373             /* falling down for unknown case */
  374         default:
  375         miss_frame:
  376                 
  377                 if(!pmap_find_phys(kernel_pmap, (addr64_t)*fp)) {       /* Check if this is valid */
  378                         db_printf("Frame not mapped %08X\n",*fp);               /* Say not found */
  379                         *fp = 0;                                                                                /* Show not found */
  380                         break;                                                                                  /* Out of here */
  381                 }
  382                 
  383                 if ((*fp)->f_frame)
  384                     *ip = (db_addr_t)
  385                             db_get_task_value((int)&(*fp)->f_frame->f_retaddr,
  386                                               4, FALSE, task);
  387                 else
  388                         *ip = (db_addr_t) 
  389                             db_get_task_value((int)&(*fp)->f_retaddr,
  390                                               4, FALSE, task);
  391 
  392             *lfp = *fp;
  393             *fp = (struct db_ppc_frame *)
  394                 db_get_task_value((int)&(*fp)->f_frame, 4, FALSE, task);
  395             break;
  396         }
  397 }
  398 
  399 void
  400 db_stack_trace_cmd(
  401         db_expr_t       addr,
  402         boolean_t       have_addr,
  403         db_expr_t       count,
  404         char            *modif)
  405 {
  406         struct db_ppc_frame *frame, *lastframe;
  407         db_addr_t       callpc, linkpc, lastcallpc;
  408         int             frame_type;
  409         boolean_t       kernel_only = TRUE;
  410         boolean_t       trace_thread = FALSE;
  411         boolean_t       trace_all_threads = FALSE;
  412         int             thcount = 0;
  413         char            *filename;
  414         int             linenum;
  415         task_t          task;
  416         thread_act_t    th, top_act;
  417         int             user_frame;
  418         int             frame_count;
  419         jmp_buf_t       *prev;
  420         jmp_buf_t       db_jmp_buf;
  421         queue_entry_t   act_list;
  422 
  423         if (!db_trace_symbols_found)
  424             db_find_trace_symbols();
  425         {
  426             register char *cp = modif;
  427             register char c;
  428 
  429                 while ((c = *cp++) != 0) {
  430                         if (c == 't')
  431                                 trace_thread = TRUE;
  432                         if (c == 'T') {
  433                                 trace_all_threads = TRUE;
  434                                 trace_thread = TRUE;
  435                         }
  436                         if (c == 'u')
  437                                 kernel_only = FALSE;
  438                 }
  439         }
  440 
  441         if (trace_all_threads) {
  442             if (!have_addr && !trace_thread) {
  443                         have_addr = TRUE;
  444                         trace_thread = TRUE;
  445                         act_list = &(current_task()->threads);
  446                         addr = (db_expr_t) queue_first(act_list);
  447             } 
  448                 else if (trace_thread) {
  449                         if (have_addr) {
  450                                 if (!db_check_act_address_valid((thread_act_t)addr)) {
  451                                         if (db_lookup_task((task_t)addr) == -1)
  452                                                 return;
  453                                         act_list = &(((task_t)addr)->threads);
  454                                         addr = (db_expr_t) queue_first(act_list);
  455                                 } 
  456                                 else {
  457                                         act_list = &(((thread_act_t)addr)->task->threads);
  458                                         thcount = db_lookup_task_act(((thread_act_t)addr)->task,
  459                                                                         (thread_act_t)addr);
  460                                 }
  461                         } 
  462                         else {
  463                                 th = db_default_act;
  464                                 if (th == THR_ACT_NULL)
  465                                         th = current_act();
  466                                 if (th == THR_ACT_NULL) {
  467                                         db_printf("no active thr_act\n");
  468                                         return;
  469                                 }
  470                                 have_addr = TRUE;
  471                                 act_list = &th->task->threads;
  472                                 addr = (db_expr_t) queue_first(act_list);
  473                         }
  474             }
  475         }
  476 
  477         if (count == -1)
  478             count = 65535;
  479 
  480 next_thread:
  481         top_act = THR_ACT_NULL;
  482 
  483         user_frame = 0;
  484         frame_count = count;
  485 
  486         if (!have_addr && !trace_thread) {
  487             frame = (struct db_ppc_frame *)(ddb_regs.save_r1);
  488             callpc = (db_addr_t)ddb_regs.save_srr0;
  489             linkpc = (db_addr_t)ddb_regs.save_lr;
  490             th = current_act();
  491             task = (th != THR_ACT_NULL)? th->task: TASK_NULL;
  492         } 
  493         else if (trace_thread) {
  494             if (have_addr) {
  495                         th = (thread_act_t) addr;
  496                         if (!db_check_act_address_valid(th))
  497                                 return;
  498             } 
  499                 else {
  500                         th = db_default_act;
  501                         if (th == THR_ACT_NULL)
  502                            th = current_act();
  503                         if (th == THR_ACT_NULL) {
  504                            db_printf("no active thread\n");
  505                            return;
  506                         }
  507             }
  508             if (trace_all_threads)
  509                 db_printf("---------- Thread 0x%x (#%d of %d) ----------\n",
  510                           addr, thcount, th->task->thread_count);
  511 
  512 next_activation:
  513 
  514             user_frame = 0;
  515 
  516             task = th->task;
  517             if (th == current_act()) {
  518                 frame = (struct db_ppc_frame *)(ddb_regs.save_r1);
  519                 callpc = (db_addr_t)ddb_regs.save_srr0;
  520                         linkpc = (db_addr_t)ddb_regs.save_lr;
  521             } 
  522                 else {
  523                         if (th->mact.pcb == 0) {
  524                         db_printf("thread has no pcb\n");
  525                                 goto thread_done;
  526                         }
  527                         if (!th->thread) {
  528                                 register struct savearea *pss =
  529                                                         th->mact.pcb;
  530         
  531                                 db_printf("thread has no shuttle\n");
  532                                 goto thread_done;
  533                         }
  534                         else if ((th->thread->state & TH_STACK_HANDOFF) ||
  535                                   th->thread->kernel_stack == 0) {
  536                                 register struct savearea *pss =
  537                                                         th->mact.pcb;
  538         
  539                                 db_printf("Continuation ");
  540                                 db_task_printsym((db_expr_t)th->thread->continuation,
  541                                                                 DB_STGY_PROC, task);
  542                                 db_printf("\n");
  543                                 frame = (struct db_ppc_frame *) (pss->save_r1);
  544                                 callpc = (db_addr_t) (pss->save_srr0);
  545                                 linkpc = (db_addr_t) (pss->save_lr);
  546                         } 
  547                         else {
  548                                 int cpu;
  549         
  550                                 for (cpu = 0; cpu < NCPUS; cpu++) {
  551                                         if (cpu_to_processor(cpu)->state == PROCESSOR_RUNNING &&
  552                                                 cpu_to_processor(cpu)->active_thread == th->thread &&
  553                                                 saved_state[cpu]) {
  554                                                 break;
  555                                         }
  556                                 }
  557                                 if (top_act != THR_ACT_NULL) {
  558                                         /*
  559                                          * Trying to get the backtrace of an activation
  560                                          * which is not the top_most one in the RPC chain:
  561                                          * use the activation's pcb.
  562                                          */
  563                                         struct savearea *pss;
  564         
  565                                         pss = th->mact.pcb;
  566                                         frame = (struct db_ppc_frame *) (pss->save_r1);
  567                                         callpc = (db_addr_t) (pss->save_srr0);
  568                                         linkpc = (db_addr_t) (pss->save_lr);
  569                                         } else {
  570                                                 if (cpu == NCPUS) {
  571                                                         register struct savearea *iks;
  572                                                         int r;
  573                         
  574                                                         iks = th->mact.pcb;
  575                                                         prev = db_recover;
  576                                                         if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
  577                                                                 frame = (struct db_ppc_frame *) (iks->save_r1);
  578                                                                 callpc = (db_addr_t) (iks->save_lr);
  579                                                                 linkpc = 0;
  580                                                         } else {
  581                                                                 /*
  582                                                                  * The kernel stack has probably been
  583                                                                  * paged out (swapped out activation).
  584                                                                  */
  585                                                                 db_recover = prev;
  586                                                                 if (r == 2)     /* 'q' from db_more() */
  587                                                                         db_error(0);
  588                                                                 db_printf("<kernel stack (0x%x) error "
  589                                                                           "(probably swapped out)>\n",
  590                                                                           iks);
  591                                                                 goto next_act;
  592                                                         }
  593                                                         db_recover = prev;
  594                                                 } else {
  595                                                         db_printf(">>>>> active on cpu %d <<<<<\n",
  596                                                                   cpu);
  597                                                         frame = (struct db_ppc_frame *)
  598                                                         (saved_state[cpu]->save_r1);
  599                                                         callpc = (db_addr_t) saved_state[cpu]->save_srr0;
  600                                                         linkpc = (db_addr_t) saved_state[cpu]->save_lr;
  601                                                 }
  602                                         }
  603                                 }
  604             }
  605         } else {
  606             frame = (struct db_ppc_frame *)addr;
  607             th = (db_default_act)? db_default_act: current_act();
  608             task = (th != THR_ACT_NULL)? th->task: TASK_NULL;
  609             if (frame->f_frame) {
  610               callpc = (db_addr_t)db_get_task_value
  611                                 ((int)&frame->f_frame->f_retaddr,
  612                                 4, FALSE, (user_frame) ? task : 0);
  613               callpc = callpc-sizeof(callpc);
  614             } else
  615               callpc =0;
  616             linkpc = 0;
  617         }
  618 
  619         if (!INKERNELSTACK((unsigned)frame, th)) {
  620             db_printf(">>>>> user space <<<<<\n");
  621             if (kernel_only)
  622                 goto thread_done;
  623             user_frame++;
  624         }
  625         
  626         lastframe = 0;
  627         lastcallpc = (db_addr_t) 0;
  628         while (frame_count-- && frame != 0) {
  629                 int narg = DB_NUMARGS_MAX;
  630                 int arg;        
  631                 char *  name;
  632                 db_expr_t       offset;
  633                 db_addr_t call_func = 0;
  634                 int r;
  635                 db_addr_t       off;
  636 
  637                 db_symbol_values(NULL,
  638                         db_search_task_symbol_and_line(
  639                                 callpc, DB_STGY_XTRN, &offset, &filename,
  640                                 &linenum, (user_frame) ? task : 0, &narg),
  641                         &name, (db_expr_t *)&call_func);
  642                 if ( name == NULL) {
  643                         db_find_task_sym_and_offset(callpc, 
  644                                 &name, &off, (user_frame) ? task : 0);
  645                         offset = (db_expr_t) off;
  646                 }
  647 
  648                 if (user_frame == 0) {
  649                         if (call_func &&
  650                                 (call_func == db_user_trap_symbol_value ||
  651                                 call_func == db_kernel_trap_symbol_value)) {
  652                         frame_type = TRAP;
  653                         narg = 1;
  654                         } else if (call_func &&
  655                                 call_func == db_interrupt_symbol_value) {
  656                                 frame_type = INTERRUPT;
  657                                 goto next_frame;
  658                         } else if (call_func &&
  659                                 call_func == db_syscall_symbol_value) {
  660                                 frame_type = SYSCALL;
  661                                 goto next_frame;
  662                         } else {
  663                                 frame_type = 0;
  664                                 prev = db_recover;
  665                                 if ((r = _setjmp(db_recover = &db_jmp_buf)) 
  666                                                                 == 0) {
  667                                         if (narg < 0)
  668                                                 narg = db_numargs(frame,
  669                                                     (user_frame) ? task : 0);
  670                                         db_recover = prev;
  671                                 } else {
  672                                         db_recover = prev;
  673                                         goto next_act;
  674                                 }
  675                         }
  676                 } else {
  677                         frame_type = 0;
  678                         prev = db_recover;
  679                         if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
  680                                 if (narg < 0)
  681                                         narg = db_numargs(frame,
  682                                                 (user_frame) ? task : 0);
  683                                 db_recover = prev;
  684                         } else {
  685                                 db_recover = prev;
  686                                 goto next_act;
  687                         }
  688                 }
  689 
  690             if (name == 0 || offset > db_maxoff) {
  691                 db_printf("[%08X]0x%08X(", frame, callpc);
  692             } else {
  693                 db_printf("[%08X]%s", frame, name);
  694                 if (offset)
  695                         db_printf("+%x", offset);
  696                 db_printf("(");
  697            };
  698 
  699         narg = db_numargs(frame, (user_frame) ? task : 0);
  700 
  701         for (arg =0; arg < narg; arg++) {
  702                 db_addr_t       argp;
  703                 int value;
  704                 boolean_t found;
  705 
  706                 prev = db_recover;
  707                 if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
  708                         found = FALSE;
  709                         if (lastframe) 
  710                                 found = db_find_arg(frame, lastframe->f_retaddr,
  711                                         (user_frame) ? task : 0, arg, &argp);
  712                         if (found)
  713                                 value = db_get_task_value(argp, 4, FALSE,
  714                                         (user_frame) ? task : 0);
  715                 } else {
  716                         db_recover = prev;
  717                         if (r == 2)     /* 'q' from db_more() */
  718                                 db_error(0);
  719                         db_printf("... <stack error>)");
  720                         db_printf("\n");
  721                         goto next_act;
  722                 }
  723                 db_recover = prev;
  724                 if (found)
  725                         db_printf("%08X", value);
  726                 else
  727                         db_printf("??");        
  728                 argp = argp + sizeof(argp);
  729                 if (arg < narg-1)
  730                         db_printf(",");
  731             }
  732             if (arg != narg)
  733                 db_printf("...");
  734             db_printf(")");
  735             db_printf("\n");
  736 
  737         next_frame:
  738             lastcallpc = callpc;
  739             prev = db_recover;
  740             if ((r = _setjmp(db_recover = &db_jmp_buf)) == 0) {
  741                     db_nextframe(&lastframe, &frame, &callpc, frame_type,
  742                                  (user_frame) ? th : THR_ACT_NULL, linkpc);
  743                     callpc = callpc-sizeof(callpc);
  744                     db_recover = prev;
  745             } else {
  746                     db_recover = prev;
  747                     frame = 0;
  748             }
  749             linkpc = 0;
  750 
  751             if (frame == 0) {
  752         next_act:
  753                 if (th->lower != THR_ACT_NULL) {
  754                     if (top_act == THR_ACT_NULL)
  755                         top_act = th;
  756                     th = th->lower;
  757                     db_printf(">>>>> next activation 0x%x ($task%d.%d) <<<<<\n",
  758                               th,
  759                               db_lookup_task(th->task),
  760                               db_lookup_task_act(th->task, th));
  761                     goto next_activation;
  762                 }
  763                 /* end of chain */
  764                 break;
  765             }
  766             if (!INKERNELSTACK(lastframe, th) ||
  767                 !INKERNELSTACK((unsigned)frame, th))
  768                 user_frame++;
  769             if (user_frame == 1) {
  770                 db_printf(">>>>> user space <<<<<\n");
  771                 if (kernel_only)
  772                     break;
  773             }
  774                 
  775                 if (frame <= lastframe) {
  776                 if ((INKERNELSTACK(lastframe, th) && !INKERNELSTACK(frame, th))) continue;
  777                 db_printf("Bad frame pointer: 0x%x\n", frame);
  778                 break;
  779             }
  780         }
  781 
  782     thread_done:
  783         if (trace_all_threads) {
  784             if (top_act != THR_ACT_NULL)
  785                 th = top_act;
  786             th = (thread_act_t) queue_next(&th->task_threads);
  787             if (! queue_end(act_list, (queue_entry_t) th)) {
  788                 db_printf("\n");
  789                 addr = (db_expr_t) th;
  790                 thcount++;
  791                 goto next_thread;
  792 
  793             }
  794         }
  795 }

Cache object: a9477ae7fd105e05983c2a39b36f7f46


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