Home | History | Annotate | Line # | Download | only in ddb
db_sym.c revision 1.26
      1 /*	$NetBSD: db_sym.c,v 1.26 2001/06/13 06:01:45 simonb Exp $	*/
      2 
      3 /*
      4  * Mach Operating System
      5  * Copyright (c) 1991,1990 Carnegie Mellon University
      6  * All Rights Reserved.
      7  *
      8  * Permission to use, copy, modify and distribute this software and its
      9  * documentation is hereby granted, provided that both the copyright
     10  * notice and this permission notice appear in all copies of the
     11  * software, derivative works or modified versions, and any portions
     12  * thereof, and that both notices appear in supporting documentation.
     13  *
     14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
     16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     17  *
     18  * Carnegie Mellon requests users of this software to return to
     19  *
     20  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     21  *  School of Computer Science
     22  *  Carnegie Mellon University
     23  *  Pittsburgh PA 15213-3890
     24  *
     25  * any improvements or extensions that they make and grant Carnegie the
     26  * rights to redistribute these changes.
     27  */
     28 
     29 #include "opt_ddbparam.h"
     30 
     31 #include <sys/param.h>
     32 #include <sys/proc.h>
     33 #include <sys/systm.h>
     34 
     35 #include <machine/db_machdep.h>
     36 
     37 #include <ddb/db_lex.h>
     38 #include <ddb/db_sym.h>
     39 #include <ddb/db_output.h>
     40 #include <ddb/db_extern.h>
     41 #include <ddb/db_command.h>
     42 
     43 /*
     44  * Multiple symbol tables
     45  */
     46 #ifndef MAXLKMS
     47 #define MAXLKMS 20
     48 #endif
     49 
     50 #ifndef MAXNOSYMTABS
     51 #define	MAXNOSYMTABS	MAXLKMS+1	/* Room for kernel + LKM's */
     52 #endif
     53 
     54 db_symtab_t	db_symtabs[MAXNOSYMTABS] = {{0,},};
     55 
     56 db_symtab_t	*db_last_symtab;
     57 
     58 #ifdef SYMTAB_SPACE
     59 #define		SYMTAB_FILLER	"|This is the symbol table!"
     60 
     61 char		db_symtab[SYMTAB_SPACE] = SYMTAB_FILLER;
     62 int		db_symtabsize = SYMTAB_SPACE;
     63 #endif
     64 
     65 static char *db_qualify __P((db_sym_t, const char *));
     66 static db_forall_func_t db_sift;
     67 
     68 /*
     69  * Put the most picky symbol table formats at the top!
     70  */
     71 const db_symformat_t * const db_symformats[] = {
     72 #ifdef DB_ELF_SYMBOLS
     73 	&db_symformat_elf,
     74 #endif
     75 #ifdef DB_AOUT_SYMBOLS
     76 	&db_symformat_aout,
     77 #endif
     78 	NULL,
     79 };
     80 
     81 const db_symformat_t *db_symformat;
     82 
     83 boolean_t	X_db_sym_init __P((int, void *, void *, const char *));
     84 db_sym_t	X_db_lookup __P((db_symtab_t *, char *));
     85 db_sym_t	X_db_search_symbol __P((db_symtab_t *, db_addr_t,
     86 		    db_strategy_t, db_expr_t *));
     87 void		X_db_symbol_values __P((db_symtab_t *, db_sym_t, char **,
     88 		    db_expr_t *));
     89 boolean_t	X_db_line_at_pc __P((db_symtab_t *, db_sym_t, char **,
     90 		    int *, db_expr_t));
     91 int		X_db_sym_numargs __P((db_symtab_t *, db_sym_t, int *,
     92 		    char **));
     93 void		X_db_forall __P((db_symtab_t *,
     94 		    db_forall_func_t db_forall_func, void *));
     95 
     96 /*
     97  * Initialize the kernel debugger by initializing the master symbol
     98  * table.  Note that if initializing the master symbol table fails,
     99  * no other symbol tables can be loaded.
    100  */
    101 void
    102 ddb_init(symsize, vss, vse)
    103 	int symsize;
    104 	void *vss, *vse;
    105 {
    106 	const db_symformat_t * const *symf;
    107 	const char *name = "netbsd";
    108 
    109 	if (symsize <= 0) {
    110 #ifdef SYMTAB_SPACE
    111 		if (strncmp(db_symtab, SYMTAB_FILLER, sizeof(SYMTAB_FILLER))) {
    112 			symsize = db_symtabsize;
    113 			vss = db_symtab;
    114 			vse = db_symtab + db_symtabsize;
    115 		} else {
    116 #endif
    117 			printf(" [ no symbols available ]\n");
    118 			return;
    119 #ifdef SYMTAB_SPACE
    120 		}
    121 #endif
    122 	}
    123 
    124 	/*
    125 	 * Do this check now for the master symbol table to avoid printing
    126 	 * the message N times.
    127 	 */
    128 	if (ALIGNED_POINTER(vss, long) == 0) {
    129 		printf("[ %s symbol table has bad start address %p ]\n",
    130 		    name, vss);
    131 		return;
    132 	}
    133 
    134 	for (symf = db_symformats; *symf != NULL; symf++) {
    135 		db_symformat = *symf;
    136 		if (X_db_sym_init(symsize, vss, vse, name) == TRUE)
    137 			return;
    138 	}
    139 
    140 	db_symformat = NULL;
    141 	printf("[ no symbol table formats found ]\n");
    142 
    143 	/* XXX: try SYMTAB_SPACE if we get this far? */
    144 }
    145 
    146 /*
    147  * Add symbol table, with given name, to list of symbol tables.
    148  */
    149 int
    150 db_add_symbol_table(start, end, name, ref)
    151 	char *start;
    152 	char *end;
    153 	const char *name;
    154 	char *ref;
    155 {
    156 	int slot;
    157 
    158 	for (slot = 0; slot < MAXNOSYMTABS; slot++) {
    159 		if (db_symtabs[slot].name == NULL)
    160 			break;
    161 	}
    162 	if (slot >= MAXNOSYMTABS) {
    163 		db_printf("No slots left for %s symbol table", name);
    164 		return(-1);
    165 	}
    166 
    167 	db_symtabs[slot].start = start;
    168 	db_symtabs[slot].end = end;
    169 	db_symtabs[slot].name = name;
    170 	db_symtabs[slot].private = ref;
    171 
    172 	return(slot);
    173 }
    174 
    175 /*
    176  * Delete a symbol table. Caller is responsible for freeing storage.
    177  */
    178 void
    179 db_del_symbol_table(name)
    180 	char *name;
    181 {
    182 	int slot;
    183 
    184 	for (slot = 0; slot < MAXNOSYMTABS; slot++) {
    185 		if (db_symtabs[slot].name &&
    186 		    ! strcmp(db_symtabs[slot].name, name))
    187 			break;
    188 	}
    189 	if (slot >= MAXNOSYMTABS) {
    190 		db_printf("Unable to find symbol table slot for %s.", name);
    191 		return;
    192 	}
    193 
    194 	db_symtabs[slot].start = 0;
    195 	db_symtabs[slot].end = 0;
    196 	db_symtabs[slot].name = 0;
    197 	db_symtabs[slot].private = 0;
    198 }
    199 
    200 /*
    201  *  db_qualify("vm_map", "netbsd") returns "netbsd:vm_map".
    202  *
    203  *  Note: return value points to static data whose content is
    204  *  overwritten by each call... but in practice this seems okay.
    205  */
    206 static char *
    207 db_qualify(sym, symtabname)
    208 	db_sym_t	sym;
    209 	const char	*symtabname;
    210 {
    211 	char		*symname;
    212 	static char     tmp[256];
    213 	char	*s;
    214 
    215 	db_symbol_values(sym, &symname, 0);
    216 	s = tmp;
    217 	while ((*s++ = *symtabname++) != '\0')
    218 		;
    219 	s[-1] = ':';
    220 	while ((*s++ = *symname++) != '\0')
    221 		;
    222 	return tmp;
    223 }
    224 
    225 
    226 boolean_t
    227 db_eqname(src, dst, c)
    228 	char *src;
    229 	char *dst;
    230 	int c;
    231 {
    232 	if (!strcmp(src, dst))
    233 	    return (TRUE);
    234 	if (src[0] == c)
    235 	    return (!strcmp(src+1,dst));
    236 	return (FALSE);
    237 }
    238 
    239 boolean_t
    240 db_value_of_name(name, valuep)
    241 	char		*name;
    242 	db_expr_t	*valuep;
    243 {
    244 	db_sym_t	sym;
    245 
    246 	sym = db_lookup(name);
    247 	if (sym == DB_SYM_NULL)
    248 	    return (FALSE);
    249 	db_symbol_values(sym, &name, valuep);
    250 	return (TRUE);
    251 }
    252 
    253 
    254 /*
    255  * Lookup a symbol.
    256  * If the symbol has a qualifier (e.g., ux:vm_map),
    257  * then only the specified symbol table will be searched;
    258  * otherwise, all symbol tables will be searched.
    259  */
    260 db_sym_t
    261 db_lookup(symstr)
    262 	char *symstr;
    263 {
    264 	db_sym_t sp;
    265 	int i;
    266 	int symtab_start = 0;
    267 	int symtab_end = MAXNOSYMTABS;
    268 	char *cp;
    269 
    270 	/*
    271 	 * Look for, remove, and remember any symbol table specifier.
    272 	 */
    273 	for (cp = symstr; *cp; cp++) {
    274 		if (*cp == ':') {
    275 			*cp = '\0';
    276 			for (i = 0; i < MAXNOSYMTABS; i++) {
    277 				if (db_symtabs[i].name &&
    278 				    ! strcmp(symstr, db_symtabs[i].name)) {
    279 					symtab_start = i;
    280 					symtab_end = i + 1;
    281 					break;
    282 				}
    283 			}
    284 			*cp = ':';
    285 			if (i == MAXNOSYMTABS) {
    286 				db_error("invalid symbol table name");
    287 				/*NOTREACHED*/
    288 			}
    289 			symstr = cp+1;
    290 		}
    291 	}
    292 
    293 	/*
    294 	 * Look in the specified set of symbol tables.
    295 	 * Return on first match.
    296 	 */
    297 	for (i = symtab_start; i < symtab_end; i++) {
    298 		if (db_symtabs[i].name &&
    299 		    (sp = X_db_lookup(&db_symtabs[i], symstr))) {
    300 			db_last_symtab = &db_symtabs[i];
    301 			return sp;
    302 		}
    303 	}
    304 	return 0;
    305 }
    306 
    307 /* Private structure for passing args to db_sift() from db_sifting(). */
    308 struct db_sift_args {
    309 	char	*symstr;
    310 	int	mode;
    311 };
    312 
    313 /*
    314  * Does the work of db_sifting(), called once for each
    315  * symbol via X_db_forall(), prints out symbols matching
    316  * criteria.
    317  */
    318 static void
    319 db_sift(stab, sym, name, suffix, prefix, arg)
    320 	db_symtab_t	*stab;
    321 	db_sym_t	sym;
    322 	char		*name;
    323 	char		*suffix;
    324 	int		prefix;
    325 	void		*arg;
    326 {
    327 	char c, sc;
    328 	char *find, *p;
    329 	size_t len;
    330 	struct db_sift_args *dsa;
    331 
    332 	dsa = (struct db_sift_args*)arg;
    333 
    334 	find = dsa->symstr;	/* String we're looking for. */
    335 	p = name;		/* String we're searching within. */
    336 
    337 	/* Matching algorithm cribbed from strstr(), which is not
    338 	   in the kernel. */
    339 	if ((c = *find++) != 0) {
    340 		len = strlen(find);
    341 		do {
    342 			do {
    343 				if ((sc = *p++) == 0)
    344 					return;
    345 			} while (sc != c);
    346 		} while (strncmp(p, find, len) != 0);
    347 	}
    348 	if (dsa->mode=='F')	/* ala ls -F */
    349 		db_printf("%s%s ", name, suffix);
    350 	else
    351 		db_printf("%s ", name);
    352 }
    353 
    354 /*
    355  * "Sift" for a partial symbol.
    356  * Named for the Sun OpenPROM command ("sifting").
    357  * If the symbol has a qualifier (e.g., ux:vm_map),
    358  * then only the specified symbol table will be searched;
    359  * otherwise, all symbol tables will be searched..
    360  *
    361  * "mode" is how-to-display, set from modifiers.
    362  */
    363 void
    364 db_sifting(symstr, mode)
    365 	char	*symstr;
    366 	int	mode;
    367 {
    368 	char *cp;
    369 	int i;
    370 	int symtab_start = 0;
    371 	int symtab_end = MAXNOSYMTABS;
    372 	struct db_sift_args dsa;
    373 
    374 	/*
    375 	 * Look for, remove, and remember any symbol table specifier.
    376 	 */
    377 	for (cp = symstr; *cp; cp++) {
    378 		if (*cp == ':') {
    379 			*cp = '\0';
    380 			for (i = 0; i < MAXNOSYMTABS; i++) {
    381 				if (db_symtabs[i].name &&
    382 				    ! strcmp(symstr, db_symtabs[i].name)) {
    383 					symtab_start = i;
    384 					symtab_end = i + 1;
    385 					break;
    386 				}
    387 			}
    388 			*cp = ':';
    389 			if (i == MAXNOSYMTABS) {
    390 				db_error("invalid symbol table name");
    391 				/*NOTREACHED*/
    392 			}
    393 			symstr = cp+1;
    394 		}
    395 	}
    396 
    397 	/* Pass args to db_sift(). */
    398 	dsa.symstr = symstr;
    399 	dsa.mode = mode;
    400 
    401 	/*
    402 	 * Look in the specified set of symbol tables.
    403 	 */
    404 	for (i = symtab_start; i < symtab_end; i++)
    405 		if (db_symtabs[i].name) {
    406 			db_printf("Sifting table %s:\n", db_symtabs[i].name);
    407 			X_db_forall(&db_symtabs[i], db_sift, &dsa);
    408 		}
    409 
    410 	return;
    411 }
    412 
    413 
    414 /*
    415  * Does this symbol name appear in more than one symbol table?
    416  * Used by db_symbol_values to decide whether to qualify a symbol.
    417  */
    418 boolean_t db_qualify_ambiguous_names = FALSE;
    419 
    420 boolean_t
    421 db_symbol_is_ambiguous(sym)
    422 	db_sym_t	sym;
    423 {
    424 	char		*sym_name;
    425 	int	i;
    426 	boolean_t	found_once = FALSE;
    427 
    428 	if (!db_qualify_ambiguous_names)
    429 		return FALSE;
    430 
    431 	db_symbol_values(sym, &sym_name, 0);
    432 	for (i = 0; i < MAXNOSYMTABS; i++) {
    433 		if (db_symtabs[i].name &&
    434 		    X_db_lookup(&db_symtabs[i], sym_name)) {
    435 			if (found_once)
    436 				return TRUE;
    437 			found_once = TRUE;
    438 		}
    439 	}
    440 	return FALSE;
    441 }
    442 
    443 /*
    444  * Find the closest symbol to val, and return its name
    445  * and the difference between val and the symbol found.
    446  */
    447 db_sym_t
    448 db_search_symbol( val, strategy, offp)
    449 	db_addr_t		val;
    450 	db_strategy_t		strategy;
    451 	db_expr_t		*offp;
    452 {
    453 	unsigned int	diff;
    454 	db_expr_t	newdiff;
    455 	int		i;
    456 	db_sym_t	ret = DB_SYM_NULL, sym;
    457 
    458 	newdiff = diff = ~0;
    459 	db_last_symtab = 0;
    460 	for (i = 0; i < MAXNOSYMTABS; i++) {
    461 	    if (!db_symtabs[i].name)
    462 	        continue;
    463 	    sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
    464 	    if (newdiff < diff) {
    465 		db_last_symtab = &db_symtabs[i];
    466 		diff = newdiff;
    467 		ret = sym;
    468 	    }
    469 	}
    470 	*offp = diff;
    471 	return ret;
    472 }
    473 
    474 /*
    475  * Return name and value of a symbol
    476  */
    477 void
    478 db_symbol_values(sym, namep, valuep)
    479 	db_sym_t	sym;
    480 	char		**namep;
    481 	db_expr_t	*valuep;
    482 {
    483 	db_expr_t	value;
    484 
    485 	if (sym == DB_SYM_NULL) {
    486 		*namep = 0;
    487 		return;
    488 	}
    489 
    490 	X_db_symbol_values(db_last_symtab, sym, namep, &value);
    491 
    492 	if (db_symbol_is_ambiguous(sym))
    493 		*namep = db_qualify(sym, db_last_symtab->name);
    494 	if (valuep)
    495 		*valuep = value;
    496 }
    497 
    498 
    499 /*
    500  * Print a the closest symbol to value
    501  *
    502  * After matching the symbol according to the given strategy
    503  * we print it in the name+offset format, provided the symbol's
    504  * value is close enough (eg smaller than db_maxoff).
    505  * We also attempt to print [filename:linenum] when applicable
    506  * (eg for procedure names).
    507  *
    508  * If we could not find a reasonable name+offset representation,
    509  * then we just print the value in hex.  Small values might get
    510  * bogus symbol associations, e.g. 3 might get some absolute
    511  * value like _INCLUDE_VERSION or something, therefore we do
    512  * not accept symbols whose value is zero (and use plain hex).
    513  * Also, avoid printing as "end+0x????" which is useless.
    514  * The variable db_lastsym is used instead of "end" in case we
    515  * add support for symbols in loadable driver modules.
    516  */
    517 extern char end[];
    518 unsigned long	db_lastsym = (unsigned long)end;
    519 unsigned int	db_maxoff = 0x10000000;
    520 
    521 
    522 void
    523 db_printsym(off, strategy, pr)
    524 	db_expr_t	off;
    525 	db_strategy_t	strategy;
    526 	void (*pr) __P((const char *, ...));
    527 {
    528 	db_expr_t	d;
    529 	char 		*filename;
    530 	char		*name;
    531 	db_expr_t	value;
    532 	int 		linenum;
    533 	db_sym_t	cursym;
    534 
    535 	if (off <= db_lastsym) {
    536 		cursym = db_search_symbol(off, strategy, &d);
    537 		db_symbol_values(cursym, &name, &value);
    538 		if (name && (d < db_maxoff) && value) {
    539 			(*pr)("%s", name);
    540 			if (d) {
    541 				char tbuf[24];
    542 
    543 				db_format_radix(tbuf, 24, d, TRUE);
    544 				(*pr)("+%s", tbuf);
    545 			}
    546 			if (strategy == DB_STGY_PROC) {
    547 				if (db_line_at_pc(cursym, &filename, &linenum, off))
    548 					(*pr)(" [%s:%d]", filename, linenum);
    549 			}
    550 			return;
    551 		}
    552 	}
    553 	(*pr)(db_num_to_str(off));
    554 	return;
    555 }
    556 
    557 
    558 boolean_t
    559 db_line_at_pc( sym, filename, linenum, pc)
    560 	db_sym_t	sym;
    561 	char		**filename;
    562 	int		*linenum;
    563 	db_expr_t	pc;
    564 {
    565 	return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
    566 }
    567 
    568 int
    569 db_sym_numargs(sym, nargp, argnames)
    570 	db_sym_t	sym;
    571 	int		*nargp;
    572 	char		**argnames;
    573 {
    574 	return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
    575 }
    576 
    577 boolean_t
    578 X_db_sym_init(symsize, vss, vse, name)
    579 	int symsize;
    580 	void *vss, *vse;
    581 	const char *name;
    582 {
    583 
    584 	if (db_symformat != NULL)
    585 		return ((*db_symformat->sym_init)(symsize, vss, vse, name));
    586 	return (FALSE);
    587 }
    588 
    589 db_sym_t
    590 X_db_lookup(stab, symstr)
    591 	db_symtab_t *stab;
    592 	char *symstr;
    593 {
    594 
    595 	if (db_symformat != NULL)
    596 		return ((*db_symformat->sym_lookup)(stab, symstr));
    597 	return ((db_sym_t)0);
    598 }
    599 
    600 db_sym_t
    601 X_db_search_symbol(stab, off, strategy, diffp)
    602 	db_symtab_t *stab;
    603 	db_addr_t off;
    604 	db_strategy_t strategy;
    605 	db_expr_t *diffp;
    606 {
    607 
    608 	if (db_symformat != NULL)
    609 		return ((*db_symformat->sym_search)(stab, off, strategy,
    610 		    diffp));
    611 	return ((db_sym_t)0);
    612 }
    613 
    614 void
    615 X_db_symbol_values(stab, sym, namep, valuep)
    616 	db_symtab_t *stab;
    617 	db_sym_t sym;
    618 	char **namep;
    619 	db_expr_t *valuep;
    620 {
    621 
    622 	if (db_symformat != NULL)
    623 		(*db_symformat->sym_value)(stab, sym, namep, valuep);
    624 }
    625 
    626 boolean_t
    627 X_db_line_at_pc(stab, cursym, filename, linenum, off)
    628 	db_symtab_t *stab;
    629 	db_sym_t cursym;
    630 	char **filename;
    631 	int *linenum;
    632 	db_expr_t off;
    633 {
    634 
    635 	if (db_symformat != NULL)
    636 		return ((*db_symformat->sym_line_at_pc)(stab, cursym,
    637 		    filename, linenum, off));
    638 	return (FALSE);
    639 }
    640 
    641 boolean_t
    642 X_db_sym_numargs(stab, cursym, nargp, argnamep)
    643 	db_symtab_t *stab;
    644 	db_sym_t cursym;
    645 	int *nargp;
    646 	char **argnamep;
    647 {
    648 
    649 	if (db_symformat != NULL)
    650 		return ((*db_symformat->sym_numargs)(stab, cursym, nargp,
    651 		    argnamep));
    652 	return (FALSE);
    653 }
    654 
    655 void
    656 X_db_forall(stab, db_forall_func, arg)
    657 	db_symtab_t	*stab;
    658 	db_forall_func_t db_forall_func;
    659 	void *arg;
    660 {
    661 	if (db_symformat != NULL)
    662 		(*db_symformat->sym_forall)(stab, db_forall_func, arg);
    663 }
    664