root/ddb/db_examine.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. db_examine_cmd
  2. db_examine
  3. db_print_cmd
  4. db_print_loc_and_inst
  5. db_strlcpy
  6. db_search_cmd
  7. db_search

    1 /*      $OpenBSD: db_examine.c,v 1.13 2007/03/15 17:10:22 miod 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/proc.h>
   35 
   36 #include <uvm/uvm_extern.h>
   37 
   38 #include <machine/db_machdep.h>         /* type definitions */
   39 
   40 #include <ddb/db_lex.h>
   41 #include <ddb/db_output.h>
   42 #include <ddb/db_command.h>
   43 #include <ddb/db_sym.h>
   44 #include <ddb/db_access.h>
   45 #include <ddb/db_extern.h>
   46 #include <ddb/db_interface.h>
   47 
   48 char    db_examine_format[TOK_STRING_SIZE] = "x";
   49 
   50 /*
   51  * Examine (print) data.  Syntax is:
   52  *              x/[bhlq][cdiorsuxz]*
   53  * For example, the command:
   54  *      x/bxxxx
   55  * should print:
   56  *      address:  01  23  45  67
   57  */
   58 /*ARGSUSED*/
   59 void
   60 db_examine_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
   61 {
   62         if (modif[0] != '\0')
   63                 db_strlcpy(db_examine_format, modif, sizeof(db_examine_format));
   64 
   65         if (count == -1)
   66                 count = 1;
   67 
   68         db_examine((db_addr_t)addr, db_examine_format, count);
   69 }
   70 
   71 void
   72 db_examine(db_addr_t addr, char *fmt, int count)
   73 {
   74         int             c;
   75         db_expr_t       value;
   76         int             size;
   77         int             width;
   78         char *          fp;
   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 #ifdef __LP64__
  105                         case 'q':       /* quad-word */
  106                                 size = 8;
  107                                 width = 20;
  108                                 break;
  109 #endif
  110                         case 'a':       /* address */
  111                                 db_printf("= 0x%lx\n", (long)addr);
  112                                 break;
  113                         case 'r':       /* signed, current radix */
  114                                 value = db_get_value(addr, size, TRUE);
  115                                 addr += size;
  116                                 db_printf("%-*lr", width, (long)value);
  117                                 break;
  118                         case 'x':       /* unsigned hex */
  119                                 value = db_get_value(addr, size, FALSE);
  120                                 addr += size;
  121                                 db_printf("%-*lx", width, (long)value);
  122                                 break;
  123                         case 'z':       /* signed hex */
  124                                 value = db_get_value(addr, size, TRUE);
  125                                 addr += size;
  126                                 db_printf("%-*lz", width, (long)value);
  127                                 break;
  128                         case 'd':       /* signed decimal */
  129                                 value = db_get_value(addr, size, TRUE);
  130                                 addr += size;
  131                                 db_printf("%-*ld", width, (long)value);
  132                                 break;
  133                         case 'u':       /* unsigned decimal */
  134                                 value = db_get_value(addr, size, FALSE);
  135                                 addr += size;
  136                                 db_printf("%-*lu", width, (long)value);
  137                                 break;
  138                         case 'o':       /* unsigned octal */
  139                                 value = db_get_value(addr, size, FALSE);
  140                                 addr += size;
  141                                 db_printf("%-*lo", width, value);
  142                                 break;
  143                         case 'c':       /* character */
  144                                 value = db_get_value(addr, 1, FALSE);
  145                                 addr += 1;
  146                                 if (value >= ' ' && value <= '~')
  147                                         db_printf("%c", value);
  148                                 else
  149                                         db_printf("\\%03o", value);
  150                                 break;
  151                         case 's':       /* null-terminated string */
  152                                 for (;;) {
  153                                         value = db_get_value(addr, 1, FALSE);
  154                                         addr += 1;
  155                                         if (value == 0)
  156                                                 break;
  157                                         if (value >= ' ' && value <= '~')
  158                                                 db_printf("%c", value);
  159                                         else
  160                                                 db_printf("\\%03o", value);
  161                                 }
  162                                 break;
  163                         case 'i':       /* instruction */
  164                                 addr = db_disasm(addr, FALSE);
  165                                 break;
  166                         case 'I':       /* instruction, alternate form */
  167                                 addr = db_disasm(addr, TRUE);
  168                                 break;
  169                         default:
  170                                 break;
  171                         }
  172                         if (db_print_position() != 0)
  173                                 db_end_line(width);
  174                 }
  175         }
  176         db_next = addr;
  177 }
  178 
  179 /*
  180  * Print value.
  181  */
  182 char    db_print_format = 'x';
  183 
  184 /*ARGSUSED*/
  185 void
  186 db_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
  187 {
  188         db_expr_t       value;
  189 
  190         if (modif[0] != '\0')
  191                 db_print_format = modif[0];
  192 
  193         switch (db_print_format) {
  194         case 'a':
  195                 db_printsym((db_addr_t)addr, DB_STGY_ANY, db_printf);
  196                 break;
  197         case 'r':
  198                 db_printf("%*r", sizeof(db_expr_t) * 2 * 6 / 5, addr);
  199                 break;
  200         case 'x':
  201                 db_printf("%*x", sizeof(db_expr_t) * 2, addr);
  202                 break;
  203         case 'z':
  204                 db_printf("%*z", sizeof(db_expr_t) * 2, addr);
  205                 break;
  206         case 'd':
  207                 db_printf("%*d", sizeof(db_expr_t) * 2 * 6 / 5, addr);
  208                 break;
  209         case 'u':
  210                 db_printf("%*u", sizeof(db_expr_t) * 2 * 6 / 5, addr);
  211                 break;
  212         case 'o':
  213                 db_printf("%*o", sizeof(db_expr_t) * 2 * 4 / 3, addr);
  214                 break;
  215         case 'c':
  216                 value = addr & 0xFF;
  217                 if (value >= ' ' && value <= '~')
  218                         db_printf("%c", value);
  219                 else
  220                         db_printf("\\%03o", value);
  221                 break;
  222         }
  223         db_printf("\n");
  224 }
  225 
  226 void
  227 db_print_loc_and_inst(db_addr_t loc)
  228 {
  229         db_printsym(loc, DB_STGY_PROC, db_printf);
  230         db_printf(":\t");
  231         (void) db_disasm(loc, FALSE);
  232 }
  233 
  234 /* local copy is needed here so that we can trace strlcpy() in libkern */
  235 size_t
  236 db_strlcpy(char *dst, const char *src, size_t siz)
  237 {
  238         char *d = dst;
  239         const char *s = src;
  240         size_t n = siz;
  241 
  242         /* Copy as many bytes as will fit */
  243         if (n != 0 && --n != 0) {
  244                 do {
  245                         if ((*d++ = *s++) == 0)
  246                                 break;
  247                 } while (--n != 0);
  248         }
  249 
  250         /* Not enough room in dst, add NUL and traverse rest of src */
  251         if (n == 0) {
  252                 if (siz != 0)
  253                         *d = '\0';              /* NUL-terminate dst */
  254                 while (*s++)
  255                         ;
  256         }
  257 
  258         return(s - src - 1);    /* count does not include NUL */
  259 }
  260 
  261 /*
  262  * Search for a value in memory.
  263  * Syntax: search [/bhl] addr value [mask] [,count]
  264  */
  265 /*ARGSUSED*/
  266 void
  267 db_search_cmd(db_expr_t daddr, int have_addr, db_expr_t dcount, char *modif)
  268 {
  269         int             t;
  270         db_addr_t       addr;
  271         int             size;
  272         db_expr_t       value;
  273         db_expr_t       mask;
  274         db_expr_t       count;
  275 
  276         t = db_read_token();
  277         if (t == tSLASH) {
  278                 t = db_read_token();
  279                 if (t != tIDENT) {
  280                         bad_modifier:
  281                         db_printf("Bad modifier\n");
  282                         db_flush_lex();
  283                         return;
  284                 }
  285 
  286                 if (!strcmp(db_tok_string, "b"))
  287                         size = 1;
  288                 else if (!strcmp(db_tok_string, "h"))
  289                         size = 2;
  290                 else if (!strcmp(db_tok_string, "l"))
  291                         size = 4;
  292                 else
  293                         goto bad_modifier;
  294         } else {
  295                 db_unread_token(t);
  296                 size = 4;
  297         }
  298 
  299         if (!db_expression(&value)) {
  300                 db_printf("Address missing\n");
  301                 db_flush_lex();
  302                 return;
  303         }
  304         addr = (db_addr_t) value;
  305 
  306         if (!db_expression(&value)) {
  307                 db_printf("Value missing\n");
  308                 db_flush_lex();
  309                 return;
  310         }
  311 
  312         if (!db_expression(&mask))
  313                 mask = (int) ~0;
  314 
  315         t = db_read_token();
  316         if (t == tCOMMA) {
  317                 if (!db_expression(&count)) {
  318                         db_printf("Count missing\n");
  319                         db_flush_lex();
  320                         return;
  321                 }
  322         } else {
  323                 db_unread_token(t);
  324                 count = -1;             /* forever */
  325         }
  326         db_skip_to_eol();
  327 
  328         db_search(addr, size, value, mask, count);
  329 }
  330 
  331 void
  332 db_search(db_addr_t addr, int size, db_expr_t value, db_expr_t mask,
  333     db_expr_t count)
  334 {
  335         /* Negative counts means forever.  */
  336         while (count < 0 || count-- != 0) {
  337                 db_prev = addr;
  338                 if ((db_get_value(addr, size, FALSE) & mask) == value)
  339                         break;
  340                 addr += size;
  341         }
  342         db_next = addr;
  343 }

/* [<][>][^][v][top][bottom][index][help] */