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

Cache object: 5f723a74f325436c53c94dd1b45cfd97


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