db_sym.c revision 1.20
1/*	$NetBSD: db_sym.c,v 1.20 2000/05/22 14:49:10 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
52db_symtab_t	db_symtabs[MAXNOSYMTABS] = {{0,},};
53
54db_symtab_t	*db_last_symtab;
55
56static char *db_qualify __P((db_sym_t, const char *));
57static db_forall_func_t db_sift;
58
59/*
60 * Put the most picky symbol table formats at the top!
61 */
62const 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
72const db_symformat_t *db_symformat;
73
74boolean_t	X_db_sym_init __P((int, void *, void *, const char *));
75db_sym_t	X_db_lookup __P((db_symtab_t *, char *));
76db_sym_t	X_db_search_symbol __P((db_symtab_t *, db_addr_t,
77		    db_strategy_t, db_expr_t *));
78void		X_db_symbol_values __P((db_symtab_t *, db_sym_t, char **,
79		    db_expr_t *));
80boolean_t	X_db_line_at_pc __P((db_symtab_t *, db_sym_t, char **,
81		    int *, db_expr_t));
82int		X_db_sym_numargs __P((db_symtab_t *, db_sym_t, int *,
83		    char **));
84void		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 */
92void
93ddb_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 */
128int
129db_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 */
157void
158db_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 */
185static char *
186db_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
205boolean_t
206db_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
218boolean_t
219db_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 */
239db_sym_t
240db_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(). */
287struct 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 */
297static void
298db_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 */
342void
343db_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 */
397boolean_t db_qualify_ambiguous_names = FALSE;
398
399boolean_t
400db_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 */
426db_sym_t
427db_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 */
456void
457db_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 */
496extern char end[];
497unsigned long	db_lastsym = (unsigned long)end;
498unsigned int	db_maxoff = 0x10000000;
499
500
501void
502db_printsym(off, strategy)
503	db_expr_t	off;
504	db_strategy_t	strategy;
505{
506	db_expr_t	d;
507	char 		*filename;
508	char		*name;
509	db_expr_t	value;
510	int 		linenum;
511	db_sym_t	cursym;
512
513	if (off <= db_lastsym) {
514		cursym = db_search_symbol(off, strategy, &d);
515		db_symbol_values(cursym, &name, &value);
516		if (name && (d < db_maxoff) && value) {
517			db_printf("%s", name);
518			if (d)
519				db_printf("+%#lr", d);
520			if (strategy == DB_STGY_PROC) {
521				if (db_line_at_pc(cursym, &filename, &linenum, off))
522					db_printf(" [%s:%d]", filename, linenum);
523			}
524			return;
525		}
526	}
527	db_printf("%#ln", off);
528	return;
529}
530
531
532boolean_t
533db_line_at_pc( sym, filename, linenum, pc)
534	db_sym_t	sym;
535	char		**filename;
536	int		*linenum;
537	db_expr_t	pc;
538{
539	return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
540}
541
542int
543db_sym_numargs(sym, nargp, argnames)
544	db_sym_t	sym;
545	int		*nargp;
546	char		**argnames;
547{
548	return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
549}
550
551boolean_t
552X_db_sym_init(symsize, vss, vse, name)
553	int symsize;
554	void *vss, *vse;
555	const char *name;
556{
557
558	if (db_symformat != NULL)
559		return ((*db_symformat->sym_init)(symsize, vss, vse, name));
560	return (FALSE);
561}
562
563db_sym_t
564X_db_lookup(stab, symstr)
565	db_symtab_t *stab;
566	char *symstr;
567{
568
569	if (db_symformat != NULL)
570		return ((*db_symformat->sym_lookup)(stab, symstr));
571	return ((db_sym_t)0);
572}
573
574db_sym_t
575X_db_search_symbol(stab, off, strategy, diffp)
576	db_symtab_t *stab;
577	db_addr_t off;
578	db_strategy_t strategy;
579	db_expr_t *diffp;
580{
581
582	if (db_symformat != NULL)
583		return ((*db_symformat->sym_search)(stab, off, strategy,
584		    diffp));
585	return ((db_sym_t)0);
586}
587
588void
589X_db_symbol_values(stab, sym, namep, valuep)
590	db_symtab_t *stab;
591	db_sym_t sym;
592	char **namep;
593	db_expr_t *valuep;
594{
595
596	if (db_symformat != NULL)
597		(*db_symformat->sym_value)(stab, sym, namep, valuep);
598}
599
600boolean_t
601X_db_line_at_pc(stab, cursym, filename, linenum, off)
602	db_symtab_t *stab;
603	db_sym_t cursym;
604	char **filename;
605	int *linenum;
606	db_expr_t off;
607{
608
609	if (db_symformat != NULL)
610		return ((*db_symformat->sym_line_at_pc)(stab, cursym,
611		    filename, linenum, off));
612	return (FALSE);
613}
614
615boolean_t
616X_db_sym_numargs(stab, cursym, nargp, argnamep)
617	db_symtab_t *stab;
618	db_sym_t cursym;
619	int *nargp;
620	char **argnamep;
621{
622
623	if (db_symformat != NULL)
624		return ((*db_symformat->sym_numargs)(stab, cursym, nargp,
625		    argnamep));
626	return (FALSE);
627}
628
629void
630X_db_forall(stab, db_forall_func, arg)
631	db_symtab_t	*stab;
632	db_forall_func_t db_forall_func;
633	void *arg;
634{
635	if (db_symformat != NULL)
636		(*db_symformat->sym_forall)(stab, db_forall_func, arg);
637}
638