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

Cache object: 3b7b6cd932a075678908caf99e801f18


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