xref: /freebsd/sys/ddb/db_sym.c (revision efeaf95a)
1 /*
2  * Mach Operating System
3  * Copyright (c) 1991,1990 Carnegie Mellon University
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify and distribute this software and its
7  * documentation is hereby granted, provided that both the copyright
8  * notice and this permission notice appear in all copies of the
9  * software, derivative works or modified versions, and any portions
10  * thereof, and that both notices appear in supporting documentation.
11  *
12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15  *
16  * Carnegie Mellon requests users of this software to return to
17  *
18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19  *  School of Computer Science
20  *  Carnegie Mellon University
21  *  Pittsburgh PA 15213-3890
22  *
23  * any improvements or extensions that they make and grant Carnegie the
24  * rights to redistribute these changes.
25  *
26  *	$Id: db_sym.c,v 1.11 1995/11/29 10:25:35 phk Exp $
27  */
28 
29 /*
30  * 	Author: David B. Golub, Carnegie Mellon University
31  *	Date:	7/90
32  */
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/proc.h>
36 #include <vm/vm_param.h>
37 #include <ddb/ddb.h>
38 #include <ddb/db_sym.h>
39 
40 /*
41  * Multiple symbol tables
42  */
43 #ifndef MAXNOSYMTABS
44 #define	MAXNOSYMTABS	3	/* mach, ux, emulator */
45 #endif
46 
47 static db_symtab_t	db_symtabs[MAXNOSYMTABS] = {{0,},};
48 static int db_nsymtab = 0;
49 
50 db_symtab_t	*db_last_symtab;
51 
52 static db_sym_t		db_lookup __P(( char *symstr));
53 static char		*db_qualify __P((db_sym_t sym, char *symtabname));
54 static boolean_t	db_symbol_is_ambiguous __P((db_sym_t sym));
55 static boolean_t	db_line_at_pc __P((db_sym_t, char **, int *,
56 				db_expr_t));
57 
58 /*
59  * Add symbol table, with given name, to list of symbol tables.
60  */
61 void
62 db_add_symbol_table(start, end, name, ref)
63 	char *start;
64 	char *end;
65 	char *name;
66 	char *ref;
67 {
68 	if (db_nsymtab >= MAXNOSYMTABS) {
69 		printf ("No slots left for %s symbol table", name);
70 		panic ("db_sym.c: db_add_symbol_table");
71 	}
72 
73 	db_symtabs[db_nsymtab].start = start;
74 	db_symtabs[db_nsymtab].end = end;
75 	db_symtabs[db_nsymtab].name = name;
76 	db_symtabs[db_nsymtab].private = ref;
77 	db_nsymtab++;
78 }
79 
80 /*
81  *  db_qualify("vm_map", "ux") returns "unix:vm_map".
82  *
83  *  Note: return value points to static data whose content is
84  *  overwritten by each call... but in practice this seems okay.
85  */
86 static char *
87 db_qualify(sym, symtabname)
88 	db_sym_t	sym;
89 	register char	*symtabname;
90 {
91 	char		*symname;
92 	static char     tmp[256];
93 
94 	db_symbol_values(sym, &symname, 0);
95 	strcpy(tmp,symtabname);
96 	strcat(tmp,":");
97 	strcat(tmp,symname);
98 	return tmp;
99 }
100 
101 
102 boolean_t
103 db_eqname(src, dst, c)
104 	char *src;
105 	char *dst;
106 	char c;
107 {
108 	if (!strcmp(src, dst))
109 	    return (TRUE);
110 	if (src[0] == c)
111 	    return (!strcmp(src+1,dst));
112 	return (FALSE);
113 }
114 
115 boolean_t
116 db_value_of_name(name, valuep)
117 	char		*name;
118 	db_expr_t	*valuep;
119 {
120 	db_sym_t	sym;
121 
122 	sym = db_lookup(name);
123 	if (sym == DB_SYM_NULL)
124 	    return (FALSE);
125 	db_symbol_values(sym, &name, valuep);
126 	return (TRUE);
127 }
128 
129 
130 /*
131  * Lookup a symbol.
132  * If the symbol has a qualifier (e.g., ux:vm_map),
133  * then only the specified symbol table will be searched;
134  * otherwise, all symbol tables will be searched.
135  */
136 static db_sym_t
137 db_lookup(symstr)
138 	char *symstr;
139 {
140 	db_sym_t sp;
141 	register int i;
142 	int symtab_start = 0;
143 	int symtab_end = db_nsymtab;
144 	register char *cp;
145 
146 	/*
147 	 * Look for, remove, and remember any symbol table specifier.
148 	 */
149 	for (cp = symstr; *cp; cp++) {
150 		if (*cp == ':') {
151 			*cp = '\0';
152 			for (i = 0; i < db_nsymtab; i++) {
153 				if (! strcmp(symstr, db_symtabs[i].name)) {
154 					symtab_start = i;
155 					symtab_end = i + 1;
156 					break;
157 				}
158 			}
159 			*cp = ':';
160 			if (i == db_nsymtab) {
161 				db_error("invalid symbol table name");
162 			}
163 			symstr = cp+1;
164 		}
165 	}
166 
167 	/*
168 	 * Look in the specified set of symbol tables.
169 	 * Return on first match.
170 	 */
171 	for (i = symtab_start; i < symtab_end; i++) {
172 		sp = X_db_lookup(&db_symtabs[i], symstr);
173 		if (sp) {
174 			db_last_symtab = &db_symtabs[i];
175 			return sp;
176 		}
177 	}
178 	return 0;
179 }
180 
181 /*
182  * Does this symbol name appear in more than one symbol table?
183  * Used by db_symbol_values to decide whether to qualify a symbol.
184  */
185 static boolean_t db_qualify_ambiguous_names = FALSE;
186 
187 static boolean_t
188 db_symbol_is_ambiguous(sym)
189 	db_sym_t	sym;
190 {
191 	char		*sym_name;
192 	register int	i;
193 	register
194 	boolean_t	found_once = FALSE;
195 
196 	if (!db_qualify_ambiguous_names)
197 		return FALSE;
198 
199 	db_symbol_values(sym, &sym_name, 0);
200 	for (i = 0; i < db_nsymtab; i++) {
201 		if (X_db_lookup(&db_symtabs[i], sym_name)) {
202 			if (found_once)
203 				return TRUE;
204 			found_once = TRUE;
205 		}
206 	}
207 	return FALSE;
208 }
209 
210 /*
211  * Find the closest symbol to val, and return its name
212  * and the difference between val and the symbol found.
213  */
214 db_sym_t
215 db_search_symbol( val, strategy, offp)
216 	register db_addr_t	val;
217 	db_strategy_t		strategy;
218 	db_expr_t		*offp;
219 {
220 	register
221 	unsigned int	diff;
222 	unsigned int	newdiff;
223 	register int	i;
224 	db_sym_t	ret = DB_SYM_NULL, sym;
225 
226 	newdiff = diff = ~0;
227 	db_last_symtab = 0;
228 	for (i = 0; i < db_nsymtab; i++) {
229 	    sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
230 	    if (newdiff < diff) {
231 		db_last_symtab = &db_symtabs[i];
232 		diff = newdiff;
233 		ret = sym;
234 	    }
235 	}
236 	*offp = diff;
237 	return ret;
238 }
239 
240 /*
241  * Return name and value of a symbol
242  */
243 void
244 db_symbol_values(sym, namep, valuep)
245 	db_sym_t	sym;
246 	char		**namep;
247 	db_expr_t	*valuep;
248 {
249 	db_expr_t	value;
250 
251 	if (sym == DB_SYM_NULL) {
252 		*namep = 0;
253 		return;
254 	}
255 
256 	X_db_symbol_values(sym, namep, &value);
257 
258 	if (db_symbol_is_ambiguous(sym))
259 		*namep = db_qualify(sym, db_last_symtab->name);
260 	if (valuep)
261 		*valuep = value;
262 }
263 
264 
265 /*
266  * Print a the closest symbol to value
267  *
268  * After matching the symbol according to the given strategy
269  * we print it in the name+offset format, provided the symbol's
270  * value is close enough (eg smaller than db_maxoff).
271  * We also attempt to print [filename:linenum] when applicable
272  * (eg for procedure names).
273  *
274  * If we could not find a reasonable name+offset representation,
275  * then we just print the value in hex.  Small values might get
276  * bogus symbol associations, e.g. 3 might get some absolute
277  * value like _INCLUDE_VERSION or something, therefore we do
278  * not accept symbols whose value is zero (and use plain hex).
279  */
280 
281 unsigned int	db_maxoff = 0x10000;
282 
283 void
284 db_printsym(off, strategy)
285 	db_expr_t	off;
286 	db_strategy_t	strategy;
287 {
288 	db_expr_t	d;
289 	char 		*filename;
290 	char		*name;
291 	db_expr_t	value;
292 	int 		linenum;
293 	db_sym_t	cursym;
294 
295 	cursym = db_search_symbol(off, strategy, &d);
296 	db_symbol_values(cursym, &name, &value);
297 	if (name == 0 || d >= db_maxoff || value == 0) {
298 		db_printf("%#n", off);
299 		return;
300 	}
301 	db_printf("%s", name);
302 	if (d)
303 		db_printf("+%#r", d);
304 	if (strategy == DB_STGY_PROC) {
305 		if (db_line_at_pc(cursym, &filename, &linenum, off))
306 			db_printf(" [%s:%d]", filename, linenum);
307 	}
308 }
309 
310 static boolean_t
311 db_line_at_pc( sym, filename, linenum, pc)
312 	db_sym_t	sym;
313 	char		**filename;
314 	int		*linenum;
315 	db_expr_t	pc;
316 {
317 	return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
318 }
319 
320 int
321 db_sym_numargs(sym, nargp, argnames)
322 	db_sym_t	sym;
323 	int		*nargp;
324 	char		**argnames;
325 {
326 	return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
327 }
328