xref: /netbsd-src/sys/ddb/db_sym.c (revision 481fca6e59249d8ffcf24fef7cfbe7b131bfb080)
1 /*	$NetBSD: db_sym.c,v 1.22 2000/06/06 05:06:25 jhawk 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/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 				(*pr)("+%#lr", d);
521 			if (strategy == DB_STGY_PROC) {
522 				if (db_line_at_pc(cursym, &filename, &linenum, off))
523 					(*pr)(" [%s:%d]", filename, linenum);
524 			}
525 			return;
526 		}
527 	}
528 	(*pr)(db_num_to_str(off));
529 	return;
530 }
531 
532 
533 boolean_t
534 db_line_at_pc( sym, filename, linenum, pc)
535 	db_sym_t	sym;
536 	char		**filename;
537 	int		*linenum;
538 	db_expr_t	pc;
539 {
540 	return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
541 }
542 
543 int
544 db_sym_numargs(sym, nargp, argnames)
545 	db_sym_t	sym;
546 	int		*nargp;
547 	char		**argnames;
548 {
549 	return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
550 }
551 
552 boolean_t
553 X_db_sym_init(symsize, vss, vse, name)
554 	int symsize;
555 	void *vss, *vse;
556 	const char *name;
557 {
558 
559 	if (db_symformat != NULL)
560 		return ((*db_symformat->sym_init)(symsize, vss, vse, name));
561 	return (FALSE);
562 }
563 
564 db_sym_t
565 X_db_lookup(stab, symstr)
566 	db_symtab_t *stab;
567 	char *symstr;
568 {
569 
570 	if (db_symformat != NULL)
571 		return ((*db_symformat->sym_lookup)(stab, symstr));
572 	return ((db_sym_t)0);
573 }
574 
575 db_sym_t
576 X_db_search_symbol(stab, off, strategy, diffp)
577 	db_symtab_t *stab;
578 	db_addr_t off;
579 	db_strategy_t strategy;
580 	db_expr_t *diffp;
581 {
582 
583 	if (db_symformat != NULL)
584 		return ((*db_symformat->sym_search)(stab, off, strategy,
585 		    diffp));
586 	return ((db_sym_t)0);
587 }
588 
589 void
590 X_db_symbol_values(stab, sym, namep, valuep)
591 	db_symtab_t *stab;
592 	db_sym_t sym;
593 	char **namep;
594 	db_expr_t *valuep;
595 {
596 
597 	if (db_symformat != NULL)
598 		(*db_symformat->sym_value)(stab, sym, namep, valuep);
599 }
600 
601 boolean_t
602 X_db_line_at_pc(stab, cursym, filename, linenum, off)
603 	db_symtab_t *stab;
604 	db_sym_t cursym;
605 	char **filename;
606 	int *linenum;
607 	db_expr_t off;
608 {
609 
610 	if (db_symformat != NULL)
611 		return ((*db_symformat->sym_line_at_pc)(stab, cursym,
612 		    filename, linenum, off));
613 	return (FALSE);
614 }
615 
616 boolean_t
617 X_db_sym_numargs(stab, cursym, nargp, argnamep)
618 	db_symtab_t *stab;
619 	db_sym_t cursym;
620 	int *nargp;
621 	char **argnamep;
622 {
623 
624 	if (db_symformat != NULL)
625 		return ((*db_symformat->sym_numargs)(stab, cursym, nargp,
626 		    argnamep));
627 	return (FALSE);
628 }
629 
630 void
631 X_db_forall(stab, db_forall_func, arg)
632 	db_symtab_t	*stab;
633 	db_forall_func_t db_forall_func;
634 	void *arg;
635 {
636 	if (db_symformat != NULL)
637 		(*db_symformat->sym_forall)(stab, db_forall_func, arg);
638 }
639