📄 dlite.c
字号:
/* * dlite.c - DLite, the lite debugger, routines * * This file is a part of the SimpleScalar tool suite written by * Todd M. Austin as a part of the Multiscalar Research Project. * * The tool suite is currently maintained by Doug Burger and Todd M. Austin. * * Copyright (C) 1994, 1995, 1996, 1997 by Todd M. Austin * * This source file is distributed "as is" in the hope that it will be * useful. The tool set comes with no warranty, and no author or * distributor accepts any responsibility for the consequences of its * use. * * Everyone is granted permission to copy, modify and redistribute * this tool set under the following conditions: * * This source code is distributed for non-commercial use only. * Please contact the maintainer for restrictions applying to * commercial use. * * Permission is granted to anyone to make or distribute copies * of this source code, either as received or modified, in any * medium, provided that all copyright notices, permission and * nonwarranty notices are preserved, and that the distributor * grants the recipient permission for further redistribution as * permitted by this document. * * Permission is granted to distribute this file in compiled * or executable form under the same conditions that apply for * source code, provided that either: * * A. it is accompanied by the corresponding machine-readable * source code, * B. it is accompanied by a written offer, with no time limit, * to give anyone a machine-readable copy of the corresponding * source code in return for reimbursement of the cost of * distribution. This written offer must permit verbatim * duplication by anyone, or * C. it is distributed by someone who received only the * executable form, and is accompanied by a copy of the * written offer of source code that they received concurrently. * * In other words, you are welcome to use, share and improve this * source file. You are forbidden to forbid anyone else to use, share * and improve what you give them. * * INTERNET: dburger@cs.wisc.edu * US Mail: 1210 W. Dayton Street, Madison, WI 53706 * * $Id: dlite.c,v 1.1 1997/03/11 01:30:41 taustin Exp taustin $ * * $Log: dlite.c,v $ * Revision 1.1 1997/03/11 01:30:41 taustin * Initial revision * * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#if defined(__CYGWIN32__)#include <errno.h>#endif#include "misc.h"#include "version.h"#include "eval.h"#include "regs.h"#include "memory.h"#include "ss.h"#include "sim.h"#include "symbol.h"#include "loader.h"#include "options.h"#include "stats.h"#include "range.h"#include "dlite.h"/* architected state accessors, initialized by dlite_init() */static dlite_reg_obj_t f_dlite_reg_obj = NULL;static dlite_mem_obj_t f_dlite_mem_obj = NULL;static dlite_mstate_obj_t f_dlite_mstate_obj = NULL;/* set non-zero to enter DLite after next instruction */int dlite_active = FALSE;/* non-zero to force a check for a break */int dlite_check = FALSE;/* set non-zero to exit DLite command loop */static int dlite_return = FALSE;/* size/type modifier mask bit definitions */#define MOD_BYTE 0x0001 /* b - print a byte */#define MOD_HALF 0x0002 /* h - print a half (short) */#define MOD_WORD 0x0004 /* w - print a word */#define MOD_DECIMAL 0x0008 /* t - print in decimal format */#define MOD_UDECIMAL 0x0010 /* u - print in unsigned format */#define MOD_OCTAL 0x0020 /* o - print in octal format */#define MOD_HEX 0x0040 /* x - print in hex format */#define MOD_BINARY 0x0080 /* 1 - print in binary format */#define MOD_FLOAT 0x0100 /* f - print a float */#define MOD_DOUBLE 0x0200 /* d - print a double */#define MOD_CHAR 0x0400 /* c - print a character */#define MOD_STRING 0x0800 /* s - print a string *//* DLite modifier parser, transforms /<mods> strings to modifier mask */static char * /* error string, NULL for no err */modifier_parser(char *p, /* ptr to /<mods> string */ char **endp, /* ptr to first byte not consumed */ int *pmod) /* modifier mask written to *PMOD */{ int modifiers = 0; /* default modifiers */ *pmod = 0; /* is this a valid modifier? */ if (*p == '/') { p++; /* parse modifiers until end-of-string or whitespace is found */ while (*p != '\0' && *p != '\n' && *p != ' ' && *p != '\t') { switch (*p) { case 'b': modifiers |= MOD_BYTE; break; case 'h': modifiers |= MOD_HALF; break; case 'w': modifiers |= MOD_WORD; break; case 't': modifiers |= MOD_DECIMAL; break; case 'u': modifiers |= MOD_UDECIMAL; break; case 'o': modifiers |= MOD_OCTAL; break; case 'x': modifiers |= MOD_HEX; break; case '1': modifiers |= MOD_BINARY; break; case 'f': modifiers |= MOD_FLOAT; break; case 'd': modifiers |= MOD_DOUBLE; break; case 'c': modifiers |= MOD_CHAR; break; case 's': modifiers |= MOD_STRING; break; default: return "bad modifier (use one or more of /bhwdox1fdcs)"; } p++; } } /* no error, return end of string and modifier mask */ *endp = p; *pmod = modifiers; return NULL;}/* DLite default expression evaluator */static struct eval_state_t *dlite_evaluator = NULL;/* DLite identifier evaluator, used by the expression evaluator, returns the value of the ident in ES->TOK_BUF, sets eval_error to value other than ERR_NOERR if an error is encountered */static struct eval_value_t /* value of identifier */ident_evaluator(struct eval_state_t *es) /* expression evaluator */{ char *err_str; struct eval_value_t val; union dlite_reg_val_t rval; struct stat_stat_t *stat; struct sym_sym_t *sym; static struct eval_value_t err_value = { et_int, { 0 } }; /* is this a builtin register definition? */ if (!mystricmp(es->tok_buf, "$pc")) { err_str = f_dlite_reg_obj(at_read, rt_PC, 0, &rval); if (err_str) { eval_error = ERR_UNDEFVAR; val = err_value; } else { val.type = et_uint; val.value.as_uint = rval.as_word; } return val; } else if (!mystricmp(es->tok_buf, "$hi")) { err_str = f_dlite_reg_obj(at_read, rt_hi, 0, &rval); if (err_str) { eval_error = ERR_UNDEFVAR; val = err_value; } else { val.type = et_uint; val.value.as_uint = rval.as_word; } return val; } else if (!mystricmp(es->tok_buf, "$lo")) { err_str = f_dlite_reg_obj(at_read, rt_lo, 0, &rval); if (err_str) { eval_error = ERR_UNDEFVAR; val = err_value; } else { val.type = et_uint; val.value.as_uint = rval.as_word; } return val; } else if (!mystricmp(es->tok_buf, "$fcc")) { err_str = f_dlite_reg_obj(at_read, rt_FCC, 0, &rval); if (err_str) { eval_error = ERR_UNDEFVAR; val = err_value; } else { val.type = et_int; val.value.as_int = rval.as_condition; } return val; } /* is this a register identifier? */ else if (es->tok_buf[0] == '$' && (tolower(es->tok_buf[1]) == 'r' || tolower(es->tok_buf[1]) == 'f' || tolower(es->tok_buf[1]) == 'd')) { int reg_num; char *reg_numstr, *endp;#if !defined(__CYGWIN32__) extern int errno;#endif /* looks like one, try to parse it */ reg_numstr = &es->tok_buf[2]; if (*reg_numstr) { errno = 0; reg_num = strtoul(reg_numstr, &endp, /* radix */10); if (!errno && !*endp) { /* good conversion, compute register value */ if (tolower(es->tok_buf[1]) == 'r') { err_str = f_dlite_reg_obj(at_read, rt_gpr, reg_num, &rval); if (err_str) { eval_error = ERR_UNDEFVAR; val = err_value; } else { val.type = et_int; val.value.as_int = rval.as_word; } } else if (tolower(es->tok_buf[1]) == 'f') { err_str = f_dlite_reg_obj(at_read, rt_fpr, reg_num, &rval); if (err_str) { eval_error = ERR_UNDEFVAR; val = err_value; } else { val.type = et_float; val.value.as_float = rval.as_float; } } else if (tolower(es->tok_buf[1]) == 'd') { err_str = f_dlite_reg_obj(at_read, rt_dpr, reg_num/2, &rval); if (err_str) { eval_error = ERR_UNDEFVAR; val = err_value; } else { val.type = et_double; val.value.as_double = rval.as_double; } } /* return register value */ return val; } /* else, reg number is bogus, try next ident format */ } /* else, no reg number, try next ident format */ } /* else, try to locate a program symbol */ sym_loadsyms(ld_prog_fname, /* load locals */TRUE); sym = sym_bind_name(es->tok_buf, NULL, sdb_any); if (sym) { /* found a symbol with this name, return it's (address) value */ val.type = et_uint; val.value.as_uint = sym->addr; return val; } /* else, try to locate a statistical value symbol */ stat = stat_find_stat(sim_sdb, es->tok_buf); if (stat) { /* found it, convert stat value to an eval_value_t value */ switch (stat->sc) { case sc_int: val.type = et_int; val.value.as_int = *stat->variant.for_int.var; break; case sc_uint: val.type = et_uint; val.value.as_uint = *stat->variant.for_uint.var; break;#ifdef __GNUC__ case sc_llong: /* FIXME: cast to double, eval package doesn't support long long's */ val.type = et_double; val.value.as_double = (double)*stat->variant.for_llong.var; break;#endif /* __GNUC__ */ case sc_float: val.type = et_float; val.value.as_float = *stat->variant.for_float.var; break; case sc_double: val.type = et_double; val.value.as_double = *stat->variant.for_double.var; break; case sc_dist: case sc_sdist: fatal("stat distributions not allowed in formula expressions"); break; case sc_formula: { /* instantiate a new evaluator to avoid recursion problems */ struct eval_state_t *es = eval_new(ident_evaluator, sim_sdb); char *endp; val = eval_expr(es, stat->variant.for_formula.formula, &endp); if (eval_error != ERR_NOERR || *endp != '\0') { /* pass through eval_error */ val = err_value; } /* else, use value returned */ eval_delete(es); } break; default: panic("bogus stat class"); } return val; } /* else, not found */ /* else, this is a bogus symbol */ eval_error = ERR_UNDEFVAR; val = err_value; return val;}/* maximum number of arguments that can passed to a dlite command handler */#define MAX_ARGS 4/* maximum length of a dlite command string argument */#define MAX_STR 128/* argument array entry, argument arrays are passed to command handlers */union arg_val_t { int as_modifier; unsigned int as_addr; unsigned int as_count; struct eval_value_t as_value; int as_access; int as_id; char as_str[MAX_STR];};/* a DLite command handler function pointer */typedef char * /* err str, NULL for no err */(*cmd_fn_t)(int nargs, /* number of arguments */ union arg_val_t args[]); /* argument vector *//* DLite command descriptor, fully describes a command supported by the DLite debugger command handler */struct dlite_cmd_t { char *cmd_str; /* DLite command string */ char *arg_strs[MAX_ARGS]; /* NULL-terminated cmd args (? - optional): m - size/type modifiers a - address expression c - count expression e - any expression s - any string t - access type {r|w|x} i - breakpoint id */ cmd_fn_t cmd_fn; /* implementing function */ char *help_str; /* DLite command help string */};/* forward handler decls */static char *dlite_help(int nargs, union arg_val_t args[]);static char *dlite_version(int nargs, union arg_val_t args[]);static char *dlite_terminate(int nargs, union arg_val_t args[]);static char *dlite_quit(int nargs, union arg_val_t args[]);static char *dlite_cont(int nargs, union arg_val_t args[]);static char *dlite_step(int nargs, union arg_val_t args[]);static char *dlite_print(int nargs, union arg_val_t args[]);static char *dlite_options(int nargs, union arg_val_t args[]);static char *dlite_option(int nargs, union arg_val_t args[]);static char *dlite_stats(int nargs, union arg_val_t args[]);static char *dlite_stat(int nargs, union arg_val_t args[]);static char *dlite_whatis(int nargs, union arg_val_t args[]);static char *dlite_regs(int nargs, union arg_val_t args[]);static char *dlite_iregs(int nargs, union arg_val_t args[]);static char *dlite_fpregs(int nargs, union arg_val_t args[]);static char *dlite_mstate(int nargs, union arg_val_t args[]);static char *dlite_display(int nargs, union arg_val_t args[]);static char *dlite_dump(int nargs, union arg_val_t args[]);static char *dlite_dis(int nargs, union arg_val_t args[]);static char *dlite_break(int nargs, union arg_val_t args[]);static char *dlite_dbreak(int nargs, union arg_val_t args[]);static char *dlite_rbreak(int nargs, union arg_val_t args[]);static char *dlite_breaks(int nargs, union arg_val_t args[]);static char *dlite_delete(int nargs, union arg_val_t args[]);static char *dlite_clear(int nargs, union arg_val_t args[]);static char *dlite_symbols(int nargs, union arg_val_t args[]);static char *dlite_tsymbols(int nargs, union arg_val_t args[]);static char *dlite_dsymbols(int nargs, union arg_val_t args[]);static char *dlite_symbol(int nargs, union arg_val_t args[]);/* DLite debugger command parser command definitions, NOTE: optional arguments must be trailing arguments, otherwise the command parser will break (modifiers are an exception to this rule) */static struct dlite_cmd_t cmd_db[] ={ { "help", { "s?", NULL }, dlite_help, "print command reference" }, { "version", { NULL }, dlite_version, "print DLite version information" }, { "terminate", { NULL }, dlite_terminate, "terminate the simulation with statistics" }, { "quit", { NULL }, dlite_quit, "exit the simulator" }, { "cont", { "a?", NULL }, dlite_cont, "continue program execution (optionally at <addr>)" }, { "step", { NULL }, dlite_step, "step program one instruction" },#if 0 /* NYI */ { "next", { NULL }, dlite_next, "step program one instruction in current procedure" },#endif { "print", { "m?", "e", NULL }, dlite_print, "print the value of <expr> using format <modifiers>" }, { "options", { NULL }, dlite_options, "print the value of all options" }, { "option", { "s", NULL }, dlite_option, "print the value of an option" }, { "stats", { NULL }, dlite_stats, "print the value of all statistical variables" }, { "stat", { "s", NULL }, dlite_stat, "print the value of a statistical variable" }, { "whatis", { "e", NULL }, dlite_whatis, "print the type of expression <expr>" }, { "---", { NULL }, NULL, NULL }, { "regs", { NULL }, dlite_regs, "print all register contents" }, { "iregs", { NULL }, dlite_iregs, "print integer register contents" }, { "fpregs", { NULL }, dlite_fpregs, "print floating point register contents" }, { "mstate", { "s?", NULL }, dlite_mstate, "print machine specific state (simulator dependent)" }, { "display", { "m?", "a", NULL }, dlite_display, "display the value at memory location <addr> using format <modifiers>" }, { "dump", { "a?", "c?", NULL }, dlite_dump, "dump memory at <addr> (optionally for <cnt> words)" }, { "dis", { "a?" "c?", NULL }, dlite_dis, "disassemble instructions at <addr> (for <cnt> insts)" }, { "break", { "a", NULL }, dlite_break, "set breakpoint at <addr>, returns <id> of breakpoint" }, { "dbreak", { "a", "t?", NULL }, dlite_dbreak, "set data breakpoint at <addr> (for (r)ead, (w)rite,\n" " and/or e(x)ecute, returns <id> of breakpoint" }, { "rbreak", { "s", "t?", NULL }, dlite_rbreak, "set read/write/exec breakpoint at <range> (for (r)ead, (w)rite,\n" " and/or e(x)ecute, returns <id> of breakpoint" }, { "breaks", { NULL }, dlite_breaks, "list active code and data breakpoints" }, { "delete", { "i", NULL }, dlite_delete, "delete breakpoint <id>" }, { "clear", { NULL }, dlite_clear, "clear all breakpoints (code and data)" }, { "---", { NULL }, NULL, NULL }, { "symbols", { NULL }, dlite_symbols, "print the value of all program symbols" }, { "tsymbols", { NULL }, dlite_tsymbols, "print the value of all program text symbols" }, { "dsymbols", { NULL }, dlite_dsymbols, "print the value of all program data symbols" }, { "symbol", { "s", NULL }, dlite_symbol, "print the value of a symbol" }, { "---", { NULL }, NULL, NULL }, /* list terminator */ { NULL, { NULL }, NULL, NULL }};/* help command trailing text */static char *dlite_help_tail = "Arguments <addr>, <cnt>, <expr>, and <id> are any legal expression:\n" " <expr> <- <factor> +|- <expr>\n" " <factor> <- <term> *|/ <factor>\n" " <term> <- ( <expr> )\n" " | - <term>\n" " | <const>\n" " | <symbol>\n" " | <file:loc>\n" "\n" "Command modifiers <mods> are any of the following:\n" "\n" " b - print a byte\n" " h - print a half (short)\n" " w - print a word (default)\n" " t - print in decimal format (default)\n" " o - print in octal format\n" " x - print in hex format\n" " 1 - print in binary format\n" " f - print a float\n" " d - print a double\n" " c - print a character\n" " s - print a string\n";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -