Implemented sym command.
This commit is contained in:
parent
37dcbfce6e
commit
da34c6c1bd
223
main.c
223
main.c
|
@ -676,12 +676,6 @@ static int cmd_prog(char **arg)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_nosyms(char **arg)
|
|
||||||
{
|
|
||||||
stab_clear();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmd_eval(char **arg)
|
static int cmd_eval(char **arg)
|
||||||
{
|
{
|
||||||
int addr;
|
int addr;
|
||||||
|
@ -704,29 +698,147 @@ static int cmd_eval(char **arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_syms(char **arg)
|
static int cmd_sym_load_add(int clear, char **arg)
|
||||||
{
|
{
|
||||||
FILE *in = fopen(*arg, "r");
|
FILE *in = fopen(*arg, "r");
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
if (!in) {
|
if (!in) {
|
||||||
fprintf(stderr, "syms: %s: %s\n", *arg, strerror(errno));
|
fprintf(stderr, "sym: %s: %s\n", *arg, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
stab_clear();
|
if (clear)
|
||||||
|
stab_clear();
|
||||||
|
|
||||||
if (elf32_check(in))
|
if (elf32_check(in))
|
||||||
result = elf32_syms(in);
|
result = elf32_syms(in);
|
||||||
else if (symmap_check(in))
|
else if (symmap_check(in))
|
||||||
result = symmap_syms(in);
|
result = symmap_syms(in);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "syms: %s: unknown file type\n", *arg);
|
fprintf(stderr, "sym: %s: unknown file type\n", *arg);
|
||||||
|
|
||||||
fclose(in);
|
fclose(in);
|
||||||
return result;
|
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)
|
static int cmd_gdb(char **arg)
|
||||||
{
|
{
|
||||||
char *port_text = get_arg(arg);
|
char *port_text = get_arg(arg);
|
||||||
|
@ -842,61 +954,70 @@ static int cmd_read(char **arg)
|
||||||
|
|
||||||
static const struct command all_commands[] = {
|
static const struct command all_commands[] = {
|
||||||
{"=", cmd_eval,
|
{"=", cmd_eval,
|
||||||
"= <expression>\n"
|
"= <expression>\n"
|
||||||
" Evaluate an expression using the symbol table.\n"},
|
" Evaluate an expression using the symbol table.\n"},
|
||||||
{"dis", cmd_dis,
|
{"dis", cmd_dis,
|
||||||
"dis <address> [length]\n"
|
"dis <address> [length]\n"
|
||||||
" Disassemble a section of memory.\n"},
|
" Disassemble a section of memory.\n"},
|
||||||
{"erase", cmd_erase,
|
{"erase", cmd_erase,
|
||||||
"erase\n"
|
"erase\n"
|
||||||
" Erase the device under test.\n"},
|
" Erase the device under test.\n"},
|
||||||
{"gdb", cmd_gdb,
|
{"gdb", cmd_gdb,
|
||||||
"gdb [port]\n"
|
"gdb [port]\n"
|
||||||
" Run a GDB remote stub on the given TCP/IP port.\n"},
|
" Run a GDB remote stub on the given TCP/IP port.\n"},
|
||||||
{"help", cmd_help,
|
{"help", cmd_help,
|
||||||
"help [command]\n"
|
"help [command]\n"
|
||||||
" Without arguments, displays a list of commands. With a command name as\n"
|
" Without arguments, displays a list of commands. With a command\n"
|
||||||
" an argument, displays help for that command.\n"},
|
" name as an argument, displays help for that command.\n"},
|
||||||
{"hexout", cmd_hexout,
|
{"hexout", cmd_hexout,
|
||||||
"hexout <address> <length> <filename.hex>\n"
|
"hexout <address> <length> <filename.hex>\n"
|
||||||
" Save a region of memory into a HEX file.\n"},
|
" Save a region of memory into a HEX file.\n"},
|
||||||
{"md", cmd_md,
|
{"md", cmd_md,
|
||||||
"md <address> [length]\n"
|
"md <address> [length]\n"
|
||||||
" Read the specified number of bytes from memory at the given address,\n"
|
" Read the specified number of bytes from memory at the given\n"
|
||||||
" and display a hexdump.\n"},
|
" address, and display a hexdump.\n"},
|
||||||
{"mw", cmd_mw,
|
{"mw", cmd_mw,
|
||||||
"mw <address> bytes ...\n"
|
"mw <address> bytes ...\n"
|
||||||
" Write a sequence of bytes to a memory address. Byte values are\n"
|
" Write a sequence of bytes to a memory address. Byte values are\n"
|
||||||
" two-digit hexadecimal numbers.\n"},
|
" two-digit hexadecimal numbers.\n"},
|
||||||
{"nosyms", cmd_nosyms,
|
|
||||||
"nosyms\n"
|
|
||||||
" Clear the symbol table.\n"},
|
|
||||||
{"prog", cmd_prog,
|
{"prog", cmd_prog,
|
||||||
"prog <filename>\n"
|
"prog <filename>\n"
|
||||||
" Erase the device and flash the data contained in a binary file. This\n"
|
" Erase the device and flash the data contained in a binary file.\n"
|
||||||
" command also loads symbols from the file, if available.\n"},
|
" This command also loads symbols from the file, if available.\n"},
|
||||||
{"read", cmd_read,
|
{"read", cmd_read,
|
||||||
"read <filename>\n"
|
"read <filename>\n"
|
||||||
" Read commands from a file and evaluate them.\n"},
|
" Read commands from a file and evaluate them.\n"},
|
||||||
{"regs", cmd_regs,
|
{"regs", cmd_regs,
|
||||||
"regs\n"
|
"regs\n"
|
||||||
" Read and display the current register contents.\n"},
|
" Read and display the current register contents.\n"},
|
||||||
{"reset", cmd_reset,
|
{"reset", cmd_reset,
|
||||||
"reset\n"
|
"reset\n"
|
||||||
" Reset (and halt) the CPU.\n"},
|
" Reset (and halt) the CPU.\n"},
|
||||||
{"run", cmd_run,
|
{"run", cmd_run,
|
||||||
"run [breakpoint]\n"
|
"run [breakpoint]\n"
|
||||||
" Run the CPU until either a specified breakpoint occurs or the command\n"
|
" Run the CPU until either a specified breakpoint occurs or the\n"
|
||||||
" is interrupted.\n"},
|
" command is interrupted.\n"},
|
||||||
{"set", cmd_set,
|
{"set", cmd_set,
|
||||||
"set <register> <value>\n"
|
"set <register> <value>\n"
|
||||||
" Change the value of a CPU register.\n"},
|
" Change the value of a CPU register.\n"},
|
||||||
{"step", cmd_step,
|
{"step", cmd_step,
|
||||||
"step [count]\n"
|
"step [count]\n"
|
||||||
" Single-step the CPU, and display the register state.\n"},
|
" Single-step the CPU, and display the register state.\n"},
|
||||||
{"syms", cmd_syms,
|
{"sym", cmd_sym,
|
||||||
"syms <filename>\n"
|
"sym clear\n"
|
||||||
" Load symbols from the given file.\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}
|
{NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
24
mspdebug.man
24
mspdebug.man
|
@ -135,9 +135,6 @@ numbers separated by spaces.
|
||||||
|
|
||||||
Unless used in the simulation mode, this command can only be used for
|
Unless used in the simulation mode, this command can only be used for
|
||||||
programming flash memory.
|
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"
|
.IP "prog \fIfilename\fR"
|
||||||
Erase and reprogram the device under test using the binary file
|
Erase and reprogram the device under test using the binary file
|
||||||
supplied. The file format will be auto-detected and may be either
|
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
|
An optional count can be specified to step multiple times. If no
|
||||||
argument is given, the CPU steps once.
|
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.
|
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
|
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)).
|
BSD-style symbol listing (like the output from \fBnm\fR(1)).
|
||||||
|
|
||||||
Symbols can be combined from many sources, as the syms command adds
|
Symbols can be combined from many sources, as the syms command adds
|
||||||
to the existing symbol table without discarding existing symbols.
|
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
|
.SH ADDRESS EXPRESSIONS
|
||||||
Any command which accepts a memory address, length or register value
|
Any command which accepts a memory address, length or register value
|
||||||
as an argument may be given an address expression. An address
|
as an argument may be given an address expression. An address
|
||||||
|
|
12
stab.c
12
stab.c
|
@ -99,7 +99,6 @@ static const struct btree_def addr_table_def = {
|
||||||
|
|
||||||
static btree_t sym_table;
|
static btree_t sym_table;
|
||||||
static btree_t addr_table;
|
static btree_t addr_table;
|
||||||
static int is_modified;
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Public interface
|
* Public interface
|
||||||
|
@ -133,17 +132,6 @@ void stab_clear(void)
|
||||||
{
|
{
|
||||||
btree_clear(sym_table);
|
btree_clear(sym_table);
|
||||||
btree_clear(addr_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)
|
int stab_set(const char *name, u_int16_t addr)
|
||||||
|
|
6
stab.h
6
stab.h
|
@ -30,12 +30,6 @@ void stab_exit(void);
|
||||||
/* Reset the symbol table (delete all symbols) */
|
/* Reset the symbol table (delete all symbols) */
|
||||||
void stab_clear(void);
|
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. */
|
/* Set a symbol in the table. Returns 0 on success, or -1 on error. */
|
||||||
int stab_set(const char *name, u_int16_t value);
|
int stab_set(const char *name, u_int16_t value);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue