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