📄 symtab.c
字号:
/*
* File: symtab.c
* Purpose: Routines for managing a symbol table within dBUG.
*
* Notes:
*
* Author: Eric DeVolder
* Date:
*
* Modifications:
*
*/
#include "src/include/dbug.h"
#include "src/uif/uif.h"
/********************************************************************/
#define SYMTABSIZE UIF_MAX_SYMBOL
/*
* The symbol table is sorted on the 'value' in increasing order.
*/
/*
* Size of string for symbol names. NOTE that there are a couple
* printf's that have the value '32' embedded in the format string.
*/
#define SYMLEN (32)
typedef struct SYM
{
union
{
struct
{
int code; /* 0xFFFFFF00 == need stringtab entry */
int offset; /* temp offset into stringtab */
} sym;
char name[SYMLEN];
} pattern;
ADDRESS value;
struct SYM *next;
} SYM;
#define CODE_ALLOCATED (0x00FFFF00) /* zero for string term */
#define CODE_FREED (0x00000000)
#define CODE_STRTAB (0x00FFFE00) /* zero for string term */
static struct
{
int used;
SYM *inuse;
SYM *free;
SYM tab[SYMTABSIZE];
} symtab;
/********************************************************************/
void
symtab_init (void)
{
/*
* Initialize symbol table.
*/
int index;
for (index = 0; index < SYMTABSIZE; index++)
{
symtab.tab[index].pattern.sym.code = CODE_FREED;
symtab.tab[index].next = &symtab.tab[index + 1];
}
symtab.tab[SYMTABSIZE - 1].next = NULL;
symtab.used = 0;
symtab.inuse = NULL;
symtab.free = &symtab.tab[0];
}
/********************************************************************/
static SYM *
alloc_entry (void)
{
/*
* This routine picks off the first entry from the free list
*/
SYM *ent;
if ((ent = symtab.free) == NULL)
return NULL;
else
symtab.free = ent->next;
return ent;
}
/********************************************************************/
static void
free_entry (SYM *ent)
{
/*
* This routine puts the entry on the free list. Note that
* the calling routine must have already adjusted the list!!!
*/
ent->pattern.sym.code = CODE_FREED;
ent->next = symtab.free;
symtab.free = ent;
--(symtab.used);
}
/********************************************************************/
static SYM *
find_symbol (char *sym)
{
/*
* This routine locates 'sym' in the symbol table and returns
* a pointer to it. If it can not locate 'sym', then NULL is
* returned.
*/
SYM *ent;
ent = symtab.inuse;
while (ent != NULL)
{
if (strncmp(sym,ent->pattern.name,SYMLEN) == 0)
{
break;
}
ent = ent->next;
}
return ent;
}
/********************************************************************/
int
symtab_convert_string (char *sym, ADDRESS *symval)
{
/*
* This routine locates 'sym' in the symbol table and
* copies the symbol value into 'symval'.
*/
SYM *ent;
if ((ent = find_symbol(sym)) != NULL)
{
*symval = ent->value;
return TRUE;
}
else
{
return FALSE;
}
}
/********************************************************************/
int
symtab_convert_address (ADDRESS address, char *symstr)
{
/*
* This routine locates 'address' in the symbol table and
* copies the symbol name into 'symstr'. If the address
* is greater than an address in the symbol table, that
* symbol plus an offset is copied into the 'symstr'.
*
* NOTE: This routine works on the premise that when the
* symbol table is loaded into memory (usually from a file
* and thus the output of the linker) that the symbols are
* listed in numerical order by address. (Not alpha).
*
* NOTE: This routine is primarily called by the disassembler
* to resolve addresses into symbolics.
*/
SYM *ent;
if ((ent = symtab.inuse) == NULL)
{
sprintf(symstr, "%#08X", address);
return FALSE;
}
while (ent->next != NULL)
{
if (ent->value == address)
break;
ent = ent->next;
}
if (ent->value == address)
{
strncpy(symstr, ent->pattern.name, SYMLEN);
return TRUE;
}
else
{
sprintf(symstr, "%#08X", address);
return FALSE;
}
}
/********************************************************************/
int
symtab_convert_address2 (ADDRESS address, char *symstr)
{
/*
* This does the same as symtab_convert_address(), but will also
* indicate a displacement.
*/
ADDRESS disp;
SYM *ent;
if ((ent = symtab.inuse) == NULL)
{
sprintf(symstr, "%#08X", address);
return FALSE;
}
while (ent->next != NULL)
{
if (ent->value == address)
break;
/* See if next symbol value is greater */
if (ent->next->value > address)
break;
ent = ent->next;
}
if (ent->value == address)
{
strncpy(symstr, ent->pattern.name, SYMLEN);
return TRUE;
}
else
{
disp = address - ent->value;
if (disp < 1024)
{
sprintf(symstr, "%s+%#04X", ent->pattern.name, disp);
return TRUE;
}
else
sprintf(symstr, "%#08X", address);
}
return FALSE;
}
/********************************************************************/
static SYM *
add_engine (char *sym, ADDRESS symval)
{
/*
* This routine inserts a symbol into the linked list which is
* the symbol table.
*/
SYM *ent, *prev, *next;
/*
* Allocate and fill in the new symbol table entry.
*/
if ((ent = alloc_entry()) == NULL)
return NULL;
ent->value = symval;
strncpy(ent->pattern.name, sym, SYMLEN);
ent->pattern.name[SYMLEN-1] = '\0'; /* ensure string termination */
/*
* Find the correct place to insert the symbol.
*/
if ((prev = symtab.inuse) == NULL)
{
/* It is the first entry */
symtab.inuse = ent;
ent->next = NULL;
return ent;
}
if (symval < prev->value)
{
/* Insert at head of linked list */
ent->next = symtab.inuse;
symtab.inuse = ent;
return ent;
}
while (prev != NULL)
{
next = prev->next;
if (prev->value == symval)
{
ent->next = prev->next;
prev->next = ent;
return ent;
}
if (next == NULL)
{
/* Insert at end of linked list */
prev->next = ent;
ent->next = NULL;
return ent;
}
if ((symval > prev->value) && (symval < next->value))
{
/* Inbetween two entries. */
ent->next = prev->next;
prev->next = ent;
return ent;
}
prev = next;
}
return ent;
}
/********************************************************************/
void
symtab_add (char *sym, ADDRESS symval)
{
add_engine(sym, symval);
}
/********************************************************************/
void
symtab_add_incomplete (int offset, ADDRESS symval)
{
int inc = (int)CODE_STRTAB;
SYM *ent;
ent = add_engine((char *)&inc, symval);
if (ent != NULL)
{
ent->pattern.sym.code = CODE_STRTAB;
ent->pattern.sym.offset = offset;
}
}
/********************************************************************/
void
symtab_add_complete (char *sym, int offset)
{
SYM *ent;
ent = symtab.inuse;
while (ent != NULL)
{
if ((ent->pattern.sym.code == (int)CODE_STRTAB) &&
(ent->pattern.sym.offset == offset))
{
strncpy(ent->pattern.name, sym, SYMLEN);
ent->pattern.name[SYMLEN-1] = '\0';
break;
}
ent = ent->next;
}
}
/********************************************************************/
static void
remove_ent (SYM *ent)
{
SYM *prev;
if (ent == symtab.inuse)
{
symtab.inuse = ent->next;
free_entry(ent);
}
else
{
prev = symtab.inuse;
while (prev != NULL)
{
if (prev->next == ent)
{
prev->next = ent->next; /* link changed */
free_entry(ent);
break;
}
prev = prev->next;
}
}
}
/********************************************************************/
static void
display_ent (char *sym)
{
ADDRESS val;
char str[64];
int success, displayed = 0;
SYM *ent;
/*
* First check to see if we are to display just one 'sym' or
* all the symbols.
*/
if (sym == NULL)
{
/* Display all entries */
ent = symtab.inuse;
while (ent != NULL)
{
printf("%08X: %s\n", ent->value, ent->pattern.name);
ent = ent->next;
if (pause(&displayed))
return;
}
}
else
{
ent = find_symbol(sym);
if (ent == NULL)
{
/*
* Try to determine if 'sym' is an address
*/
val = (ADDRESS)get_value(sym, &success, BASE);
if (!success)
{
printf("Error: No such symbol: %s\n", sym);
}
else
{
if (symtab_convert_address2(val,str))
printf("%08X: %s\n", val, str);
else
printf("Error: No such symbol: %s\n", sym);
}
return;
}
if (ent->pattern.sym.code != (int)CODE_STRTAB)
{
printf("%08X: %s\n", ent->value, ent->pattern.name);
}
}
}
/********************************************************************/
void
uif_cmd_sym (int argc, char **argv)
{
/*
* This routine adds, removes, and clears symbol table
* entries.
*/
int i;
ADDRESS symval;
char *p;
SYM *sp;
/* parse through arguments */
i = 1;
while (i < argc)
{
if (argv[i][0] != '-')
{
/* The arg must be a symbol name */
display_ent(argv[i]);
}
else
{
/* must be an option of some sort */
switch (argv[i][1])
{
case 'a':
case 'A':
/* Add a symbol into the table */
if ((i+2) >= argc) /* not past end of args */
{
printf("Error: Invalid value\n");
return;
}
else
{
symval = (ADDRESS)strtoul(argv[i+2],&p,BASE);
if ((symval == 0) && (p == argv[i+1]))
{
printf(INVALUE, argv[i+1]);
}
if ((sp = find_symbol(argv[i+1])) == NULL)
{
symtab_add(argv[i+1], symval);
}
else
{
remove_ent(sp);
symtab_add(argv[i+1], symval);
}
i += 2;
}
break;
case 'c':
case 'C':
/* clear all symbol table entries */
symtab_init();
return;
break;
case 'l':
case 'L':
/* List all symbol table entries */
display_ent(NULL);
return;
break;
case 'r':
case 'R':
++i;
if ((sp = find_symbol(argv[i])) == NULL)
{
printf("Error: Invalid symbol: %s\n",argv[i]);
}
else
{
remove_ent(sp);
}
++i;
break;
case 's':
case 'S':
printf("%d of %d symbol table entries in use.\n",
symtab.used, SYMTABSIZE);
return;
break;
default:
printf("Error: Invalid option: %s\n", argv[i]);
return;
break;
}
}
i++;
}
}
/********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -