Implemented "sym rename".

This commit is contained in:
Daniel Beer 2010-03-31 20:40:46 +13:00
parent 6cc43e17c8
commit dab86a82f6
4 changed files with 261 additions and 128 deletions

12
btree.c
View File

@ -500,6 +500,18 @@ int btree_put(btree_t bt, const void *key, const void *data)
check_btree(bt);
/* Special case: cursor overwrite */
if (!key) {
if (bt->slot[0] < 0) {
fprintf(stderr, "btree: put at invalid cursor\n");
return -1;
}
memcpy(PAGE_DATA(bt->path[0], bt->slot[0]), data,
def->data_size);
return 1;
}
/* Find a path down the tree that leads to the page which should
* contain this datum (though the page might be too big to hold it).
*/

View File

@ -49,6 +49,8 @@ void btree_clear(btree_t bt);
/* Add or update a record in a B+Tree. Any existing data for the key will
* be overwritten.
*
* Specifying a NULL key causes the cursor value to be overwritten.
*
* Returns 1 if the key already existed, 0 if a new key was inserted,
* or -1 if an error occurs (failed memory allocation).
*/

View File

@ -214,6 +214,11 @@ by MSPDebug, and all symbols are saved as type \fBt\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.
.IP "\fBsym rename\fR \fIregex\fR \fIstring\fR"
Rename symbols by searching for those matching the given regular
expression and substituting the given string for the matched portion. The
symbols renamed are displayed, as well as a total count of all symbols
renamed.
.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

370
stab.c
View File

