Implemented sym command.

This commit is contained in:
Daniel Beer 2010-03-27 23:47:17 +13:00
parent 37dcbfce6e
commit da34c6c1bd
4 changed files with 192 additions and 73 deletions

223
main.c
View File

@ -676,12 +676,6 @@ static int cmd_prog(char **arg)
return result;
}
static int cmd_nosyms(char **arg)
{
stab_clear();
return 0;
}
static int cmd_eval(char **arg)
{
int addr;
@ -704,29 +698,147 @@ static int cmd_eval(char **arg)
return 0;
}
static int cmd_syms(char **arg)
static int cmd_sym_load_add(int clear, char **arg)
{
FILE *in = fopen(*arg, "r");
int result = 0;
if (!in) {
fprintf(stderr, "syms: %s: %s\n", *arg, strerror(errno));
fprintf(stderr, "sym: %s: %s\n", *arg, strerror(errno));
return -1;
}
stab_clear();
if (clear)
stab_clear();
if (elf32_check(in))
result = elf32_syms(in);
else if (symmap_check(in))
result = symmap_syms(in);
else
fprintf(stderr, "syms: %s: unknown file type\n", *arg);
fprintf(stderr, "sym: %s: unknown file type\n", *arg);
fclose(in);
return result;
}
static FILE *savemap_out;
static int savemap_write(const char *name, u_int16_t value)
{
if (fprintf(savemap_out, "%08x t %s\n", value, name) < 0) {
fprintf(stderr, "sym: error writing symbols: %s\n",
strerror(errno));
return -1;
}
return 0;
}
static int cmd_sym_savemap(char **arg)
{
char *fname = get_arg(arg);
if (!fname) {
fprintf(stderr, "sym: filename required to save map\n");
return -1;
}
savemap_out = fopen(fname, "w");
if (!savemap_out) {
fprintf(stderr, "sym: couldn't write to %s: %s\n", fname,
strerror(errno));
return -1;
}
if (stab_enum(savemap_write) < 0)
return -1;
if (fclose(savemap_out) < 0) {
fprintf(stderr, "sym: error closing %s: %s\n", fname,
strerror(errno));
return -1;
}
return 0;
}
static int printsym(const char *name, u_int16_t value)
{
printf("0x%04x: %s\n", value, name);
return 0;
}
static int cmd_sym(char **arg)
{
char *subcmd = get_arg(arg);
if (!subcmd) {
fprintf(stderr, "sym: need to specify a subcommand "
"(try \"help sym\")\n");
return -1;
}
if (!strcasecmp(subcmd, "clear")) {
stab_clear();
return 0;
}
if (!strcasecmp(subcmd, "set")) {
char *name = get_arg(arg);
char *val_text = get_arg(arg);
int value;
if (!(name && val_text)) {
fprintf(stderr, "sym: need a name and value to set "
"symbol table entries\n");
return -1;
}
if (stab_parse(val_text, &value) < 0) {
fprintf(stderr, "sym: can't parse value: %s\n",
val_text);
return -1;
}
return stab_set(name, value);
}
if (!strcasecmp(subcmd, "del")) {
char *name = get_arg(arg);
if (!name) {
fprintf(stderr, "sym: need a name to delete "
"symbol table entries\n");
return -1;
}
return stab_del(name);
}
if (!strcasecmp(subcmd, "load"))
return cmd_sym_load_add(1, arg);
if (!strcasecmp(subcmd, "add"))
return cmd_sym_load_add(0, arg);
if (!strcasecmp(subcmd, "savemap"))
return cmd_sym_savemap(arg);
if (!strcasecmp(subcmd, "find")) {
char *expr = get_arg(arg);
if (!expr) {
stab_enum(printsym);
return 0;
}
return stab_re_search(expr, printsym) < 0 ? -1 : 0;
}
fprintf(stderr, "sym: unknown subcommand: %s\n", subcmd);
return -1;
}
static int cmd_gdb(char **arg)
{
char *port_text = get_arg(arg);
@ -842,61 +954,70 @@ static int cmd_read(char **arg)
static const struct command all_commands[] = {
{"=", cmd_eval,
"= <expression>\n"
" Evaluate an expression using the symbol table.\n"},
"= <expression>\n"
" Evaluate an expression using the symbol table.\n"},
{"dis", cmd_dis,
"dis <address> [length]\n"
" Disassemble a section of memory.\n"},
"dis <address> [length]\n"
" Disassemble a section of memory.\n"},
{"erase", cmd_erase,
"erase\n"
" Erase the device under test.\n"},
"erase\n"
" Erase the device under test.\n"},
{"gdb", cmd_gdb,
"gdb [port]\n"
" Run a GDB remote stub on the given TCP/IP port.\n"},
"gdb [port]\n"
" Run a GDB remote stub on the given TCP/IP port.\n"},
{"help", cmd_help,
"help [command]\n"
" Without arguments, displays a list of commands. With a command name as\n"
" an argument, displays help for that command.\n"},
"help [command]\n"
" Without arguments, displays a list of commands. With a command\n"
" name as an argument, displays help for that command.\n"},
{"hexout", cmd_hexout,
"hexout <address> <length> <filename.hex>\n"
" Save a region of memory into a HEX file.\n"},
"hexout <address> <length> <filename.hex>\n"
" Save a region of memory into a HEX file.\n"},
{"md", cmd_md,
"md <address> [length]\n"
" Read the specified number of bytes from memory at the given address,\n"
" and display a hexdump.\n"},
"md <address> [length]\n"
" Read the specified number of bytes from memory at the given\n"
" address, and display a hexdump.\n"},
{"mw", cmd_mw,
"mw <address> bytes ...\n"
" Write a sequence of bytes to a memory address. Byte values are\n"
" two-digit hexadecimal numbers.\n"},
{"nosyms", cmd_nosyms,
"nosyms\n"
" Clear the symbol table.\n"},
"mw <address> bytes ...\n"
" Write a sequence of bytes to a memory address. Byte values are\n"
" two-digit hexadecimal numbers.\n"},
{"prog", cmd_prog,
"prog <filename>\n"
" Erase the device and flash the data contained in a binary file. This\n"
" command also loads symbols from the file, if available.\n"},
"prog <filename>\n"
" Erase the device and flash the data contained in a binary file.\n"
" This command also loads symbols from the file, if available.\n"},
{"read", cmd_read,
"read <filename>\n"
" Read commands from a file and evaluate them.\n"},
"read <filename>\n"
" Read commands from a file and evaluate them.\n"},
{"regs", cmd_regs,
"regs\n"
" Read and display the current register contents.\n"},
"regs\n"
" Read and display the current register contents.\n"},
{"reset", cmd_reset,
"reset\n"
" Reset (and halt) the CPU.\n"},
"reset\n"
" Reset (and halt) the CPU.\n"},
{"run", cmd_run,
"run [breakpoint]\n"
" Run the CPU until either a specified breakpoint occurs or the command\n"
" is interrupted.\n"},
"run [breakpoint]\n"
" Run the CPU until either a specified breakpoint occurs or the\n"
" command is interrupted.\n"},
{"set", cmd_set,
"set <register> <value>\n"
" Change the value of a CPU register.\n"},
"set <register> <value>\n"
" Change the value of a CPU register.\n"},
{"step", cmd_step,
"step [count]\n"
" Single-step the CPU, and display the register state.\n"},
{"syms", cmd_syms,
"syms <filename>\n"
" Load symbols from the given file.\n"},
"step [count]\n"
" Single-step the CPU, and display the register state.\n"},
{"sym", cmd_sym,
"sym clear\n"
" Clear the symbol table.\n"
"sym set <name> <value>\n"
" Set or overwrite the value of a symbol.\n"
"sym del <name>\n"
" Delete a symbol from the symbol table.\n"
"sym load <filename>\n"
" Load symbols from the given file.\n"
"sym add <filename>\n"
" Load additional symbols from the given file.\n"
"sym savemap <filename>\n"
" Save the current symbols to a BSD-style symbol file.\n"
"sym find <regex>\n"
" Search for symbols by regular expression.\n"},
{NULL, NULL, NULL}
};

