Separated command database.
This commit is contained in:
parent
e834241e90
commit
6dd1ab25c3
3
Makefile
3
Makefile
|
@ -56,7 +56,8 @@ install: mspdebug mspdebug.man
|
|||
mspdebug: main.o fet.o rf2500.o dis.o uif.o olimex.o ihex.o elf32.o stab.o \
|
||||
util.o bsl.o sim.o symmap.o gdb.o btree.o rtools.o sym.o devcmd.o \
|
||||
cproc.o vector.o output_util.o expr.o fet_error.o binfile.o \
|
||||
fet_db.o usbutil.o titext.o srec.o device.o coff.o opdb.o output.o
|
||||
fet_db.o usbutil.o titext.o srec.o device.o coff.o opdb.o output.o \
|
||||
cmddb.o
|
||||
$(CC) $(LDFLAGS) $(MACPORTS_LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS)
|
||||
|
||||
.c.o:
|
||||
|
|
|
@ -0,0 +1,247 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2009, 2010 Daniel Beer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "cmddb.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "devcmd.h"
|
||||
#include "gdb.h"
|
||||
#include "rtools.h"
|
||||
#include "cproc.h"
|
||||
#include "sym.h"
|
||||
|
||||
const struct cmddb_record commands[] = {
|
||||
{
|
||||
.name = "help",
|
||||
.func = cmd_help,
|
||||
.help =
|
||||
"help [command]\n"
|
||||
" Without arguments, displays a list of commands. With a command\n"
|
||||
" name as an argument, displays help for that command.\n"
|
||||
},
|
||||
{
|
||||
.name = "opt",
|
||||
.func = cmd_opt,
|
||||
.help =
|
||||
"opt [name] [value]\n"
|
||||
" Query or set option variables. With no arguments, displays all\n"
|
||||
" available options.\n"
|
||||
},
|
||||
{
|
||||
.name = "read",
|
||||
.func = cmd_read,
|
||||
.help =
|
||||
"read <filename>\n"
|
||||
" Read commands from a file and evaluate them.\n"
|
||||
},
|
||||
{
|
||||
.name = "setbreak",
|
||||
.func = cmd_setbreak,
|
||||
.help =
|
||||
"setbreak <addr> [index]\n"
|
||||
" Set a breakpoint. If no index is specified, the first available\n"
|
||||
" slot will be used.\n"
|
||||
},
|
||||
{
|
||||
.name = "delbreak",
|
||||
.func = cmd_delbreak,
|
||||
.help =
|
||||
"delbreak [index]\n"
|
||||
" Delete a breakpoint. If no index is specified, then all active\n"
|
||||
" breakpoints are cleared.\n"
|
||||
},
|
||||
{
|
||||
.name = "break",
|
||||
.func = cmd_break,
|
||||
.help =
|
||||
"break\n"
|
||||
" List active breakpoints.\n"
|
||||
},
|
||||
{
|
||||
.name = "regs",
|
||||
.func = cmd_regs,
|
||||
.help =
|
||||
"regs\n"
|
||||
" Read and display the current register contents.\n"
|
||||
},
|
||||
{
|
||||
.name = "prog",
|
||||
.func = cmd_prog,
|
||||
.help =
|
||||
"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"
|
||||
},
|
||||
{
|
||||
.name = "md",
|
||||
.func = cmd_md,
|
||||
.help =
|
||||
"md <address> [length]\n"
|
||||
" Read the specified number of bytes from memory at the given\n"
|
||||
" address, and display a hexdump.\n"
|
||||
},
|
||||
{
|
||||
.name = "mw",
|
||||
.func = cmd_mw,
|
||||
.help =
|
||||
"mw <address> bytes ...\n"
|
||||
" Write a sequence of bytes to a memory address. Byte values are\n"
|
||||
" two-digit hexadecimal numbers.\n"
|
||||
},
|
||||
{
|
||||
.name = "reset",
|
||||
.func = cmd_reset,
|
||||
.help =
|
||||
"reset\n"
|
||||
" Reset (and halt) the CPU.\n"
|
||||
},
|
||||
{
|
||||
.name = "erase",
|
||||
.func = cmd_erase,
|
||||
.help =
|
||||
"erase\n"
|
||||
" Erase the device under test.\n"
|
||||
},
|
||||
{
|
||||
.name = "step",
|
||||
.func = cmd_step,
|
||||
.help =
|
||||
"step [count]\n"
|
||||
" Single-step the CPU, and display the register state.\n"
|
||||
},
|
||||
{
|
||||
.name = "run",
|
||||
.func = cmd_run,
|
||||
.help =
|
||||
"run\n"
|
||||
" Run the CPU to until a breakpoint is reached or the command is\n"
|
||||
" interrupted.\n"
|
||||
},
|
||||
{
|
||||
.name = "set",
|
||||
.func = cmd_set,
|
||||
.help =
|
||||
"set <register> <value>\n"
|
||||
" Change the value of a CPU register.\n"
|
||||
},
|
||||
{
|
||||
.name = "dis",
|
||||
.func = cmd_dis,
|
||||
.help =
|
||||
"dis <address> [length]\n"
|
||||
" Disassemble a section of memory.\n"
|
||||
},
|
||||
{
|
||||
.name = "hexout",
|
||||
.func = cmd_hexout,
|
||||
.help =
|
||||
"hexout <address> <length> <filename.hex>\n"
|
||||
" Save a region of memory into a HEX file.\n"
|
||||
},
|
||||
{
|
||||
.name = "gdb",
|
||||
.func = cmd_gdb,
|
||||
.help =
|
||||
"gdb [port]\n"
|
||||
" Run a GDB remote stub on the given TCP/IP port.\n"
|
||||
},
|
||||
{
|
||||
.name = "=",
|
||||
.func = cmd_eval,
|
||||
.help =
|
||||
"= <expression>\n"
|
||||
" Evaluate an expression using the symbol table.\n"
|
||||
},
|
||||
{
|
||||
.name = "sym",
|
||||
.func = cmd_sym,
|
||||
.help =
|
||||
"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 import <filename>\n"
|
||||
" Load symbols from the given file.\n"
|
||||
"sym import+ <filename>\n"
|
||||
" Load additional symbols from the given file.\n"
|
||||
"sym export <filename>\n"
|
||||
" Save the current symbols to a BSD-style symbol file.\n"
|
||||
"sym find <regex>\n"
|
||||
" Search for symbols by regular expression.\n"
|
||||
"sym rename <regex> <string>\n"
|
||||
" Replace every occurance of a pattern in symbol names.\n"
|
||||
},
|
||||
{
|
||||
.name = "isearch",
|
||||
.func = cmd_isearch,
|
||||
.help =
|
||||
"isearch <address> <length> [options ...]\n"
|
||||
" Search for an instruction matching certain search terms. These\n"
|
||||
" terms may be any of the following:\n"
|
||||
" opcode <opcode>\n"
|
||||
" byte|word|aword\n"
|
||||
" jump|single|double|noarg\n"
|
||||
" src <value>\n"
|
||||
" dst <value>\n"
|
||||
" srcreg <register>\n"
|
||||
" dstreg <register>\n"
|
||||
" srcmode R|I|S|&|@|+|#\n"
|
||||
" dstmode R|I|S|&|@|+|#\n"
|
||||
" For single-operand instructions, the operand is considered the\n"
|
||||
" destination operand.\n"
|
||||
},
|
||||
{
|
||||
.name = "cgraph",
|
||||
.func = cmd_cgraph,
|
||||
.help =
|
||||
"cgraph <address> <length> [function]\n"
|
||||
" Analyse the range given and produce a call graph. Displays a summary\n"
|
||||
" of all functions if no function address is given.\n"
|
||||
}
|
||||
};
|
||||
|
||||
int cmddb_get(const char *name, struct cmddb_record *ret)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LEN(commands); i++) {
|
||||
const struct cmddb_record *r = &commands[i];
|
||||
|
||||
if (!strcasecmp(r->name, name)) {
|
||||
memcpy(ret, r, sizeof(*ret));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cmddb_enum(cmddb_enum_func_t func, void *user_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LEN(commands); i++)
|
||||
if (func(user_data, &commands[i]) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2009, 2010 Daniel Beer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef CMDDB_H_
|
||||
#define CMDDB_H_
|
||||
|
||||
#include "cproc.h"
|
||||
|
||||
typedef int (*cproc_command_func_t)(cproc_t cp, char **arg);
|
||||
|
||||
struct cmddb_record {
|
||||
const char *name;
|
||||
cproc_command_func_t func;
|
||||
const char *help;
|
||||
};
|
||||
|
||||
/* Fetch a command record */
|
||||
int cmddb_get(const char *name, struct cmddb_record *r);
|
||||
|
||||
/* Enumerate all command records.
|
||||
*
|
||||
* Returns 0, or -1 if an error occurs during enumeration.
|
||||
*/
|
||||
typedef int (*cmddb_enum_func_t)(void *user_data,
|
||||
const struct cmddb_record *r);
|
||||
|
||||
int cmddb_enum(cmddb_enum_func_t func, void *user_data);
|
||||
|
||||
#endif
|
125
cproc.c
125
cproc.c
|
@ -35,56 +35,26 @@
|
|||
#include "stab.h"
|
||||
#include "util.h"
|
||||
#include "output.h"
|
||||
#include "cmddb.h"
|
||||
|
||||
struct cproc {
|
||||
struct vector command_list;
|
||||
int lists_modified;
|
||||
|
||||
int modify_flags;
|
||||
int in_reader_loop;
|
||||
};
|
||||
|
||||
static struct cproc_command *find_command(cproc_t cp, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cp->command_list.size; i++) {
|
||||
struct cproc_command *cmd =
|
||||
VECTOR_PTR(cp->command_list, i, struct cproc_command);
|
||||
|
||||
if (!strcasecmp(cmd->name, name))
|
||||
return cmd;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int namelist_cmp(const void *a, const void *b)
|
||||
{
|
||||
return strcasecmp(*(const char **)a, *(const char **)b);
|
||||
}
|
||||
|
||||
/* NOTE: Both sort_lists and namelist_print assume that the first item in each
|
||||
* vector element is a const char *
|
||||
*/
|
||||
static void sort_lists(cproc_t cp)
|
||||
{
|
||||
if (!cp->lists_modified)
|
||||
return;
|
||||
|
||||
if (cp->command_list.ptr)
|
||||
qsort(cp->command_list.ptr, cp->command_list.size,
|
||||
cp->command_list.elemsize, namelist_cmp);
|
||||
|
||||
cp->lists_modified = 0;
|
||||
}
|
||||
|
||||
static void namelist_print(struct vector *v)
|
||||
{
|
||||
int i;
|
||||
int max_len = 0;
|
||||
int rows, cols;
|
||||
|
||||
qsort(v->ptr, v->size, v->elemsize, namelist_cmp);
|
||||
|
||||
for (i = 0; i < v->size; i++) {
|
||||
const char *text = VECTOR_AT(*v, i, const char *);
|
||||
int len = strlen(text);
|
||||
|
@ -137,22 +107,25 @@ static const char *type_text(opdb_type_t type)
|
|||
static int push_option_name(void *user_data, const struct opdb_key *key,
|
||||
const union opdb_value *value)
|
||||
{
|
||||
struct vector *v = (struct vector *)user_data;
|
||||
|
||||
return vector_push(v, &key->name, 1);
|
||||
return vector_push((struct vector *)user_data, &key->name, 1);
|
||||
}
|
||||
|
||||
static int cmd_help(cproc_t cp, char **arg)
|
||||
static int push_command_name(void *user_data, const struct cmddb_record *rec)
|
||||
{
|
||||
return vector_push((struct vector *)user_data, &rec->name, 1);
|
||||
}
|
||||
|
||||
int cmd_help(cproc_t cp, char **arg)
|
||||
{
|
||||
const char *topic = get_arg(arg);
|
||||
|
||||
if (topic) {
|
||||
const struct cproc_command *cmd = find_command(cp, topic);
|
||||
struct cmddb_record cmd;
|
||||
struct opdb_key key;
|
||||
|
||||
if (cmd) {
|
||||
if (!cmddb_get(topic, &cmd)) {
|
||||
printc("\x1b[1mCOMMAND: %s\x1b[0m\n\n%s\n",
|
||||
cmd->name, cmd->help);
|
||||
cmd.name, cmd.help);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -168,18 +141,23 @@ static int cmd_help(cproc_t cp, char **arg)
|
|||
struct vector v;
|
||||
|
||||
vector_init(&v, sizeof(const char *));
|
||||
sort_lists(cp);
|
||||
|
||||
printf("Available commands:\n");
|
||||
namelist_print(&cp->command_list);
|
||||
printf("\n");
|
||||
if (!cmddb_enum(push_command_name, &v)) {
|
||||
printf("Available commands:\n");
|
||||
namelist_print(&v);
|
||||
printf("\n");
|
||||
} else {
|
||||
perror("help: can't allocate memory for command list");
|
||||
}
|
||||
|
||||
vector_realloc(&v, 0);
|
||||
|
||||
if (!opdb_enum(push_option_name, &v)) {
|
||||
printf("Available options:\n");
|
||||
namelist_print(&v);
|
||||
printf("\n");
|
||||
} else {
|
||||
perror("failed to allocate memory");
|
||||
perror("help: can't allocate memory for option list");
|
||||
}
|
||||
|
||||
vector_destroy(&v);
|
||||
|
@ -236,7 +214,7 @@ static int display_option(void *user_data, const struct opdb_key *key,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_opt(cproc_t cp, char **arg)
|
||||
int cmd_opt(cproc_t cp, char **arg)
|
||||
{
|
||||
const char *opt_text = get_arg(arg);
|
||||
struct opdb_key key;
|
||||
|
@ -267,7 +245,7 @@ static int cmd_opt(cproc_t cp, char **arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_read(cproc_t cp, char **arg)
|
||||
int cmd_read(cproc_t cp, char **arg)
|
||||
{
|
||||
char *filename = get_arg(arg);
|
||||
|
||||
|
@ -279,32 +257,6 @@ static int cmd_read(cproc_t cp, char **arg)
|
|||
return cproc_process_file(cp, filename);
|
||||
}
|
||||
|
||||
static const struct cproc_command built_in_commands[] = {
|
||||
{
|
||||
.name = "help",
|
||||
.func = cmd_help,
|
||||
.help =
|
||||
"help [command]\n"
|
||||
" Without arguments, displays a list of commands. With a command\n"
|
||||
" name as an argument, displays help for that command.\n"
|
||||
},
|
||||
{
|
||||
.name = "opt",
|
||||
.func = cmd_opt,
|
||||
.help =
|
||||
"opt [name] [value]\n"
|
||||
" Query or set option variables. With no arguments, displays all\n"
|
||||
" available options.\n"
|
||||
},
|
||||
{
|
||||
.name = "read",
|
||||
.func = cmd_read,
|
||||
.help =
|
||||
"read <filename>\n"
|
||||
" Read commands from a file and evaluate them.\n"
|
||||
}
|
||||
};
|
||||
|
||||
cproc_t cproc_new(void)
|
||||
{
|
||||
cproc_t cp = malloc(sizeof(*cp));
|
||||
|
@ -313,35 +265,14 @@ cproc_t cproc_new(void)
|
|||
return NULL;
|
||||
|
||||
memset(cp, 0, sizeof(*cp));
|
||||
|
||||
vector_init(&cp->command_list, sizeof(struct cproc_command));
|
||||
|
||||
if (vector_push(&cp->command_list, &built_in_commands,
|
||||
ARRAY_LEN(built_in_commands)) < 0) {
|
||||
vector_destroy(&cp->command_list);
|
||||
free(cp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
void cproc_destroy(cproc_t cp)
|
||||
{
|
||||
vector_destroy(&cp->command_list);
|
||||
free(cp);
|
||||
}
|
||||
|
||||
int cproc_register_commands(cproc_t cp, const struct cproc_command *cmd,
|
||||
int count)
|
||||
{
|
||||
if (vector_push(&cp->command_list, cmd, count) < 0)
|
||||
return -1;
|
||||
|
||||
cp->lists_modified = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cproc_modify(cproc_t cp, int flags)
|
||||
{
|
||||
cp->modify_flags |= flags;
|
||||
|
@ -423,14 +354,14 @@ static int process_command(cproc_t cp, char *arg, int interactive)
|
|||
|
||||
cmd_text = get_arg(&arg);
|
||||
if (cmd_text) {
|
||||
const struct cproc_command *cmd = find_command(cp, cmd_text);
|
||||
struct cmddb_record cmd;
|
||||
|
||||
if (cmd) {
|
||||
if (!cmddb_get(cmd_text, &cmd)) {
|
||||
int old = cp->in_reader_loop;
|
||||
int ret;
|
||||
|
||||
cp->in_reader_loop = interactive;
|
||||
ret = cmd->func(cp, &arg);
|
||||
ret = cmd.func(cp, &arg);
|
||||
cp->in_reader_loop = old;
|
||||
|
||||
return ret;
|
||||
|
|
26
cproc.h
26
cproc.h
|
@ -27,21 +27,6 @@
|
|||
struct cproc;
|
||||
typedef struct cproc *cproc_t;
|
||||
|
||||
/* Command definitions.
|
||||
*
|
||||
* Each command is specified as a tuple of name, command function and help
|
||||
* text. When the command is invoked, the command function is called with
|
||||
* a mutable pointer to the command line text, and a pointer to the command
|
||||
* processor.
|
||||
*/
|
||||
typedef int (*cproc_command_func_t)(cproc_t cp, char **arg);
|
||||
|
||||
struct cproc_command {
|
||||
const char *name;
|
||||
cproc_command_func_t func;
|
||||
const char *help;
|
||||
};
|
||||
|
||||
/* Commmand processor modification flags.
|
||||
*
|
||||
* Within the context of a command processor, various data items may be
|
||||
|
@ -65,12 +50,6 @@ struct cproc_command {
|
|||
cproc_t cproc_new(void);
|
||||
void cproc_destroy(cproc_t cp);
|
||||
|
||||
/* Register commands and options with the command processor. These functions
|
||||
* return 0 on success or -1 if an error occurs (failure to allocate memory).
|
||||
*/
|
||||
int cproc_register_commands(cproc_t cp, const struct cproc_command *cmd,
|
||||
int count);
|
||||
|
||||
/* This should be called before a destructive operation to give the user
|
||||
* a chance to abort. If it returns 1, then the operation should be aborted.
|
||||
*
|
||||
|
@ -90,4 +69,9 @@ void cproc_reader_loop(cproc_t cp);
|
|||
int cproc_process_command(cproc_t cp, char *cmd);
|
||||
int cproc_process_file(cproc_t cp, const char *filename);
|
||||
|
||||
/* Built-in commands */
|
||||
int cmd_help(cproc_t cp, char **arg);
|
||||
int cmd_read(cproc_t cp, char **arg);
|
||||
int cmd_opt(cproc_t cp, char **arg);
|
||||
|
||||
#endif
|
||||
|
|
140
devcmd.c
140
devcmd.c
|
@ -31,7 +31,7 @@
|
|||
#include "util.h"
|
||||
#include "dis.h"
|
||||
|
||||
static int cmd_regs(cproc_t cp, char **arg)
|
||||
int cmd_regs(cproc_t cp, char **arg)
|
||||
{
|
||||
address_t regs[DEVICE_NUM_REGS];
|
||||
uint8_t code[16];
|
||||
|
@ -51,7 +51,7 @@ static int cmd_regs(cproc_t cp, char **arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_md(cproc_t cp, char **arg)
|
||||
int cmd_md(cproc_t cp, char **arg)
|
||||
{
|
||||
char *off_text = get_arg(arg);
|
||||
char *len_text = get_arg(arg);
|
||||
|
@ -94,7 +94,7 @@ static int cmd_md(cproc_t cp, char **arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_mw(cproc_t cp, char **arg)
|
||||
int cmd_mw(cproc_t cp, char **arg)
|
||||
{
|
||||
char *off_text = get_arg(arg);
|
||||
char *byte_text;
|
||||
|
@ -130,12 +130,12 @@ static int cmd_mw(cproc_t cp, char **arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_reset(cproc_t cp, char **arg)
|
||||
int cmd_reset(cproc_t cp, char **arg)
|
||||
{
|
||||
return device_default->ctl(device_default, DEVICE_CTL_RESET);
|
||||
}
|
||||
|
||||
static int cmd_erase(cproc_t cp, char **arg)
|
||||
int cmd_erase(cproc_t cp, char **arg)
|
||||
{
|
||||
if (device_default->ctl(device_default, DEVICE_CTL_HALT) < 0)
|
||||
return -1;
|
||||
|
@ -144,7 +144,7 @@ static int cmd_erase(cproc_t cp, char **arg)
|
|||
return device_default->ctl(device_default, DEVICE_CTL_ERASE);
|
||||
}
|
||||
|
||||
static int cmd_step(cproc_t cp, char **arg)
|
||||
int cmd_step(cproc_t cp, char **arg)
|
||||
{
|
||||
char *count_text = get_arg(arg);
|
||||
int count = 1;
|
||||
|
@ -161,7 +161,7 @@ static int cmd_step(cproc_t cp, char **arg)
|
|||
return cmd_regs(cp, NULL);
|
||||
}
|
||||
|
||||
static int cmd_run(cproc_t cp, char **arg)
|
||||
int cmd_run(cproc_t cp, char **arg)
|
||||
{
|
||||
device_status_t status;
|
||||
address_t regs[DEVICE_NUM_REGS];
|
||||
|
@ -210,7 +210,7 @@ static int cmd_run(cproc_t cp, char **arg)
|
|||
return cmd_regs(cp, NULL);
|
||||
}
|
||||
|
||||
static int cmd_set(cproc_t cp, char **arg)
|
||||
int cmd_set(cproc_t cp, char **arg)
|
||||
{
|
||||
char *reg_text = get_arg(arg);
|
||||
char *val_text = get_arg(arg);
|
||||
|
@ -244,7 +244,7 @@ static int cmd_set(cproc_t cp, char **arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_dis(cproc_t cp, char **arg)
|
||||
int cmd_dis(cproc_t cp, char **arg)
|
||||
{
|
||||
char *off_text = get_arg(arg);
|
||||
char *len_text = get_arg(arg);
|
||||
|
@ -393,7 +393,7 @@ static int hexout_feed(struct hexout_data *hexout,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_hexout(cproc_t cp, char **arg)
|
||||
int cmd_hexout(cproc_t cp, char **arg)
|
||||
{
|
||||
char *off_text = get_arg(arg);
|
||||
char *len_text = get_arg(arg);
|
||||
|
@ -523,7 +523,7 @@ static int prog_feed(void *user_data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_prog(cproc_t cp, char **arg)
|
||||
int cmd_prog(cproc_t cp, char **arg)
|
||||
{
|
||||
FILE *in;
|
||||
struct prog_data prog;
|
||||
|
@ -568,7 +568,7 @@ static int cmd_prog(cproc_t cp, char **arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_setbreak(cproc_t cp, char **arg)
|
||||
int cmd_setbreak(cproc_t cp, char **arg)
|
||||
{
|
||||
char *addr_text = get_arg(arg);
|
||||
char *index_text = get_arg(arg);
|
||||
|
@ -606,7 +606,7 @@ static int cmd_setbreak(cproc_t cp, char **arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_delbreak(cproc_t cp, char **arg)
|
||||
int cmd_delbreak(cproc_t cp, char **arg)
|
||||
{
|
||||
char *index_text = get_arg(arg);
|
||||
int ret = 0;
|
||||
|
@ -633,7 +633,7 @@ static int cmd_delbreak(cproc_t cp, char **arg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int cmd_break(cproc_t cp, char **arg)
|
||||
int cmd_break(cproc_t cp, char **arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -660,115 +660,3 @@ static int cmd_break(cproc_t cp, char **arg)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct cproc_command commands[] = {
|
||||
{
|
||||
.name = "setbreak",
|
||||
.func = cmd_setbreak,
|
||||
.help =
|
||||
"setbreak <addr> [index]\n"
|
||||
" Set a breakpoint. If no index is specified, the first available\n"
|
||||
" slot will be used.\n"
|
||||
},
|
||||
{
|
||||
.name = "delbreak",
|
||||
.func = cmd_delbreak,
|
||||
.help =
|
||||
"delbreak [index]\n"
|
||||
" Delete a breakpoint. If no index is specified, then all active\n"
|
||||
" breakpoints are cleared.\n"
|
||||
},
|
||||
{
|
||||
.name = "break",
|
||||
.func = cmd_break,
|
||||
.help =
|
||||
"break\n"
|
||||
" List active breakpoints.\n"
|
||||
},
|
||||
{
|
||||
.name = "regs",
|
||||
.func = cmd_regs,
|
||||
.help =
|
||||
"regs\n"
|
||||
" Read and display the current register contents.\n"
|
||||
},
|
||||
{
|
||||
.name = "prog",
|
||||
.func = cmd_prog,
|
||||
.help =
|
||||
"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"
|
||||
},
|
||||
{
|
||||
.name = "md",
|
||||
.func = cmd_md,
|
||||
.help =
|
||||
"md <address> [length]\n"
|
||||
" Read the specified number of bytes from memory at the given\n"
|
||||
" address, and display a hexdump.\n"
|
||||
},
|
||||
{
|
||||
.name = "mw",
|
||||
.func = cmd_mw,
|
||||
.help =
|
||||
"mw <address> bytes ...\n"
|
||||
" Write a sequence of bytes to a memory address. Byte values are\n"
|
||||
" two-digit hexadecimal numbers.\n"
|
||||
},
|
||||
{
|
||||
.name = "reset",
|
||||
.func = cmd_reset,
|
||||
.help =
|
||||
"reset\n"
|
||||
" Reset (and halt) the CPU.\n"
|
||||
},
|
||||
{
|
||||
.name = "erase",
|
||||
.func = cmd_erase,
|
||||
.help =
|
||||
"erase\n"
|
||||
" Erase the device under test.\n"
|
||||
},
|
||||
{
|
||||
.name = "step",
|
||||
.func = cmd_step,
|
||||
.help =
|
||||
"step [count]\n"
|
||||
" Single-step the CPU, and display the register state.\n"
|
||||
},
|
||||
{
|
||||
.name = "run",
|
||||
.func = cmd_run,
|
||||
.help =
|
||||
"run\n"
|
||||
" Run the CPU to until a breakpoint is reached or the command is\n"
|
||||
" interrupted.\n"
|
||||
},
|
||||
{
|
||||
.name = "set",
|
||||
.func = cmd_set,
|
||||
.help =
|
||||
"set <register> <value>\n"
|
||||
" Change the value of a CPU register.\n"
|
||||
},
|
||||
{
|
||||
.name = "dis",
|
||||
.func = cmd_dis,
|
||||
.help =
|
||||
"dis <address> [length]\n"
|
||||
" Disassemble a section of memory.\n"
|
||||
},
|
||||
{
|
||||
.name = "hexout",
|
||||
.func = cmd_hexout,
|
||||
.help =
|
||||
"hexout <address> <length> <filename.hex>\n"
|
||||
" Save a region of memory into a HEX file.\n"
|
||||
}
|
||||
};
|
||||
|
||||
int devcmd_register(cproc_t cp)
|
||||
{
|
||||
return cproc_register_commands(cp, commands, ARRAY_LEN(commands));
|
||||
}
|
||||
|
|
16
devcmd.h
16
devcmd.h
|
@ -21,7 +21,19 @@
|
|||
|
||||
#include "cproc.h"
|
||||
|
||||
/* Register device commands */
|
||||
int devcmd_register(cproc_t cp);
|
||||
int cmd_regs(cproc_t cp, char **arg);
|
||||
int cmd_md(cproc_t cp, char **arg);
|
||||
int cmd_mw(cproc_t cp, char **arg);
|
||||
int cmd_reset(cproc_t cp, char **arg);
|
||||
int cmd_erase(cproc_t cp, char **arg);
|
||||
int cmd_step(cproc_t cp, char **arg);
|
||||
int cmd_run(cproc_t cp, char **arg);
|
||||
int cmd_set(cproc_t cp, char **arg);
|
||||
int cmd_dis(cproc_t cp, char **arg);
|
||||
int cmd_hexout(cproc_t cp, char **arg);
|
||||
int cmd_prog(cproc_t cp, char **arg);
|
||||
int cmd_setbreak(cproc_t cp, char **arg);
|
||||
int cmd_delbreak(cproc_t cp, char **arg);
|
||||
int cmd_break(cproc_t cp, char **arg);
|
||||
|
||||
#endif
|
||||
|
|
15
gdb.c
15
gdb.c
|
@ -662,7 +662,7 @@ static int gdb_server(int port)
|
|||
return data.error ? -1 : 0;
|
||||
}
|
||||
|
||||
static int cmd_gdb(cproc_t cp, char **arg)
|
||||
int cmd_gdb(cproc_t cp, char **arg)
|
||||
{
|
||||
char *port_text = get_arg(arg);
|
||||
int port = 2000;
|
||||
|
@ -682,16 +682,3 @@ static int cmd_gdb(cproc_t cp, char **arg)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct cproc_command command_gdb = {
|
||||
.name = "gdb",
|
||||
.func = cmd_gdb,
|
||||
.help =
|
||||
"gdb [port]\n"
|
||||
" Run a GDB remote stub on the given TCP/IP port.\n"
|
||||
};
|
||||
|
||||
int gdb_register(cproc_t cp)
|
||||
{
|
||||
return cproc_register_commands(cp, &command_gdb, 1);
|
||||
}
|
||||
|
|
3
gdb.h
3
gdb.h
|
@ -21,7 +21,6 @@
|
|||
|
||||
#include "cproc.h"
|
||||
|
||||
/* Register the "gdb" command */
|
||||
int gdb_register(cproc_t cp);
|
||||
int cmd_gdb(cproc_t cp, char **arg);
|
||||
|
||||
#endif
|
||||
|
|
8
main.c
8
main.c
|
@ -437,14 +437,6 @@ cproc_t setup_cproc(struct cmdline_args *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (sym_register(cp) < 0 ||
|
||||
devcmd_register(cp) < 0 ||
|
||||
gdb_register(cp) < 0 ||
|
||||
rtools_register(cp) < 0) {
|
||||
cproc_destroy(cp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
|
|
44
rtools.c
44
rtools.c
|
@ -373,7 +373,7 @@ static int do_isearch(cproc_t cp, address_t addr, address_t len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_isearch(cproc_t cp, char **arg)
|
||||
int cmd_isearch(cproc_t cp, char **arg)
|
||||
{
|
||||
const static struct {
|
||||
const char *name;
|
||||
|
@ -900,7 +900,7 @@ static void cgraph_func_info(struct call_graph *graph, cproc_t cp,
|
|||
}
|
||||
}
|
||||
|
||||
static int cmd_cgraph(cproc_t cp, char **arg)
|
||||
int cmd_cgraph(cproc_t cp, char **arg)
|
||||
{
|
||||
char *offset_text, *len_text, *addr_text;;
|
||||
address_t offset, len, addr;
|
||||
|
@ -965,43 +965,3 @@ static int cmd_cgraph(cproc_t cp, char **arg)
|
|||
cgraph_destroy(&graph);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Setup and registration
|
||||
*/
|
||||
|
||||
static const struct cproc_command rtools_commands[] = {
|
||||
{
|
||||
.name = "isearch",
|
||||
.func = cmd_isearch,
|
||||
.help =
|
||||
"isearch <address> <length> [options ...]\n"
|
||||
" Search for an instruction matching certain search terms. These\n"
|
||||
" terms may be any of the following:\n"
|
||||
" opcode <opcode>\n"
|
||||
" byte|word|aword\n"
|
||||
" jump|single|double|noarg\n"
|
||||
" src <value>\n"
|
||||
" dst <value>\n"
|
||||
" srcreg <register>\n"
|
||||
" dstreg <register>\n"
|
||||
" srcmode R|I|S|&|@|+|#\n"
|
||||
" dstmode R|I|S|&|@|+|#\n"
|
||||
" For single-operand instructions, the operand is considered the\n"
|
||||
" destination operand.\n"
|
||||
},
|
||||
{
|
||||
.name = "cgraph",
|
||||
.func = cmd_cgraph,
|
||||
.help =
|
||||
"cgraph <address> <length> [function]\n"
|
||||
" Analyse the range given and produce a call graph. Displays a summary\n"
|
||||
" of all functions if no function address is given.\n"
|
||||
}
|
||||
};
|
||||
|
||||
int rtools_register(cproc_t cp)
|
||||
{
|
||||
return cproc_register_commands(cp, rtools_commands,
|
||||
ARRAY_LEN(rtools_commands));
|
||||
}
|
||||
|
|
4
rtools.h
4
rtools.h
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "cproc.h"
|
||||
|
||||
/* Register reverse-engineering tool commands. */
|
||||
int rtools_register(cproc_t cp);
|
||||
int cmd_isearch(cproc_t cp, char **arg);
|
||||
int cmd_cgraph(cproc_t cp, char **arg);
|
||||
|
||||
#endif
|
||||
|
|
40
sym.c
40
sym.c
|
@ -30,7 +30,7 @@
|
|||
#include "vector.h"
|
||||
#include "sym.h"
|
||||
|
||||
static int cmd_eval(cproc_t cp, char **arg)
|
||||
int cmd_eval(cproc_t cp, char **arg)
|
||||
{
|
||||
address_t addr;
|
||||
address_t offset;
|
||||
|
@ -288,7 +288,7 @@ static int cmd_sym_del(cproc_t cp, char **arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_sym(cproc_t cp, char **arg)
|
||||
int cmd_sym(cproc_t cp, char **arg)
|
||||
{
|
||||
char *subcmd = get_arg(arg);
|
||||
|
||||
|
@ -346,39 +346,3 @@ static int cmd_sym(cproc_t cp, char **arg)
|
|||
fprintf(stderr, "sym: unknown subcommand: %s\n", subcmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const struct cproc_command commands[] = {
|
||||
{
|
||||
.name = "=",
|
||||
.func = cmd_eval,
|
||||
.help =
|
||||
"= <expression>\n"
|
||||
" Evaluate an expression using the symbol table.\n"
|
||||
},
|
||||
{
|
||||
.name = "sym",
|
||||
.func = cmd_sym,
|
||||
.help =
|
||||
"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 import <filename>\n"
|
||||
" Load symbols from the given file.\n"
|
||||
"sym import+ <filename>\n"
|
||||
" Load additional symbols from the given file.\n"
|
||||
"sym export <filename>\n"
|
||||
" Save the current symbols to a BSD-style symbol file.\n"
|
||||
"sym find <regex>\n"
|
||||
" Search for symbols by regular expression.\n"
|
||||
"sym rename <regex> <string>\n"
|
||||
" Replace every occurance of a pattern in symbol names.\n"
|
||||
}
|
||||
};
|
||||
|
||||
int sym_register(cproc_t cp)
|
||||
{
|
||||
return cproc_register_commands(cp, commands, ARRAY_LEN(commands));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue