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 /*      $NetBSD: db_examine.c,v 1.40 2019/09/12 09:20:23 ryo Exp $      */
    2 
    3 /*
    4  * Mach Operating System
    5  * Copyright (c) 1991,1990 Carnegie Mellon University
    6  * All Rights Reserved.
    7  *
    8  * Permission to use, copy, modify and distribute this software and its
    9  * documentation is hereby granted, provided that both the copyright
   10  * notice and this permission notice appear in all copies of the
   11  * software, derivative works or modified versions, and any portions
   12  * thereof, and that both notices appear in supporting documentation.
   13  *
   14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  *
   18  * Carnegie Mellon requests users of this software to return to
   19  *
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  *
   25  * any improvements or extensions that they make and grant Carnegie the
   26  * rights to redistribute these changes.
   27  *
   28  *      Author: David B. Golub, Carnegie Mellon University
   29  *      Date:   7/90
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: db_examine.c,v 1.40 2019/09/12 09:20:23 ryo Exp $");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/buf.h>
   38 #include <sys/proc.h>
   39 
   40 #include <ddb/ddb.h>
   41 
   42 static char     db_examine_format[TOK_STRING_SIZE] = "x";
   43 
   44 static void     db_examine(db_addr_t, char *, int);
   45 static void     db_search(db_addr_t, int, db_expr_t, db_expr_t, unsigned int);
   46 
   47 /*
   48  * Examine (print) data.  Syntax is:
   49  *              x/[bhl][cdiorsuxz]*
   50  * For example, the command:
   51  *      x/bxxxx
   52  * should print:
   53  *      address:  01  23  45  67
   54  */
   55 /*ARGSUSED*/
   56 void
   57 db_examine_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
   58     const char *modif)
   59 {
   60         if (modif[0] != '\0')
   61                 strlcpy(db_examine_format, modif, sizeof(db_examine_format));
   62 
   63         if (count == -1)
   64                 count = 1;
   65 
   66         db_examine((db_addr_t) addr, db_examine_format, count);
   67 }
   68 
   69 static void
   70 db_examine(db_addr_t addr, char *fmt, int count)
   71 {
   72         int             i, c;
   73         quad_t          value;
   74         int             size;
   75         int             width;
   76         int             bytes;
   77         char *          fp;
   78         char            tbuf[24];
   79 
   80         while (--count >= 0) {
   81                 fp = fmt;
   82                 size = 4;
   83                 width = 12;
   84                 while ((c = *fp++) != 0) {
   85                         if (db_print_position() == 0) {
   86                                 /* Always print the address. */
   87                                 db_printsym(addr, DB_STGY_ANY, db_printf);
   88                                 db_printf(":\t");
   89                                 db_prev = addr;
   90                         }
   91                         switch (c) {
   92                         case 'b':       /* byte */
   93                                 size = 1;
   94                                 width = 4;
   95                                 break;
   96                         case 'h':       /* half-word */
   97                                 size = 2;
   98                                 width = 8;
   99                                 break;
  100                         case 'l':       /* long-word */
  101                                 size = 4;
  102                                 width = 12;
  103                                 break;
  104                         case 'q':       /* quad-word */
  105                                 size = 8;
  106                                 width = 24;
  107                                 break;
  108                         case 'L':       /* implementation maximum */
  109                                 size = sizeof value;
  110                                 width = 12 * (sizeof value / 4);
  111                                 break;
  112                         case 'a':       /* address */
  113                                 db_printf("= 0x%lx\n", (long)addr);
  114                                 break;
  115                         case 'p':
  116                                 size = sizeof(void *);
  117                                 value = db_get_value(addr, size, false);
  118                                 addr += size;
  119                                 db_printf("= 0x%lx ", (long)value);
  120                                 db_printsym((db_addr_t)value, DB_STGY_ANY, db_printf);
  121                                 db_printf("\n");
  122                                 break;
  123                         case 'r':       /* signed, current radix */
  124                                 value = db_get_qvalue(addr, size, true);
  125                                 addr += size;
  126                                 db_format_radix(tbuf, 24, value, false);
  127                                 db_printf("%-*s", width, tbuf);
  128                                 break;
  129                         case 'x':       /* unsigned hex */
  130                                 value = db_get_qvalue(addr, size, false);
  131                                 addr += size;
  132                                 db_printf("%-*" PRIx64, width, value);
  133                                 break;
  134                         case 'm':       /* hex dump */
  135                                 /*
  136                                  * Print off in chunks of size. Try to print 16
  137                                  * bytes at a time into 16/size columns. This
  138                                  * loops modify's count extra times in order
  139                                  * to get the nicely formatted lines.
  140                                  */
  141 
  142                                 bytes = 0;
  143                                 do {
  144                                         for (i = 0; i < size; i++) {
  145                                                 value =
  146 #if BYTE_ORDER == LITTLE_ENDIAN
  147                                                     db_get_value(addr +
  148                                                     (bytes & ~(size - 1)) +
  149                                                     size - i - 1, 1, false);
  150 #else
  151                                                     db_get_value(addr + bytes,
  152                                                     1, false);
  153 #endif
  154                                                 db_printf(
  155                                                     "%02" PRIx64,
  156                                                     value);
  157                                                 bytes++;
  158                                                 if (!(bytes % size))
  159                                                         db_printf(" ");
  160                                         }
  161                                 } while ((bytes != 16) && count--);
  162                                 /* True up the columns before continuing */
  163                                 for (i = 4; i >= (bytes / 4); i--)
  164                                         db_printf ("\t");
  165                                 /* Print chars,  use . for non-printable's. */
  166                                 while (bytes--) {
  167                                         value = db_get_value(addr, 1, false);
  168                                         addr += 1;
  169                                         if (value >= ' ' && value <= '~')
  170                                                 db_printf("%c", (char)value);
  171                                         else
  172                                                 db_printf(".");
  173                                 }
  174                                 db_printf("\n");
  175                                 break;
  176                         case 'z':       /* signed hex */
  177                                 value = db_get_qvalue(addr, size, true);
  178                                 addr += size;
  179                                 db_format_hex(tbuf, 24, value, false);
  180                                 db_printf("%-*s", width, tbuf);
  181                                 break;
  182                         case 'd':       /* signed decimal */
  183                                 value = db_get_qvalue(addr, size, true);
  184                                 addr += size;
  185                                 db_printf("%-*" PRId64, width, value);
  186                                 break;
  187                         case 'u':       /* unsigned decimal */
  188                                 value = db_get_qvalue(addr, size, false);
  189                                 addr += size;
  190                                 db_printf("%-*" PRIu64, width, value);
  191                                 break;
  192                         case 'o':       /* unsigned octal */
  193                                 value = db_get_qvalue(addr, size, false);
  194                                 addr += size;
  195                                 db_printf("%-*" PRIo64, width, value);
  196                                 break;
  197                         case 'c':       /* character */
  198                                 value = db_get_value(addr, 1, false);
  199                                 addr += 1;
  200                                 if (value >= ' ' && value <= '~')
  201                                         db_printf("%c", (char)value);
  202                                 else
  203                                         db_printf("\\%03o", (int)value);
  204                                 break;
  205                         case 's':       /* null-terminated string */
  206                                 for (;;) {
  207                                         value = db_get_value(addr, 1, false);
  208                                         addr += 1;
  209                                         if (value == 0)
  210                                                 break;
  211                                         if (value >= ' ' && value <= '~')
  212                                                 db_printf("%c", (char)value);
  213                                         else
  214                                                 db_printf("\\%03o", (int)value);
  215                                 }
  216                                 break;
  217                         case 'i':       /* instruction */
  218                                 addr = db_disasm(addr, false);
  219                                 break;
  220                         case 'I':       /* instruction, alternate form */
  221                                 addr = db_disasm(addr, true);
  222                                 break;
  223                         default:
  224                                 break;
  225                         }
  226                         if (db_print_position() != 0)
  227                                 db_end_line();
  228                 }
  229         }
  230         db_next = addr;
  231 }
  232 
  233 /*
  234  * Print value.
  235  */
  236 static char     db_print_format = 'x';
  237 
  238 /*ARGSUSED*/
  239 void
  240 db_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
  241     const char *modif)
  242 {
  243         db_expr_t       value;
  244 
  245         if (modif[0] != '\0')
  246                 db_print_format = modif[0];
  247 
  248         switch (db_print_format) {
  249         case 'a':
  250                 db_printsym((db_addr_t)addr, DB_STGY_ANY, db_printf);
  251                 break;
  252         case 'r':
  253                 {
  254                         char tbuf[24];
  255 
  256                         db_format_radix(tbuf, 24, addr, false);
  257                         db_printf("%11s", tbuf);
  258                         break;
  259                 }
  260         case 'x':
  261                 db_printf("%16" DDB_EXPR_FMT "x", addr);
  262                 break;
  263         case 'z':
  264                 {
  265                         char tbuf[24];
  266 
  267                         db_format_hex(tbuf, 24, addr, false);
  268                         db_printf("%8s", tbuf);
  269                         break;
  270                 }
  271         case 'd':
  272                 db_printf("%11" DDB_EXPR_FMT "d", addr);
  273                 break;
  274         case 'u':
  275                 db_printf("%11" DDB_EXPR_FMT "u", addr);
  276                 break;
  277         case 'o':
  278                 db_printf("%15" DDB_EXPR_FMT "o", addr);
  279                 break;
  280         case 'c':
  281                 value = addr & 0xFF;
  282                 if (value >= ' ' && value <= '~')
  283                         db_printf("%c", (char)value);
  284                 else
  285                         db_printf("\\%03o", (int)value);
  286                 break;
  287         }
  288         db_printf("\n");
  289 }
  290 
  291 void
  292 db_print_loc_and_inst(db_addr_t loc)
  293 {
  294 
  295         db_printsym(loc, DB_STGY_PROC, db_printf);
  296         db_printf(":\t");
  297         (void) db_disasm(loc, false);
  298 }
  299 
  300 /*
  301  * Search for a value in memory.
  302  * Syntax: search [/bhl] addr value [mask] [,count]
  303  */
  304 /*ARGSUSED*/
  305 void
  306 db_search_cmd(db_expr_t daddr, bool have_addr,
  307     db_expr_t dcount, const char *modif)
  308 {
  309         int             t;
  310         db_addr_t       addr;
  311         int             size;
  312         db_expr_t       value;
  313         db_expr_t       mask;
  314         db_expr_t       count;
  315 
  316         t = db_read_token();
  317         if (t == tSLASH) {
  318                 t = db_read_token();
  319                 if (t != tIDENT) {
  320                         bad_modifier:
  321                         db_printf("Bad modifier\n");
  322                         db_flush_lex();
  323                         return;
  324                 }
  325 
  326                 if (!strcmp(db_tok_string, "b"))
  327                         size = 1;
  328                 else if (!strcmp(db_tok_string, "h"))
  329                         size = 2;
  330                 else if (!strcmp(db_tok_string, "l"))
  331                         size = 4;
  332                 else
  333                         goto bad_modifier;
  334         } else {
  335                 db_unread_token(t);
  336                 size = 4;
  337         }
  338 
  339         if (!db_expression(&value)) {
  340                 db_printf("Address missing\n");
  341                 db_flush_lex();
  342                 return;
  343         }
  344         addr = (db_addr_t) value;
  345 
  346         if (!db_expression(&value)) {
  347                 db_printf("Value missing\n");
  348                 db_flush_lex();
  349                 return;
  350         }
  351 
  352         if (!db_expression(&mask))
  353                 mask = (int) ~0;
  354 
  355         t = db_read_token();
  356         if (t == tCOMMA) {
  357                 if (!db_expression(&count)) {
  358                         db_printf("Count missing\n");
  359                         db_flush_lex();
  360                         return;
  361                 }
  362         } else {
  363                 db_unread_token(t);
  364                 count = -1;             /* effectively forever */
  365         }
  366         db_skip_to_eol();
  367 
  368         db_search(addr, size, value, mask, count);
  369 }
  370 
  371 static void
  372 db_search(db_addr_t addr, int size, db_expr_t value, db_expr_t mask,
  373     unsigned int count)
  374 {
  375         while (count-- != 0) {
  376                 db_prev = addr;
  377                 if ((db_get_value(addr, size, false) & mask) == value)
  378                         break;
  379                 addr += size;
  380         }
  381         db_next = addr;
  382 }

Cache object: 989ae39a4988a212967f5fce71a6a002


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