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