xref: /openbsd/sys/ddb/db_sym.c (revision 91f110e0)
1 /*	$OpenBSD: db_sym.c,v 1.34 2014/03/16 20:31:46 guenther 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 extern char end[];
60 
61 /*
62  * Put the most picky symbol table formats at the top!
63  */
64 const db_symformat_t *db_symformats[] = {
65 	&db_symformat_elf,
66 	NULL,
67 };
68 
69 const db_symformat_t *db_symformat;
70 
71 boolean_t	X_db_sym_init(int, void *, void *, const char *);
72 db_sym_t	X_db_lookup(db_symtab_t *, char *);
73 db_sym_t	X_db_search_symbol(db_symtab_t *, db_addr_t,
74 		    db_strategy_t, db_expr_t *);
75 void		X_db_symbol_values(db_symtab_t *, db_sym_t, char **,
76 		    db_expr_t *);
77 boolean_t	X_db_line_at_pc(db_symtab_t *, db_sym_t, char **,
78 		    int *, db_expr_t);
79 int		X_db_sym_numargs(db_symtab_t *, db_sym_t, int *,
80 		    char **);
81 
82 /*
83  * Initialize the kernel debugger by initializing the master symbol
84  * table.  Note that if initializing the master symbol table fails,
85  * no other symbol tables can be loaded.
86  */
87 #if 0
88 void
89 ddb_init(int symsize, void *vss, void *vse)
90 {
91 	const db_symformat_t **symf;
92 	const char *name = "bsd";
93 
94 	if (symsize <= 0) {
95 		printf(" [ no symbols available ]\n");
96 		return;
97 	}
98 
99 	/*
100 	 * Do this check now for the master symbol table to avoid printing
101 	 * the message N times.
102 	 */
103 	if (ALIGNED_POINTER(vss, long) == 0) {
104 		printf("[ %s symbol table has bad start address %p ]\n",
105 		    name, vss);
106 		return;
107 	}
108 
109 	for (symf = db_symformats; *symf != NULL; symf++) {
110 		db_symformat = *symf;
111 		if (X_db_sym_init(symsize, vss, vse, name) == TRUE)
112 			return;
113 	}
114 
115 	db_symformat = NULL;
116 	printf("[ no symbol table formats found ]\n");
117 }
118 #else
119 void
120 ddb_init(void)
121 {
122 	const db_symformat_t **symf;
123 	const char *name = "bsd";
124 	extern char *esym;
125 #if defined(__sparc64__) || defined(__mips__)
126 	extern char *ssym;
127 #endif
128 	char *xssym, *xesym;
129 
130 	xesym = esym;
131 #if defined(__sparc64__) || defined(__mips__)
132 	xssym = ssym;
133 #else
134 	xssym = (char *)&end;
135 #endif
136 	/*
137 	 * Do this check now for the master symbol table to avoid printing
138 	 * the message N times.
139 	 */
140 	if ((((vaddr_t)xssym) & (sizeof(long) - 1)) != 0) {
141 		printf("[ %s symbol table has bad start address %p ]\n",
142 		    name, xssym);
143 		return;
144 	}
145 
146 	if (xesym != NULL && xesym != xssym)
147 		for (symf = db_symformats; *symf != NULL; symf++) {
148 			db_symformat = *symf;
149 			if (X_db_sym_init((vaddr_t)xesym - (vaddr_t)xssym,
150 			    xssym, xesym, name) == TRUE)
151 			return;
152 		}
153 
154 	db_symformat = NULL;
155 	printf("[ no symbol table formats found ]\n");
156 }
157 #endif
158 
159 /*
160  * Add symbol table, with given name, to list of symbol tables.
161  */
162 int
163 db_add_symbol_table(char *start, char *end, const char *name, char *ref)
164 {
165 	int slot;
166 
167 	for (slot = 0; slot < MAXNOSYMTABS; slot++) {
168 		if (db_symtabs[slot].name == NULL)
169 			break;
170 	}
171 	if (slot >= MAXNOSYMTABS) {
172 		db_printf("No slots left for %s symbol table", name);
173 		return(-1);
174 	}
175 
176 	db_symtabs[slot].start = start;
177 	db_symtabs[slot].end = end;
178 	db_symtabs[slot].name = name;
179 	db_symtabs[slot].private = ref;
180 
181 	return(slot);
182 }
183 
184 /*
185  * Delete a symbol table. Caller is responsible for freeing storage.
186  */
187 void
188 db_del_symbol_table(char *name)
189 {
190 	int slot;
191 
192 	for (slot = 0; slot < MAXNOSYMTABS; slot++) {
193 		if (db_symtabs[slot].name &&
194 		    ! strcmp(db_symtabs[slot].name, name))
195 			break;
196 	}
197 	if (slot >= MAXNOSYMTABS) {
198 		db_printf("Unable to find symbol table slot for %s.", name);
199 		return;
200 	}
201 
202 	db_symtabs[slot].start = 0;
203 	db_symtabs[slot].end = 0;
204 	db_symtabs[slot].name = 0;
205 	db_symtabs[slot].private = 0;
206 }
207 
208 /*
209  *  db_qualify("vm_map", "bsd") returns "bsd:vm_map".
210  *
211  *  Note: return value points to static data whose content is
212  *  overwritten by each call... but in practice this seems okay.
213  */
214 char *
215 db_qualify(db_sym_t sym, const char *symtabname)
216 {
217 	char		*symname;
218 	static char     tmp[256];
219 	char	*s;
220 
221 	db_symbol_values(sym, &symname, 0);
222 	s = tmp;
223 	while ((*s++ = *symtabname++) != '\0')
224 		;
225 	s[-1] = ':';
226 	while ((*s++ = *symname++) != '\0')
227 		;
228 	return tmp;
229 }
230 
231 
232 boolean_t
233 db_eqname(char *src, char *dst, 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 
242 boolean_t
243 db_value_of_name(char *name, db_expr_t *valuep)
244 {
245 	db_sym_t	sym;
246 
247 	sym = db_lookup(name);
248 	if (sym == DB_SYM_NULL)
249 	    return (FALSE);
250 	db_symbol_values(sym, &name, valuep);
251 	return (TRUE);
252 }
253 
254 
255 /*
256  * Lookup a symbol.
257  * If the symbol has a qualifier (e.g., ux:vm_map),
258  * then only the specified symbol table will be searched;
259  * otherwise, all symbol tables will be searched.
260  */
261 db_sym_t
262 db_lookup(char *symstr)
263 {
264 	db_sym_t sp;
265 	int i;
266 	int symtab_start = 0;
267 	int symtab_end = MAXNOSYMTABS;
268 	char *cp;
269 
270 	/*
271 	 * Look for, remove, and remember any symbol table specifier.
272 	 */
273 	for (cp = symstr; *cp; cp++) {
274 		if (*cp == ':') {
275 			*cp = '\0';
276 			for (i = 0; i < MAXNOSYMTABS; i++) {
277 				if (db_symtabs[i].name &&
278 				    ! strcmp(symstr, db_symtabs[i].name)) {
279 					symtab_start = i;
280 					symtab_end = i + 1;
281 					break;
282 				}
283 			}
284 			*cp = ':';
285 			if (i == MAXNOSYMTABS) {
286 				db_error("invalid symbol table name");
287 				/*NOTREACHED*/
288 			}
289 			symstr = cp+1;
290 		}
291 	}
292 
293 	/*
294 	 * Look in the specified set of symbol tables.
295 	 * Return on first match.
296 	 */
297 	for (i = symtab_start; i < symtab_end; i++) {
298 		if (db_symtabs[i].name &&
299 		    (sp = X_db_lookup(&db_symtabs[i], symstr))) {
300 			db_last_symtab = &db_symtabs[i];
301 			return sp;
302 		}
303 	}
304 	return 0;
305 }
306 
307 /* Private structure for passing args to db_sift() from db_sifting(). */
308 struct db_sift_args {
309 	char	*symstr;
310 	int	mode;
311 };
312 
313 /*
314  * Does the work of db_sifting(), called once for each
315  * symbol via X_db_forall(), prints out symbols matching
316  * criteria.
317  */
318 static void
319 db_sift(db_symtab_t *stab, db_sym_t sym, char *name, char *suffix, int prefix,
320     void *arg)
321 {
322 	char c, sc;
323 	char *find, *p;
324 	size_t len;
325 	struct db_sift_args *dsa;
326 
327 	dsa = (struct db_sift_args*)arg;
328 
329 	find = dsa->symstr;	/* String we're looking for. */
330 	p = name;		/* String we're searching within. */
331 
332 	/* Matching algorithm cribbed from strstr(), which is not
333 	   in the kernel. */
334 	if ((c = *find++) != 0) {
335 		len = strlen(find);
336 		do {
337 			do {
338 				if ((sc = *p++) == 0)
339 					return;
340 			} while (sc != c);
341 		} while (strncmp(p, find, len) != 0);
342 	}
343 	if (dsa->mode=='F')	/* ala ls -F */
344 		db_printf("%s%s ", name, suffix);
345 	else
346 		db_printf("%s ", name);
347 }
348 
349 /*
350  * "Sift" for a partial symbol.
351  * Named for the Sun OpenPROM command ("sifting").
352  * If the symbol has a qualifier (e.g., ux:vm_map),
353  * then only the specified symbol table will be searched;
354  * otherwise, all symbol tables will be searched..
355  *
356  * "mode" is how-to-display, set from modifiers.
357  */
358 void
359 db_sifting(char *symstr, int mode)
360 {
361 	char *cp;
362 	int i;
363 	int symtab_start = 0;
364 	int symtab_end = MAXNOSYMTABS;
365 	struct db_sift_args dsa;
366 
367 	/*
368 	 * Look for, remove, and remember any symbol table specifier.
369 	 */
370 	for (cp = symstr; *cp; cp++) {
371 		if (*cp == ':') {
372 			*cp = '\0';
373 			for (i = 0; i < MAXNOSYMTABS; i++) {
374 				if (db_symtabs[i].name &&
375 				    ! strcmp(symstr, db_symtabs[i].name)) {
376 					symtab_start = i;
377 					symtab_end = i + 1;
378 					break;
379 				}
380 			}
381 			*cp = ':';
382 			if (i == MAXNOSYMTABS) {
383 				db_error("invalid symbol table name");
384 				/*NOTREACHED*/
385 			}
386 			symstr = cp+1;
387 		}
388 	}
389 
390 	/* Pass args to db_sift(). */
391 	dsa.symstr = symstr;
392 	dsa.mode = mode;
393 
394 	/*
395 	 * Look in the specified set of symbol tables.
396 	 */
397 	for (i = symtab_start; i < symtab_end; i++)
398 		if (db_symtabs[i].name) {
399 			db_printf("Sifting table %s:\n", db_symtabs[i].name);
400 			X_db_forall(&db_symtabs[i], db_sift, &dsa);
401 		}
402 
403 	return;
404 }
405 
406 
407 /*
408  * Does this symbol name appear in more than one symbol table?
409  * Used by db_symbol_values to decide whether to qualify a symbol.
410  */
411 boolean_t db_qualify_ambiguous_names = FALSE;
412 
413 boolean_t
414 db_symbol_is_ambiguous(db_sym_t sym)
415 {
416 	char		*sym_name;
417 	int	i;
418 	boolean_t	found_once = FALSE;
419 
420 	if (!db_qualify_ambiguous_names)
421 		return FALSE;
422 
423 	db_symbol_values(sym, &sym_name, 0);
424 	for (i = 0; i < MAXNOSYMTABS; i++) {
425 		if (db_symtabs[i].name &&
426 		    X_db_lookup(&db_symtabs[i], sym_name)) {
427 			if (found_once)
428 				return TRUE;
429 			found_once = TRUE;
430 		}
431 	}
432 	return FALSE;
433 }
434 
435 /*
436  * Find the closest symbol to val, and return its name
437  * and the difference between val and the symbol found.
438  */
439 db_sym_t
440 db_search_symbol(db_addr_t val, db_strategy_t strategy, db_expr_t *offp)
441 {
442 	unsigned int	diff;
443 	db_expr_t	newdiff;
444 	int		i;
445 	db_sym_t	ret = DB_SYM_NULL, sym;
446 
447 	newdiff = diff = ~0;
448 	db_last_symtab = 0;
449 	for (i = 0; i < MAXNOSYMTABS; i++) {
450 	    if (!db_symtabs[i].name)
451 	        continue;
452 	    sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
453 	    if (newdiff < diff) {
454 		db_last_symtab = &db_symtabs[i];
455 		diff = newdiff;
456 		ret = sym;
457 	    }
458 	}
459 	*offp = diff;
460 	return ret;
461 }
462 
463 /*
464  * Return name and value of a symbol
465  */
466 void
467 db_symbol_values(db_sym_t sym, char **namep, db_expr_t *valuep)
468 {
469 	db_expr_t	value;
470 
471 	if (sym == DB_SYM_NULL) {
472 		*namep = 0;
473 		return;
474 	}
475 
476 	X_db_symbol_values(db_last_symtab, sym, namep, &value);
477 
478 	if (db_symbol_is_ambiguous(sym))
479 		*namep = db_qualify(sym, db_last_symtab->name);
480 	if (valuep)
481 		*valuep = value;
482 }
483 
484 
485 /*
486  * Print a the closest symbol to value
487  *
488  * After matching the symbol according to the given strategy
489  * we print it in the name+offset format, provided the symbol's
490  * value is close enough (eg smaller than db_maxoff).
491  * We also attempt to print [filename:linenum] when applicable
492  * (eg for procedure names).
493  *
494  * If we could not find a reasonable name+offset representation,
495  * then we just print the value in hex.  Small values might get
496  * bogus symbol associations, e.g. 3 might get some absolute
497  * value like _INCLUDE_VERSION or something, therefore we do
498  * not accept symbols whose value is zero (and use plain hex).
499  * Also, avoid printing as "end+0x????" which is useless.
500  * The variable db_lastsym is used instead of "end" in case we
501  * add support for symbols in loadable driver modules.
502  */
503 unsigned long	db_lastsym = (unsigned long)end;
504 unsigned int	db_maxoff = 0x10000000;
505 
506 
507 void
508 db_printsym(db_expr_t off, db_strategy_t strategy,
509     int (*pr)(const char *, ...))
510 {
511 	db_expr_t	d;
512 	char 		*filename;
513 	char		*name;
514 	db_expr_t	value;
515 	int 		linenum;
516 	db_sym_t	cursym;
517 	char		buf[DB_FORMAT_BUF_SIZE];
518 
519 	if (off <= db_lastsym) {
520 		cursym = db_search_symbol(off, strategy, &d);
521 		db_symbol_values(cursym, &name, &value);
522 		if (name && (d < db_maxoff) && value) {
523 			(*pr)("%s", name);
524 			if (d) {
525 				(*pr)("+%s", db_format(buf, sizeof(buf),
526 				    d, DB_FORMAT_R, 1, 0));
527 			}
528 			if (strategy == DB_STGY_PROC) {
529 				if (db_line_at_pc(cursym, &filename, &linenum, off))
530 					(*pr)(" [%s:%d]", filename, linenum);
531 			}
532 			return;
533 		}
534 	}
535 
536 	(*pr)("%s", db_format(buf, sizeof(buf), off, DB_FORMAT_N, 1, 0));
537 	return;
538 }
539 
540 
541 boolean_t
542 db_line_at_pc(db_sym_t sym, char **filename, int *linenum, db_expr_t pc)
543 {
544 	return X_db_line_at_pc(db_last_symtab, sym, filename, linenum, pc);
545 }
546 
547 int
548 db_sym_numargs(db_sym_t sym, int *nargp, char **argnames)
549 {
550 	return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
551 }
552 
553 boolean_t
554 X_db_sym_init(int symsize, void *vss, void *vse, const char *name)
555 {
556 
557 	if (db_symformat != NULL)
558 		return ((*db_symformat->sym_init)(symsize, vss, vse, name));
559 	return (FALSE);
560 }
561 
562 db_sym_t
563 X_db_lookup(db_symtab_t *stab, char *symstr)
564 {
565 
566 	if (db_symformat != NULL)
567 		return ((*db_symformat->sym_lookup)(stab, symstr));
568 	return ((db_sym_t)0);
569 }
570 
571 db_sym_t
572 X_db_search_symbol(db_symtab_t *stab, db_addr_t off, db_strategy_t strategy,
573     db_expr_t *diffp)
574 {
575 
576 	if (db_symformat != NULL)
577 		return ((*db_symformat->sym_search)(stab, off, strategy,
578 		    diffp));
579 	return ((db_sym_t)0);
580 }
581 
582 void
583 X_db_symbol_values(db_symtab_t *stab, db_sym_t sym, char **namep,
584     db_expr_t *valuep)
585 {
586 
587 	if (db_symformat != NULL)
588 		(*db_symformat->sym_value)(stab, sym, namep, valuep);
589 }
590 
591 boolean_t
592 X_db_line_at_pc(db_symtab_t *stab, db_sym_t cursym, char **filename,
593     int *linenum, db_expr_t off)
594 {
595 
596 	if (db_symformat != NULL)
597 		return ((*db_symformat->sym_line_at_pc)(stab, cursym,
598 		    filename, linenum, off));
599 	return (FALSE);
600 }
601 
602 boolean_t
603 X_db_sym_numargs(db_symtab_t *stab, db_sym_t cursym, int *nargp,
604     char **argnamep)
605 {
606 
607 	if (db_symformat != NULL)
608 		return ((*db_symformat->sym_numargs)(stab, cursym, nargp,
609 		    argnamep));
610 	return (FALSE);
611 }
612 
613 void
614 X_db_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg)
615 {
616 	if (db_symformat != NULL)
617 		(*db_symformat->sym_forall)(stab, db_forall_func, arg);
618 }
619