db_examine.c revision 22975
122514Sdarrenr/*
231183Speter * Mach Operating System
322514Sdarrenr * Copyright (c) 1991,1990 Carnegie Mellon University
431183Speter * All Rights Reserved.
531183Speter *
631183Speter * Permission to use, copy, modify and distribute this software and its
722514Sdarrenr * documentation is hereby granted, provided that both the copyright
831183Speter * notice and this permission notice appear in all copies of the
931183Speter * software, derivative works or modified versions, and any portions
1037074Speter * thereof, and that both notices appear in supporting documentation.
1122514Sdarrenr *
1222514Sdarrenr * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
1322514Sdarrenr * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
1422514Sdarrenr * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1522514Sdarrenr *
1622514Sdarrenr * Carnegie Mellon requests users of this software to return to
1722514Sdarrenr *
1822514Sdarrenr *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
1931183Speter *  School of Computer Science
2022514Sdarrenr *  Carnegie Mellon University
2122514Sdarrenr *  Pittsburgh PA 15213-3890
2222514Sdarrenr *
2322514Sdarrenr * any improvements or extensions that they make and grant Carnegie the
2422514Sdarrenr * rights to redistribute these changes.
2522514Sdarrenr *
2622514Sdarrenr *	$Id$
2722514Sdarrenr */
2822514Sdarrenr
2931183Speter/*
3031183Speter *	Author: David B. Golub, Carnegie Mellon University
3131183Speter *	Date:	7/90
3231183Speter */
3331183Speter#include <sys/param.h>
3431183Speter#include <sys/systm.h>
3526119Sdarrenr
3626119Sdarrenr#include <ddb/ddb.h>
3726119Sdarrenr
3822514Sdarrenr#include <ddb/db_lex.h>
3922514Sdarrenr#include <ddb/db_output.h>
4022514Sdarrenr#include <ddb/db_command.h>
4122514Sdarrenr#include <ddb/db_sym.h>
4222514Sdarrenr#include <ddb/db_access.h>
4322514Sdarrenr
4431183Speterstatic char	db_examine_format[TOK_STRING_SIZE] = "x";
4531183Speter
4631183Speterstatic void db_examine(db_addr_t, char *, int);
4722514Sdarrenrstatic void db_search(db_addr_t, int, db_expr_t, db_expr_t, u_int);
4822514Sdarrenr
4922514Sdarrenr/*
5022514Sdarrenr * Examine (print) data.
5131183Speter */
5231183Speter/*ARGSUSED*/
5331183Spetervoid
5431183Speterdb_examine_cmd(addr, have_addr, count, modif)
5531183Speter	db_expr_t	addr;
5631183Speter	boolean_t	have_addr;
5731183Speter	db_expr_t	count;
5831183Speter	char *		modif;
5931183Speter{
6022514Sdarrenr	if (modif[0] != '\0')
6122514Sdarrenr	    db_strcpy(db_examine_format, modif);
6222514Sdarrenr
6322514Sdarrenr	if (count == -1)
6422514Sdarrenr	    count = 1;
6522514Sdarrenr
6631183Speter	db_examine((db_addr_t) addr, db_examine_format, count);
6731183Speter}
6831183Speter
6931183Speterstatic void
7031183Speterdb_examine(addr, fmt, count)
7131183Speter	register
7231183Speter	db_addr_t	addr;
7331183Speter	char *		fmt;	/* format string */
7431183Speter	int		count;	/* repeat count */
7524583Sdarrenr{
7622514Sdarrenr	int		c;
7724583Sdarrenr	db_expr_t	value;
7822514Sdarrenr	int		size;
7922514Sdarrenr	int		width;
8022514Sdarrenr	char *		fp;
8122514Sdarrenr
8222514Sdarrenr	while (--count >= 0) {
8322514Sdarrenr	    fp = fmt;
8422514Sdarrenr	    size = 4;
8522514Sdarrenr	    width = 16;
8622514Sdarrenr	    while ((c = *fp++) != 0) {
8722514Sdarrenr		switch (c) {
8822514Sdarrenr		    case 'b':
8922514Sdarrenr			size = 1;
9022514Sdarrenr			width = 4;
9131183Speter			break;
9222514Sdarrenr		    case 'h':
9322514Sdarrenr			size = 2;
9422514Sdarrenr			width = 8;
9522514Sdarrenr			break;
9622514Sdarrenr		    case 'l':
9722514Sdarrenr			size = 4;
9822514Sdarrenr			width = 16;
9922514Sdarrenr			break;
10022514Sdarrenr		    case 'a':	/* address */
10137074Speter			/* always forces a new line */
10237074Speter			if (db_print_position() != 0)
10322514Sdarrenr			    db_printf("\n");
10437074Speter			db_prev = addr;
10537074Speter			db_printsym(addr, DB_STGY_ANY);
10622514Sdarrenr			db_printf(":\t");
10722514Sdarrenr			break;
10822514Sdarrenr		    default:
10922514Sdarrenr			if (db_print_position() == 0) {
11022514Sdarrenr			    /* Print the address. */
11122514Sdarrenr			    db_printsym(addr, DB_STGY_ANY);
11222514Sdarrenr			    db_printf(":\t");
11322514Sdarrenr			    db_prev = addr;
11422514Sdarrenr			}
11537074Speter
11622514Sdarrenr			switch (c) {
11722514Sdarrenr			    case 'r':	/* signed, current radix */
11822514Sdarrenr				value = db_get_value(addr, size, TRUE);
11922514Sdarrenr				addr += size;
12022514Sdarrenr				db_printf("%+-*n", width, value);
12122514Sdarrenr				break;
12222514Sdarrenr			    case 'x':	/* unsigned hex */
12322514Sdarrenr				value = db_get_value(addr, size, FALSE);
12422514Sdarrenr				addr += size;
12522514Sdarrenr				db_printf("%-*x", width, value);
12622514Sdarrenr				break;
12722514Sdarrenr			    case 'z':	/* signed hex */
12822514Sdarrenr				value = db_get_value(addr, size, TRUE);
12922514Sdarrenr				addr += size;
13022514Sdarrenr				db_printf("%+-*x", width, value);
13137074Speter				break;
13222514Sdarrenr			    case 'd':	/* signed decimal */
13322514Sdarrenr				value = db_get_value(addr, size, TRUE);
13422514Sdarrenr				addr += size;
13522514Sdarrenr				db_printf("%-*d", width, value);
13622514Sdarrenr				break;
13722514Sdarrenr			    case 'u':	/* unsigned decimal */
13822514Sdarrenr				value = db_get_value(addr, size, FALSE);
13922514Sdarrenr				addr += size;
14022514Sdarrenr				db_printf("%-*u", width, value);
14122514Sdarrenr				break;
14222514Sdarrenr			    case 'o':	/* unsigned octal */
14322514Sdarrenr				value = db_get_value(addr, size, FALSE);
14422514Sdarrenr				addr += size;
14522514Sdarrenr				db_printf("%-*o", width, value);
14622514Sdarrenr				break;
14722514Sdarrenr			    case 'c':	/* character */
14822514Sdarrenr				value = db_get_value(addr, 1, FALSE);
14922514Sdarrenr				addr += 1;
15022514Sdarrenr				if (value >= ' ' && value <= '~')
15122514Sdarrenr				    db_printf("%c", value);
15222514Sdarrenr				else
15322514Sdarrenr				    db_printf("\\%03o", value);
15422514Sdarrenr				break;
15522514Sdarrenr			    case 's':	/* null-terminated string */
15622514Sdarrenr				for (;;) {
15722514Sdarrenr				    value = db_get_value(addr, 1, FALSE);
15822514Sdarrenr				    addr += 1;
15922514Sdarrenr				    if (value == 0)
16022514Sdarrenr					break;
16122514Sdarrenr				    if (value >= ' ' && value <= '~')
16222514Sdarrenr					db_printf("%c", value);
16322514Sdarrenr				    else
16422514Sdarrenr					db_printf("\\%03o", value);
16522514Sdarrenr				}
16622514Sdarrenr				break;
16722514Sdarrenr			    case 'i':	/* instruction */
16822514Sdarrenr				addr = db_disasm(addr, FALSE);
16922514Sdarrenr				break;
17022514Sdarrenr			    case 'I':	/* instruction, alternate form */
17122514Sdarrenr				addr = db_disasm(addr, TRUE);
17222514Sdarrenr				break;
17322514Sdarrenr			    default:
17422514Sdarrenr				break;
17522514Sdarrenr			}
17622514Sdarrenr			if (db_print_position() != 0)
17722514Sdarrenr			    db_end_line();
17822514Sdarrenr			break;
17922514Sdarrenr		}
18022514Sdarrenr	    }
18122514Sdarrenr	}
18237074Speter	db_next = addr;
18322514Sdarrenr}
18422514Sdarrenr
18524583Sdarrenr/*
18624583Sdarrenr * Print value.
18722514Sdarrenr */
18822514Sdarrenrstatic char	db_print_format = 'x';
18922514Sdarrenr
19022514Sdarrenr/*ARGSUSED*/
19122514Sdarrenrvoid
19222514Sdarrenrdb_print_cmd(addr, have_addr, count, modif)
19322514Sdarrenr	db_expr_t	addr;
19422514Sdarrenr	boolean_t	have_addr;
19537074Speter	db_expr_t	count;
19622514Sdarrenr	char *		modif;
19724583Sdarrenr{
19824583Sdarrenr	db_expr_t	value;
19922514Sdarrenr
20022514Sdarrenr	if (modif[0] != '\0')
20122514Sdarrenr	    db_print_format = modif[0];
20222514Sdarrenr
20322514Sdarrenr	switch (db_print_format) {
20422514Sdarrenr	    case 'a':
20522514Sdarrenr		db_printsym((db_addr_t)addr, DB_STGY_ANY);
20622514Sdarrenr		break;
20722514Sdarrenr	    case 'r':
20822514Sdarrenr		db_printf("%+11n", addr);
20922514Sdarrenr		break;
21022514Sdarrenr	    case 'x':
21122514Sdarrenr		db_printf("%8x", addr);
21222514Sdarrenr		break;
21322514Sdarrenr	    case 'z':
21437074Speter		db_printf("%+8x", addr);
21522514Sdarrenr		break;
21624583Sdarrenr	    case 'd':
21724583Sdarrenr		db_printf("%11d", addr);
21822514Sdarrenr		break;
21922514Sdarrenr	    case 'u':
22022514Sdarrenr		db_printf("%11u", addr);
22122514Sdarrenr		break;
22222514Sdarrenr	    case 'o':
22337074Speter		db_printf("%16o", addr);
22422514Sdarrenr		break;
22522514Sdarrenr	    case 'c':
22622514Sdarrenr		value = addr & 0xFF;
22722514Sdarrenr		if (value >= ' ' && value <= '~')
22824583Sdarrenr		    db_printf("%c", value);
22924583Sdarrenr		else
23022514Sdarrenr		    db_printf("\\%03o", value);
23122514Sdarrenr		break;
23222514Sdarrenr	}
23322514Sdarrenr	db_printf("\n");
23422514Sdarrenr}
23522514Sdarrenr
23622514Sdarrenrvoid
23722514Sdarrenrdb_print_loc_and_inst(loc)
23822514Sdarrenr	db_addr_t	loc;
23922514Sdarrenr{
24022514Sdarrenr	db_printsym(loc, DB_STGY_PROC);
24122514Sdarrenr	db_printf(":\t");
24222514Sdarrenr	(void) db_disasm(loc, TRUE);
24322514Sdarrenr}
24422514Sdarrenr
24522514Sdarrenr/*
24622514Sdarrenr * Search for a value in memory.
24722514Sdarrenr * Syntax: search [/bhl] addr value [mask] [,count]
24822514Sdarrenr */
24922514Sdarrenrvoid
25022514Sdarrenrdb_search_cmd(dummy1, dummy2, dummy3, dummy4)
25122514Sdarrenr	db_expr_t	dummy1;
25222514Sdarrenr	boolean_t	dummy2;
25322514Sdarrenr	db_expr_t	dummy3;
25422514Sdarrenr	char *		dummy4;
25522514Sdarrenr{
25622514Sdarrenr	int		t;
25722514Sdarrenr	db_addr_t	addr;
25822514Sdarrenr	int		size;
25922514Sdarrenr	db_expr_t	value;
26022514Sdarrenr	db_expr_t	mask;
26122514Sdarrenr	unsigned int	count;
26222514Sdarrenr
26322514Sdarrenr	t = db_read_token();
26422514Sdarrenr	if (t == tSLASH) {
26522514Sdarrenr	    t = db_read_token();
26622514Sdarrenr	    if (t != tIDENT) {
26722514Sdarrenr	      bad_modifier:
26822514Sdarrenr		db_printf("Bad modifier\n");
26922514Sdarrenr		db_flush_lex();
27022514Sdarrenr		return;
27122514Sdarrenr	    }
27222514Sdarrenr
27322514Sdarrenr	    if (!strcmp(db_tok_string, "b"))
27422514Sdarrenr		size = 1;
27522514Sdarrenr	    else if (!strcmp(db_tok_string, "h"))
27622514Sdarrenr		size = 2;
27722514Sdarrenr	    else if (!strcmp(db_tok_string, "l"))
27822514Sdarrenr		size = 4;
27922514Sdarrenr	    else
28022514Sdarrenr		goto bad_modifier;
28122514Sdarrenr	} else {
28222514Sdarrenr	    db_unread_token(t);
28322514Sdarrenr	    size = 4;
28422514Sdarrenr	}
28522514Sdarrenr
28637074Speter	if (!db_expression((db_expr_t *)&addr)) {
28722514Sdarrenr	    db_printf("Address missing\n");
28822514Sdarrenr	    db_flush_lex();
28922514Sdarrenr	    return;
29022514Sdarrenr	}
29122514Sdarrenr
29222514Sdarrenr	if (!db_expression(&value)) {
29322514Sdarrenr	    db_printf("Value missing\n");
29422514Sdarrenr	    db_flush_lex();
29522514Sdarrenr	    return;
29622514Sdarrenr	}
29737074Speter
29822514Sdarrenr	if (!db_expression(&mask))
29922514Sdarrenr	    mask = 0xffffffffUL;
30022514Sdarrenr
30122514Sdarrenr	t = db_read_token();
30222514Sdarrenr	if (t == tCOMMA) {
30322514Sdarrenr	    if (!db_expression(&count)) {
30437074Speter		db_printf("Count missing\n");
30522514Sdarrenr		db_flush_lex();
30622514Sdarrenr		return;
30722514Sdarrenr	    }
30822514Sdarrenr	} else {
30922514Sdarrenr	    db_unread_token(t);
31022514Sdarrenr	    count = -1;		/* effectively forever */
31122514Sdarrenr	}
31222514Sdarrenr	db_skip_to_eol();
31322514Sdarrenr
31422514Sdarrenr	db_search(addr, size, value, mask, count);
31522514Sdarrenr}
31622514Sdarrenr
31737074Speterstatic void
31822514Sdarrenrdb_search(addr, size, value, mask, count)
31922514Sdarrenr	register
32022514Sdarrenr	db_addr_t	addr;
32122514Sdarrenr	int		size;
32222514Sdarrenr	db_expr_t	value;
32322514Sdarrenr	db_expr_t	mask;
32422514Sdarrenr	unsigned int	count;
32522514Sdarrenr{
32622514Sdarrenr	while (count-- != 0) {
32722514Sdarrenr		db_prev = addr;
32822514Sdarrenr		if ((db_get_value(addr, size, FALSE) & mask) == value)
32922514Sdarrenr			break;
33022514Sdarrenr		addr += size;
33137074Speter	}
33222514Sdarrenr	db_next = addr;
33322514Sdarrenr}
33422514Sdarrenr