⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 symtab.c

📁 motorola自己开发的针对coldfire 5272的Dbug bootloader程序
💻 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 + -