xref: /netbsd-src/sys/ddb/db_sym.c (revision 06be8101a16cc95f40783b3cb7afd12112103a9a)
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@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