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