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