View File

@ -135,9 +135,6 @@ numbers separated by spaces.
Unless used in the simulation mode, this command can only be used for
programming flash memory.
.IP "nosyms"
Clear all symbols from the symbol table. Symbols may be reloaded with
the \fBsyms\fR command.
.IP "prog \fIfilename\fR"
Erase and reprogram the device under test using the binary file
supplied. The file format will be auto-detected and may be either
@ -181,13 +178,32 @@ instructions at the address selected by the program counter.
An optional count can be specified to step multiple times. If no
argument is given, the CPU steps once.
.IP "syms \fIfilename\fR"
.IP "sym clear"
Clear the symbol table, deleting all symbols.
.IP "sym set \fIname\fR \fIvalue\fR"
Set or alter the value of a symbol. The value given may be an address
expression.
.IP "sym del \fIname\fR"
Delete the given symbol from the symbol table.
.IP "sym load \fIfilename\fR"
Load symbols from the specified file and add them to the symbol table.
The file format will be auto-detected and may be either ELF32 or a
BSD-style symbol listing (like the output from \fBnm\fR(1)).
Symbols can be combined from many sources, as the syms command adds
to the existing symbol table without discarding existing symbols.
.IP "sym add \fIfilename\fR"
This command is similar to \fBsym load\fR, except that the symbol table
is not cleared first. By using this command, symbols from multiple
sources can be combined.
.IP "sym savemap \fIfilename\fR"
Save all symbols currently defined to the given file. The symbols are
saved as a BSD-style symbol table. Note that symbol types are not stored
by MSPDebug, and all symbols are saved as type \fBt\fR.
.IP "sym find [\fIregex\fR]"
Search for symbols. If a regular expression is given, then all symbols
matching the expression are printed. If no expression is specified, then
the entire symbol table is listed.
.SH ADDRESS EXPRESSIONS
Any command which accepts a memory address, length or register value
as an argument may be given an address expression. An address

12
stab.c
View File

@ -99,7 +99,6 @@ static const struct btree_def addr_table_def = {
static btree_t sym_table;
static btree_t addr_table;
static int is_modified;
/************************************************************************
* Public interface
@ -133,17 +132,6 @@ void stab_clear(void)
{
btree_clear(sym_table);
btree_clear(addr_table);
is_modified = 0;
}
int stab_is_modified(void)
{
return is_modified;
}
void stab_clear_modified(void)
{
is_modified = 0;
}
int stab_set(const char *name, u_int16_t addr)

6
stab.h
View File

@ -30,12 +30,6 @@ void stab_exit(void);
/* Reset the symbol table (delete all symbols) */
void stab_clear(void);
/* Check to see if the symbol table has been modified, and clear
* modification flag.
*/
int stab_is_modified(void);
void stab_clear_modified(void);
/* Set a symbol in the table. Returns 0 on success, or -1 on error. */
int stab_set(const char *name, u_int16_t value);