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/ddb/db_examine.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  * Mach Operating System
    3  * Copyright (c) 1992,1991,1990 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        db_examine.c,v $
   29  * Revision 2.13  93/05/17  10:26:31  rvb
   30  *      Type casts, etc to quiet gcc 2.3.3 warnings
   31  * 
   32  * Revision 2.12  93/03/09  17:55:55  danner
   33  *      Added ',' format to examine command.
   34  *      [93/02/25            jfriedl]
   35  * 
   36  * Revision 2.11  93/01/14  17:24:52  danner
   37  *      64bit cleanup.
   38  *      [92/12/10  16:16:01  af]
   39  * 
   40  * Revision 2.10  92/08/03  17:30:58  jfriedl
   41  *      removed silly prototypes
   42  *      [92/08/02            jfriedl]
   43  * 
   44  * Revision 2.9  92/05/21  17:06:44  jfriedl
   45  *      Added void type to functions that needed it.
   46  *      Added init to 'size' in db_search_cmd(). Removed unused variables.
   47  *      Other cleanup to quiet gcc warnings.
   48  *      [92/05/16            jfriedl]
   49  * 
   50  * Revision 2.8  92/05/04  11:23:59  danner
   51  *      x/u now examines current user space. x/t still examines user
   52  *      space of the the specified thread. x/tu is redundant. 
   53  *      To examine an value as unsigned decimal, use x/U. 
   54  *      [92/04/18            danner]
   55  * 
   56  * Revision 2.7  91/10/09  15:59:28  af
   57  *      Supported non current task space data examination and search.
   58  *      Added 'm' format and db_xcdump to print with hex and characters.
   59  *      Added db_examine_{forward, backward}.
   60  *      Changed db_print_cmd to support variable number of parameters
   61  *      including string constant.
   62  *      Included "db_access.h".
   63  *      [91/08/29            tak]
   64  * 
   65  * Revision 2.6  91/08/28  11:11:01  jsb
   66  *      Added 'A' flag to examine: just like 'a' (address), but prints addr
   67  *      as a procedure type, thus printing file/line info if available.
   68  *      Useful when called as 'x/Ai'.
   69  *      [91/08/13  18:14:55  jsb]
   70  * 
   71  * Revision 2.5  91/05/14  15:33:31  mrt
   72  *      Correcting copyright
   73  * 
   74  * Revision 2.4  91/02/05  17:06:20  mrt
   75  *      Changed to new Mach copyright
   76  *      [91/01/31  16:17:37  mrt]
   77  * 
   78  * Revision 2.3  90/11/07  16:49:23  rpd
   79  *      Added db_search_cmd, db_search.
   80  *      [90/11/06            rpd]
   81  * 
   82  * Revision 2.2  90/08/27  21:50:38  dbg
   83  *      Add 'r', 'z' to print and examine formats.
   84  *      Change calling sequence of db_disasm.
   85  *      db_examine sets db_prev and db_next instead of explicitly
   86  *      advancing dot.
   87  *      [90/08/20            dbg]
   88  *      Reflected changes in db_printsym()'s calling seq.
   89  *      [90/08/20            af]
   90  *      Reduce lint.
   91  *      [90/08/07            dbg]
   92  *      Created.
   93  *      [90/07/25            dbg]
   94  * 
   95  */
   96 /*
   97  *      Author: David B. Golub, Carnegie Mellon University
   98  *      Date:   7/90
   99  */
  100 #include <mach/boolean.h>
  101 #include <machine/db_machdep.h>
  102 
  103 #include <ddb/db_access.h>
  104 #include <ddb/db_lex.h>
  105 #include <ddb/db_output.h>
  106 #include <ddb/db_command.h>
  107 #include <ddb/db_sym.h>
  108 #include <ddb/db_task_thread.h>
  109 #include <kern/thread.h>
  110 #include <kern/task.h>
  111 #include <mach/vm_param.h>
  112 
  113 #define db_thread_to_task(thread)       ((thread)? thread->task: TASK_NULL)
  114 
  115 char            db_examine_format[TOK_STRING_SIZE] = "x";
  116 int             db_examine_count = 1;
  117 db_addr_t       db_examine_prev_addr = 0;
  118 thread_t        db_examine_thread = THREAD_NULL;
  119 
  120 extern  db_addr_t db_disasm(db_addr_t pc, boolean_t altform, task_t task);
  121                         /* instruction disassembler */
  122 
  123 void db_examine();/*forwards*/
  124 void db_strcpy();
  125 
  126 /*
  127  * Examine (print) data.
  128  */
  129 /*ARGSUSED*/
  130 void
  131 db_examine_cmd(addr, have_addr, count, modif)
  132         db_expr_t       addr;
  133         int             have_addr;
  134         db_expr_t       count;
  135         char *          modif;
  136 {
  137         thread_t        thread;
  138         boolean_t       db_option();
  139 
  140         if (modif[0] != '\0')
  141             db_strcpy(db_examine_format, modif);
  142 
  143         if (count == -1)
  144             count = 1;
  145         db_examine_count = count;
  146         if (db_option(modif, 't')) 
  147           {
  148             if (!db_get_next_thread(&thread, 0))
  149               return;
  150           }
  151         else 
  152           if (db_option(modif,'u'))
  153             thread = current_thread();
  154           else
  155             thread = THREAD_NULL;
  156         
  157         db_examine_thread = thread;
  158         db_examine((db_addr_t) addr, db_examine_format, count, 
  159                                         db_thread_to_task(thread));
  160 }
  161 
  162 /* ARGSUSED */
  163 void
  164 db_examine_forward(addr, have_addr, count, modif)
  165         db_expr_t       addr;
  166         int             have_addr;
  167         db_expr_t       count;
  168         char *          modif;
  169 {
  170         db_examine(db_next, db_examine_format, db_examine_count,
  171                                 db_thread_to_task(db_examine_thread));
  172 }
  173 
  174 /* ARGSUSED */
  175 void
  176 db_examine_backward(addr, have_addr, count, modif)
  177         db_expr_t       addr;
  178         int             have_addr;
  179         db_expr_t       count;
  180         char *          modif;
  181 {
  182 
  183         db_examine(db_examine_prev_addr - (db_next - db_examine_prev_addr),
  184                          db_examine_format, db_examine_count,
  185                                 db_thread_to_task(db_examine_thread));
  186 }
  187 
  188 void
  189 db_examine(addr, fmt, count, task)
  190         register
  191         db_addr_t       addr;
  192         char *          fmt;    /* format string */
  193         int             count;  /* repeat count */
  194         task_t          task;
  195 {
  196         int             c;
  197         db_expr_t       value;
  198         int             size;   /* in bytes */
  199         int             width;
  200         char *          fp;
  201 
  202         db_examine_prev_addr = addr;
  203         while (--count >= 0) {
  204             fp = fmt;
  205             size = sizeof(int);
  206             width = 4*size;
  207             while ((c = *fp++) != 0) {
  208                 switch (c) {
  209                     case 'b':
  210                         size = sizeof(char);
  211                         width = 4*size;
  212                         break;
  213                     case 'h':
  214                         size = sizeof(short);
  215                         width = 4*size;
  216                         break;
  217                     case 'l':
  218                         size = sizeof(long);
  219                         width = 4*size;
  220                         break;
  221                     case 'a':   /* address */
  222                     case 'A':   /* function address */
  223                         /* always forces a new line */
  224                         if (db_print_position() != 0)
  225                             db_printf("\n");
  226                         db_prev = addr;
  227                         db_task_printsym(addr, 
  228                                         (c == 'a')?DB_STGY_ANY:DB_STGY_PROC,
  229                                         task);
  230                         db_printf(":\t");
  231                         break;
  232                     case 'm':
  233                         db_next = db_xcdump(addr, size, count+1, task);
  234                         return;
  235                     default:
  236                         if (db_print_position() == 0) {
  237                             /* If we hit a new symbol, print it */
  238                             char *      name;
  239                             db_addr_t   off;
  240 
  241                             db_find_task_sym_and_offset(addr,&name,&off,task);
  242                             if (off == 0)
  243                                 db_printf("%s:\t", name);
  244                             else
  245                                 db_printf("\t\t");
  246 
  247                             db_prev = addr;
  248                         }
  249 
  250                         switch (c) {
  251                             case ',':   /* skip one unit w/o printing */
  252                                 addr += size;
  253                                 break;
  254 
  255                             case 'r':   /* signed, current radix */
  256                                 value = db_get_task_value(addr,size,TRUE,task);
  257                                 addr += size;
  258                                 db_printf("%-*R", width, value);
  259                                 break;
  260                             case 'x':   /* unsigned hex */
  261                                 value = db_get_task_value(addr,size,FALSE,task);
  262                                 addr += size;
  263                                 db_printf("%-*X", width, value);
  264                                 break;
  265                             case 'z':   /* signed hex */
  266                                 value = db_get_task_value(addr,size,TRUE,task);
  267                                 addr += size;
  268                                 db_printf("%-*Z", width, value);
  269                                 break;
  270                             case 'd':   /* signed decimal */
  271                                 value = db_get_task_value(addr,size,TRUE,task);
  272                                 addr += size;
  273                                 db_printf("%-*D", width, value);
  274                                 break;
  275                             case 'U':   /* unsigned decimal */
  276                                 value = db_get_task_value(addr,size,FALSE,task);
  277                                 addr += size;
  278                                 db_printf("%-*U", width, value);
  279                                 break;
  280                             case 'o':   /* unsigned octal */
  281                                 value = db_get_task_value(addr,size,FALSE,task);
  282                                 addr += size;
  283                                 db_printf("%-*O", width, value);
  284                                 break;
  285                             case 'c':   /* character */
  286                                 value = db_get_task_value(addr,1,FALSE,task);
  287                                 addr += 1;
  288                                 if (value >= ' ' && value <= '~')
  289                                     db_printf("%c", value);
  290                                 else
  291                                     db_printf("\\%03o", value);
  292                                 break;
  293                             case 's':   /* null-terminated string */
  294                                 for (;;) {
  295                                     value = db_get_task_value(addr,1,FALSE,task);
  296                                     addr += 1;
  297                                     if (value == 0)
  298                                         break;
  299                                     if (value >= ' ' && value <= '~')
  300                                         db_printf("%c", value);
  301                                     else
  302                                         db_printf("\\%03o", value);
  303                                 }
  304                                 break;
  305                             case 'i':   /* instruction */
  306                                 addr = db_disasm(addr, FALSE, task);
  307                                 break;
  308                             case 'I':   /* instruction, alternate form */
  309                                 addr = db_disasm(addr, TRUE, task);
  310                                 break;
  311                             default:
  312                                 break;
  313                         }
  314                         if (db_print_position() != 0)
  315                             db_end_line();
  316                         break;
  317                 }
  318             }
  319         }
  320         db_next = addr;
  321 }
  322 
  323 /*
  324  * Print value.
  325  */
  326 char    db_print_format = 'x';
  327 
  328 /*ARGSUSED*/
  329 void
  330 db_print_cmd()
  331 {
  332         db_expr_t       value;
  333         int             t;
  334         task_t          task = TASK_NULL;
  335 
  336         if ((t = db_read_token()) == tSLASH) {
  337             if (db_read_token() != tIDENT) {
  338                 db_printf("Bad modifier \"/%s\"\n", db_tok_string);
  339                 db_error(0);
  340                 /* NOTREACHED */
  341             }
  342             if (db_tok_string[0])
  343                 db_print_format = db_tok_string[0];
  344             if (db_option(db_tok_string, 't') && db_default_thread)
  345                 task = db_default_thread->task;
  346         } else
  347             db_unread_token(t);
  348         
  349         for ( ; ; ) {
  350             t = db_read_token();
  351             if (t == tSTRING) {
  352                 db_printf("%s", db_tok_string);
  353                 continue;
  354             }
  355             db_unread_token(t);
  356             if (!db_expression(&value))
  357                 break;
  358             switch (db_print_format) {
  359             case 'a':
  360                 db_task_printsym((db_addr_t)value, DB_STGY_ANY, task);
  361                 break;
  362             case 'r':
  363                 db_printf("%*r", 3+2*sizeof(db_expr_t), value);
  364                 break;
  365             case 'x':
  366                 db_printf("%*x", 2*sizeof(db_expr_t), value);
  367                 break;
  368             case 'z':
  369                 db_printf("%*z", 2*sizeof(db_expr_t), value);
  370                 break;
  371             case 'd':
  372                 db_printf("%*d", 3+2*sizeof(db_expr_t), value);
  373                 break;
  374             case 'u':
  375                 db_printf("%*u", 3+2*sizeof(db_expr_t), value);
  376                 break;
  377             case 'o':
  378                 db_printf("%o", 4*sizeof(db_expr_t), value);
  379                 break;
  380             case 'c':
  381                 value = value & 0xFF;
  382                 if (value >= ' ' && value <= '~')
  383                     db_printf("%c", value);
  384                 else
  385                     db_printf("\\%03o", value);
  386                 break;
  387             default:
  388                 db_printf("Unknown format %c\n", db_print_format);
  389                 db_print_format = 'x';
  390                 db_error(0);
  391             }
  392         }
  393 }
  394 
  395 void
  396 db_print_loc_and_inst(loc, task)
  397         db_addr_t       loc;
  398         task_t          task;
  399 {
  400         db_task_printsym(loc, DB_STGY_PROC, task);
  401         db_printf(":\t");
  402         (void) db_disasm(loc, TRUE, task);
  403 }
  404 
  405 void
  406 db_strcpy(dst, src)
  407         register char *dst;
  408         register char *src;
  409 {
  410         while (*dst++ = *src++)
  411             ;
  412 }
  413 
  414 void db_search(); /*forward*/
  415 /*
  416  * Search for a value in memory.
  417  * Syntax: search [/bhl] addr value [mask] [,count] [thread]
  418  */
  419 void
  420 db_search_cmd()
  421 {
  422         int             t;
  423         db_addr_t       addr;
  424         int             size = 0;
  425         db_expr_t       value;
  426         db_expr_t       mask;
  427         db_addr_t       count;
  428         thread_t        thread;
  429         boolean_t       thread_flag = FALSE;
  430         register char   *p;
  431 
  432         t = db_read_token();
  433         if (t == tSLASH) {
  434             t = db_read_token();
  435             if (t != tIDENT) {
  436               bad_modifier:
  437                 db_printf("Bad modifier \"/%s\"\n", db_tok_string);
  438                 db_flush_lex();
  439                 return;
  440             }
  441 
  442             for (p = db_tok_string; *p; p++) {
  443                 switch(*p) {
  444                 case 'b':
  445                     size = sizeof(char);
  446                     break;
  447                 case 'h':
  448                     size = sizeof(short);
  449                     break;
  450                 case 'l':
  451                     size = sizeof(long);
  452                     break;
  453                 case 't':
  454                     thread_flag = TRUE;
  455                     break;
  456                 default:
  457                     goto bad_modifier;
  458                 }
  459             }
  460         } else {
  461             db_unread_token(t);
  462             size = sizeof(int);
  463         }
  464 
  465         if (!db_expression(&addr)) {
  466             db_printf("Address missing\n");
  467             db_flush_lex();
  468             return;
  469         }
  470 
  471         if (!db_expression(&value)) {
  472             db_printf("Value missing\n");
  473             db_flush_lex();
  474             return;
  475         }
  476 
  477         if (!db_expression(&mask))
  478             mask = ~0;
  479 
  480         t = db_read_token();
  481         if (t == tCOMMA) {
  482             if (!db_expression(&count)) {
  483                 db_printf("Count missing\n");
  484                 db_flush_lex();
  485                 return;
  486             }
  487         } else {
  488             db_unread_token(t);
  489             count = -1;         /* effectively forever */
  490         }
  491         if (thread_flag) {
  492             if (!db_get_next_thread(&thread, 0))
  493                 return;
  494         } else
  495             thread = THREAD_NULL;
  496 
  497         db_search(addr, size, value, mask, count, db_thread_to_task(thread));
  498 }
  499 
  500 void
  501 db_search(addr, size, value, mask, count, task)
  502         register
  503         db_addr_t       addr;
  504         int             size;
  505         db_expr_t       value;
  506         db_expr_t       mask;
  507         unsigned int    count;
  508         task_t          task;
  509 {
  510         while (count-- != 0) {
  511                 db_prev = addr;
  512                 if ((db_get_task_value(addr,size,FALSE,task) & mask) == value)
  513                         break;
  514                 addr += size;
  515         }
  516         db_next = addr;
  517 }
  518 
  519 #define DB_XCDUMP_NC    16
  520 
  521 int
  522 db_xcdump(addr, size, count, task)
  523         db_addr_t       addr;
  524         int             size;
  525         int             count;
  526         task_t          task;
  527 {
  528         register        i, n;
  529         db_expr_t       value;
  530         int             bcount;
  531         db_addr_t       off;
  532         char            *name;
  533         char            data[DB_XCDUMP_NC];
  534 
  535         db_find_task_sym_and_offset(addr, &name, &off, task);
  536         for (n = count*size; n > 0; n -= bcount) {
  537             db_prev = addr;
  538             if (off == 0) {
  539                 db_printf("%s:\n", name);
  540                 off = -1;
  541             }
  542             db_printf("%0*X:%s", 2*sizeof(db_addr_t), addr,
  543                         (size != 1)? " ": "");
  544             bcount = ((n > DB_XCDUMP_NC)? DB_XCDUMP_NC: n);
  545             if (trunc_page(addr) != trunc_page(addr+bcount-1)) {
  546                 db_addr_t next_page_addr = trunc_page(addr+bcount-1);
  547                 if (!DB_CHECK_ACCESS(next_page_addr, sizeof(int), task))
  548                     bcount = next_page_addr - addr;
  549             }
  550             db_read_bytes((char *)addr, bcount, data, task);
  551             for (i = 0; i < bcount && off != 0; i += size) {
  552                 if (i % 4 == 0)
  553                         db_printf(" ");
  554                 value = db_get_task_value(addr, size, FALSE, task);
  555                 db_printf("%0*x ", size*2, value);
  556                 addr += size;
  557                 db_find_task_sym_and_offset(addr, &name, &off, task);
  558             }
  559             db_printf("%*s",
  560                         ((DB_XCDUMP_NC-i)/size)*(size*2+1)+(DB_XCDUMP_NC-i)/4,
  561                          "");
  562             bcount = i;
  563             db_printf("%s*", (size != 1)? " ": "");
  564             for (i = 0; i < bcount; i++) {
  565                 value = data[i];
  566                 db_printf("%c", (value >= ' ' && value <= '~')? value: '.');
  567             }
  568             db_printf("*\n");
  569         }
  570         return(addr);
  571 }

Cache object: 878a149e21fc4d79373719885a1016ab


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