[BACK]Return to symbol.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / pmdb

File: [local] / src / usr.bin / pmdb / Attic / symbol.c (download)

Revision 1.1, Fri Mar 15 16:30:32 2002 UTC (22 years, 3 months ago) by art
Branch: MAIN

Initial revision

/*	$PMDB: symbol.c,v 1.5 2002/03/07 14:27:08 art Exp $	*/
/*
 * Copyright (c) 2002 Artur Grabowski <art@openbsd.org>
 * All rights reserved. 
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met: 
 *
 * 1. Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer. 
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <err.h>

#include "pmdb.h"
#include "symbol.h"

/*
 * Initialize the executable and the symbol table.
 */
void
sym_init_exec(struct pstate *ps, const char *name)
{
	ps->ps_sops = NULL;
	ps->ps_sym_exe = NULL;
	TAILQ_INIT(&ps->ps_syms);

#ifdef PMDB_ELF
	if (sym_check_elf(name, ps))
#endif
#ifdef PMDB_AOUT
	if (sym_check_aout(name, ps))
#endif
		warnx("sym_init_exec: %s is not a supported file format", name);

	if (ps->ps_sops) {
		ps->ps_sym_exe = st_open(ps, name);
		if (ps->ps_sym_exe)
			ps->ps_sym_exe->st_flags |= ST_EXEC;
	}
}

/*
 * Destroy all symbol tables.
 */
void
sym_destroy(struct pstate *ps)
{
	struct sym_table *st;

	while ((st = TAILQ_FIRST(&ps->ps_syms)) != NULL) {
		TAILQ_REMOVE(&ps->ps_syms, st, st_list);
		(*ps->ps_sops->sop_close)(st);
	}
	ps->ps_sym_exe = NULL;
}

/*
 * We have reasons to believe that the symbol tables we have are not consistent
 * with the running binary. Update.
 */
void
sym_update(struct pstate *ps)
{
	(*ps->ps_sops->sop_update)(ps);
}

char *
sym_name_and_offset(struct pstate *ps, reg pc, char *nam, size_t len, reg *off)
{
	struct sym_table *st;
	int bestoffisset = 0;
	reg bestoff, noff;
	char *res;

	TAILQ_FOREACH(st, &ps->ps_syms, st_list) {
		res = (*ps->ps_sops->sop_name_and_off)(st, pc, &noff);
		if (res == NULL)
			continue;
		if (noff < bestoff || !bestoffisset) {
			bestoffisset = 1;
			bestoff = noff;
			strlcpy(nam, res, len);
		}
	}

	if (!bestoffisset || !strcmp(nam, "_end"))
		return (NULL);

	*off = bestoff;
	return (nam);
}

int
sym_lookup(struct pstate *ps, const char *name, reg *res)
{
	/*
	 * We let the sop do the table walking itself since it might have
	 * preferences about what symbols to pick (weak and stuff).
	 */
	return ((*ps->ps_sops->sop_lookup)(ps, name, res));
}

char *
sym_print(struct pstate *ps, reg pc, char *buf, size_t buflen)
{
	char namebuf[1024], *name;
	reg offs;

	name = sym_name_and_offset(ps, pc, namebuf, sizeof(namebuf), &offs);
	if (name == NULL) {
		snprintf(buf, buflen, "0x%lx", pc);
	} else {
		snprintf(buf, buflen, "%s+0x%lx(0x%lx)", name, offs, pc);
	}

	return (buf);
}

/*
 * Open a symbol table and install it in the list. Don't do anything if
 * it's already there.
 */
struct sym_table *
st_open(struct pstate *ps, const char *name)
{
	struct sym_table *st;

	TAILQ_FOREACH(st, &ps->ps_syms, st_list) {
		if (!strcmp(name, st->st_fname))
			return (st);
	}

	warnx("Loading symbols from %s", name);

	if ((st = (*ps->ps_sops->sop_open)(name)) != NULL) {
		TAILQ_INSERT_TAIL(&ps->ps_syms, st, st_list);
		strlcpy(st->st_fname, name, sizeof(st->st_fname));
	}

	return (st);
}