db_sym.c revision 1.30
1/*	$NetBSD: db_sym.c,v 1.30 2002/01/05 20:09:52 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/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: db_sym.c,v 1.30 2002/01/05 20:09:52 jhawk Exp $");
31
32#include "opt_ddb.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
57db_symtab_t	db_symtabs[MAXNOSYMTABS] = {{0,},};
58
59db_symtab_t	*db_last_symtab;
60
61#ifdef SYMTAB_SPACE
62#define		SYMTAB_FILLER	"|This is the symbol table!"
63
64char		db_symtab[SYMTAB_SPACE] = SYMTAB_FILLER;
65int		db_symtabsize = SYMTAB_SPACE;
66#endif
67
68static char *db_qualify __P((db_sym_t, const char *));
69static db_forall_func_t db_sift;
70
71/*
72 * Put the most picky symbol table formats at the top!
73 */
74const 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
84const db_symformat_t *db_symformat;
85
86boolean_t	X_db_sym_init __P((int, void *, void *, const char *));
87db_sym_t	X_db_lookup __P((db_symtab_t *, char *));
88db_sym_t	X_db_search_symbol __P((db_symtab_t *, db_addr_t,
89		    db_strategy_t, db_expr_t *));
90void		X_db_symbol_values __P((db_symtab_t *, db_sym_t, char **,
91		    db_expr_t *));
92boolean_t	X_db_line_at_pc __P((db_symtab_t *, db_sym_t, char **,
93		    int *, db_expr_t));
94int		X_db_sym_numargs __P((db_symtab_t *, db_sym_t, int *,
95		    char **));
96void		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 */
104void
105ddb_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 */
152int
153db_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 */
181void
182db_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 */
209static char *
210db_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
229boolean_t
230db_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
242boolean_t
243db_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 */
263db_sym_t
264db_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(). */
311struct 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 */
321static void
322db_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 */
366void
367db_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 */
422boolean_t db_qualify_ambiguous_names = FALSE;
423
424boolean_t
425db_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 */
451db_sym_t
452db_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 */
481void
482db_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 */
521extern char end[];
522unsigned long	db_lastsym = (unsigned long)end;
523unsigned int	db_maxoff = 0x10000000;
524
525void
526db_symstr(buf, off, strategy)
527	char		*buf;
528	db_expr_t	off;
529	db_strategy_t	strategy;
530{
531	db_expr_t	d;
532	char 		*filename;
533	char		*name;
534	db_expr_t	value;
535	int 		linenum;
536	db_sym_t	cursym;
537
538	if (off <= db_lastsym) {
539		cursym = db_search_symbol(off, strategy, &d);
540		db_symbol_values(cursym, &name, &value);
541		if (name && (d < db_maxoff) && value) {
542			strcpy(buf, name);
543			if (d) {
544				strcat(buf, "+");
545				db_format_radix(buf+strlen(buf), 24, d, TRUE);
546			}
547			if (strategy == DB_STGY_PROC) {
548				if (db_line_at_pc(cursym, &filename, &linenum,
549				    off))
550					sprintf(buf+strlen(buf),
551					    " [%s:%d]", filename, linenum);
552			}
553			return;
554		}
555	}
556	strcpy(buf, db_num_to_str(off));
557	return;
558}
559
560void
561db_printsym(off, strategy, pr)
562	db_expr_t	off;
563	db_strategy_t	strategy;
564	void (*pr) __P((const char *, ...));
565{
566	db_expr_t	d;
567	char 		*filename;
568	char		*name;
569	db_expr_t	value;
570	int 		linenum;
571	db_sym_t	cursym;
572
573	if (off <= db_lastsym) {
574		cursym = db_search_symbol(off, strategy, &d);
575		db_symbol_values(cursym, &name, &value);
576		if (name && (d < db_maxoff) && value) {
577			(*pr)("%s", name);
578			if (d) {
579				char tbuf[24];
580
581				db_format_radix(tbuf, 24, d, TRUE);
582				(*pr)("+%s", tbuf);
583			}
584			if (strategy == DB_STGY_PROC) {
585				if (db_line_at_pc(cursym, &filename, &linenum, off))
586					(*pr)(" [%s:%d]", filename, linenum);
587			}
588			return;
589		}
590	}
591	(*pr)(db_num_to_str(off));
592	return;
593}
594
595
596boolean_t
597db_line_at_pc( sym, filename, linenum, pc)
598	db_sym_t	sym;
599	char		**filename;
600	int		*linenum;
601	db_expr_t	pc;
602{
603	return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
604}
605
606int
607db_sym_numargs(sym, nargp, argnames)
608	db_sym_t	sym;
609	int		*nargp;
610	char		**argnames;
611{
612	return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
613}
614
615boolean_t
616X_db_sym_init(symsize, vss, vse, name)
617	int symsize;
618	void *vss, *vse;
619	const char *name;
620{
621
622	if (db_symformat != NULL)
623		return ((*db_symformat->sym_init)(symsize, vss, vse, name));
624	return (FALSE);
625}
626
627db_sym_t
628X_db_lookup(stab, symstr)
629	db_symtab_t *stab;
630	char *symstr;
631{
632
633	if (db_symformat != NULL)
634		return ((*db_symformat->sym_lookup)(stab, symstr));
635	return ((db_sym_t)0);
636}
637
638db_sym_t
639X_db_search_symbol(stab, off, strategy, diffp)
640	db_symtab_t *stab;
641	db_addr_t off;
642	db_strategy_t strategy;
643	db_expr_t *diffp;
644{
645
646	if (db_symformat != NULL)
647		return ((*db_symformat->sym_search)(stab, off, strategy,
648		    diffp));
649	return ((db_sym_t)0);
650}
651
652void
653X_db_symbol_values(stab, sym, namep, valuep)
654	db_symtab_t *stab;
655	db_sym_t sym;
656	char **namep;
657	db_expr_t *valuep;
658{
659
660	if (db_symformat != NULL)
661		(*db_symformat->sym_value)(stab, sym, namep, valuep);
662}
663
664boolean_t
665X_db_line_at_pc(stab, cursym, filename, linenum, off)
666	db_symtab_t *stab;
667	db_sym_t cursym;
668	char **filename;
669	int *linenum;
670	db_expr_t off;
671{
672
673	if (db_symformat != NULL)
674		return ((*db_symformat->sym_line_at_pc)(stab, cursym,
675		    filename, linenum, off));
676	return (FALSE);
677}
678
679boolean_t
680X_db_sym_numargs(stab, cursym, nargp, argnamep)
681	db_symtab_t *stab;
682	db_sym_t cursym;
683	int *nargp;
684	char **argnamep;
685{
686
687	if (db_symformat != NULL)
688		return ((*db_symformat->sym_numargs)(stab, cursym, nargp,
689		    argnamep));
690	return (FALSE);
691}
692
693void
694X_db_forall(stab, db_forall_func, arg)
695	db_symtab_t	*stab;
696	db_forall_func_t db_forall_func;
697	void *arg;
698{
699	if (db_symformat != NULL)
700		(*db_symformat->sym_forall)(stab, db_forall_func, arg);
701}
702