@ -169,86 +169,6 @@ int stab_set(const char *name, int value)
return 0;
}
static int stab_get(const char *name, u_int16_t *value)
{
struct sym_key skey;
sym_key_init(&skey, name);
if (btree_get(sym_table, &skey, value))
return -1;
return 0;
}
static int stab_del(const char *name)
{
struct sym_key skey;
u_int16_t value;
struct addr_key akey;
sym_key_init(&skey, name);
if (btree_get(sym_table, &skey, &value)) {
fprintf(stderr, "stab: can't delete nonexistent symbol: %s\n",
name);
return -1;
}
addr_key_init(&akey, value, name);
btree_delete(sym_table, &skey);
btree_delete(addr_table, &akey);
return 0;
}
static int stab_enum(stab_callback_t cb)
{
struct sym_key skey;
u_int16_t value;
int ret;
int count = 0;
ret = btree_select(sym_table, NULL, BTREE_FIRST, &skey, &value);
while (!ret) {
if (cb && cb(skey.name, value) < 0)
return -1;
count++;
ret = btree_select(sym_table, NULL, BTREE_NEXT, &skey, &value);
}
return count;
}
static int stab_re_search(const char *regex, stab_callback_t cb)
{
struct sym_key skey;
u_int16_t value;
int ret;
int count = 0;
regex_t preg;
if (regcomp(&preg, regex, REG_EXTENDED | REG_NOSUB)) {
fprintf(stderr, "stab: failed to compile: %s\n", regex);
return -1;
}
ret = btree_select(sym_table, NULL, BTREE_FIRST, &skey, &value);
while (!ret) {
if (!regexec(&preg, skey.name, 0, NULL, 0)) {
if (cb && cb(skey.name, value) < 0) {
regfree(&preg);
return -1;
}
count++;
}
ret = btree_select(sym_table, NULL, BTREE_NEXT, &skey, &value);
}
regfree(&preg);
return count;
}
int stab_nearest(u_int16_t addr, char *ret_name, int max_len,
u_int16_t *ret_offset)
{
@ -304,22 +224,12 @@ static int cmd_sym_load_add(int clear, char **arg)
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);
int ret;
struct addr_key akey;
FILE *savemap_out;
if (!fname) {
fprintf(stderr, "sym: filename required to save map\n");
@ -333,8 +243,13 @@ static int cmd_sym_savemap(char **arg)
return -1;
}
if (stab_enum(savemap_write) < 0)
return -1;
ret = btree_select(addr_table, NULL, BTREE_FIRST,
&akey, NULL);
while (!ret) {
fprintf(savemap_out, "0x%04x: %s\n", akey.addr, akey.name);
ret = btree_select(addr_table, NULL, BTREE_NEXT,
&akey, NULL);
}
if (fclose(savemap_out) < 0) {
fprintf(stderr, "sym: error closing %s: %s\n", fname,
@ -346,9 +261,226 @@ static int cmd_sym_savemap(char **arg)
return 0;
}
static int printsym(const char *name, u_int16_t value)
static int cmd_sym_find(char **arg)
{
printf("0x%04x: %s\n", value, name);
char *expr = get_arg(arg);
int ret;
struct sym_key skey;
u_int16_t value;
regex_t preg;
if (!expr) {
struct addr_key akey;
ret = btree_select(addr_table, NULL, BTREE_FIRST,
&akey, NULL);
while (!ret) {
printf("0x%04x: %s\n", akey.addr, akey.name);
ret = btree_select(addr_table, NULL, BTREE_NEXT,
&akey, NULL);
}
return 0;
}
if (regcomp(&preg, expr, REG_EXTENDED | REG_NOSUB)) {
fprintf(stderr, "stab: failed to compile: %s\n", expr);
return -1;
}
ret = btree_select(sym_table, NULL, BTREE_FIRST, &skey, &value);
while (!ret) {
if (!regexec(&preg, skey.name, 0, NULL, 0))
printf("0x%04x: %s\n", value, skey.name);
ret = btree_select(sym_table, NULL, BTREE_NEXT, &skey, &value);
}
regfree(&preg);
return 0;
}
struct rename_record {
char old_name[64];
int start, end;
};
struct rename_record *renames;
static int renames_cap;
static int renames_len;
static void renames_free(void)
{
if (!renames)
return;
free(renames);
renames = NULL;
renames_cap = 0;
renames_len = 0;
}
static int renames_push(const char *old_name,
int start, int end)
{
struct rename_record *r;
if (renames_len + 1 > renames_cap) {
int new_cap = renames_cap * 2;
struct rename_record *new_array;
if (!new_cap)
new_cap = 64;
new_array = realloc(renames, new_cap * sizeof(renames[0]));
if (!new_array) {
perror("sym: can't allocate memory for renaming");
return -1;
}
renames = new_array;
renames_cap = new_cap;
}
r = &renames[renames_len++];
strncpy(r->old_name, old_name, sizeof(r->old_name));
r->old_name[sizeof(r->old_name) - 1] = 0;
r->start = start;
r->end = end;
return 0;
}
static int renames_do(const char *replace)
{
int i;
int count = 0;
for (i = 0; i < renames_len; i++) {
struct rename_record *r = &renames[i];
char new_name[128];
int len = r->start;
struct sym_key skey;
struct addr_key akey;
u_int16_t addr;
u_int16_t new_addr;
if (len + 1 > sizeof(new_name))
len = sizeof(new_name) - 1;
memcpy(new_name, r->old_name, len);
snprintf(new_name + len,
sizeof(new_name) - len,
"%s%s", replace, r->old_name + r->end);
printf("%s -> %s\n", r->old_name, new_name);
/* Step 1: delete old symbol, record address */
sym_key_init(&skey, r->old_name);
if (!btree_get(sym_table, &skey, &new_addr)) {
addr_key_init(&akey, new_addr, r->old_name);
if (btree_delete(addr_table, &akey))
fprintf(stderr, "sym: warning: "
"no reverse symbol: %s\n",
r->old_name);
} else {
fprintf(stderr, "sym: warning: "
"no forward symbol: %s\n",
r->old_name);
}
btree_delete(sym_table, &skey);
/* Step 2: overwrite new name */
sym_key_init(&skey, new_name);
if (!btree_get(sym_table, &skey, &addr)) {
addr_key_init(&akey, addr, new_name);
btree_delete(addr_table, &akey);
}
if (btree_put(sym_table, &skey, &new_addr) < 0)
return -1;
addr_key_init(&akey, new_addr, new_name);
if (btree_put(addr_table, &akey, NULL) < 0)
return -1;
count++;
}
if (count)
modify_set(MODIFY_SYMS);
printf("%d symbols renamed\n", count);
return 0;
}
static int cmd_sym_rename(char **arg)
{
const char *expr = get_arg(arg);
const char *replace = get_arg(arg);
regex_t preg;
struct addr_key akey;
int ret;
if (!(expr && replace)) {
fprintf(stderr, "sym: expected pattern and replacement\n");
return -1;
}
if (regcomp(&preg, expr, REG_EXTENDED)) {
fprintf(stderr, "sym: failed to compile: %s\n", expr);
return -1;
}
ret = btree_select(addr_table, NULL, BTREE_FIRST, &akey, NULL);
while (!ret) {
regmatch_t pmatch;
if (!regexec(&preg, akey.name, 1, &pmatch, 0) &&
pmatch.rm_so >= 0 && pmatch.rm_eo > pmatch.rm_so &&
renames_push(akey.name, pmatch.rm_so,
pmatch.rm_eo) < 0)
goto fail;
ret = btree_select(addr_table, NULL, BTREE_NEXT,
&akey, NULL);
}
regfree(&preg);
ret = renames_do(replace);
renames_free();
return ret;
fail:
regfree(&preg);
renames_free();
return -1;
}
static int cmd_sym_del(char **arg)
{
char *name = get_arg(arg);
struct sym_key skey;
u_int16_t value;
struct addr_key akey;
if (!name) {
fprintf(stderr, "sym: need a name to delete "
"symbol table entries\n");
return -1;
}
sym_key_init(&skey, name);
if (btree_get(sym_table, &skey, &value)) {
fprintf(stderr, "sym: can't delete nonexistent symbol: %s\n",
name);
return -1;
}
addr_key_init(&akey, value, name);
btree_delete(sym_table, &skey);
btree_delete(addr_table, &akey);
modify_set(MODIFY_SYMS);
return 0;
}
@ -394,40 +526,18 @@ static int cmd_sym(char **arg)
return 0;
}
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;
}
if (stab_del(name) < 0)
return -1;
modify_set(MODIFY_SYMS);
return 0;
}
if (!strcasecmp(subcmd, "del"))
return cmd_sym_del(arg);
if (!strcasecmp(subcmd, "import"))
return cmd_sym_load_add(1, arg);
if (!strcasecmp(subcmd, "import+"))
return cmd_sym_load_add(0, arg);
if (!strcasecmp(subcmd, "export"))
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;
}
if (!strcasecmp(subcmd, "rename"))
return cmd_sym_rename(arg);
if (!strcasecmp(subcmd, "find"))
return cmd_sym_find(arg);
fprintf(stderr, "sym: unknown subcommand: %s\n", subcmd);
return -1;
@ -451,16 +561,20 @@ static struct command command_sym = {
" 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"
};
static int lookup_token(const char *name, int *value)
{
u_int16_t val;
struct sym_key skey;
u_int16_t addr;
if (stab_get(name, &val) < 0)
sym_key_init(&skey, name);
if (btree_get(sym_table, &skey, &addr))
return -1;
*value = val;
*value = addr;
return 0;
}