db_sym.c revision 1.8 1 /* $NetBSD: db_sym.c,v 1.8 1994/10/09 08:56:27 mycroft 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
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 (at) 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
32 #include <machine/db_machdep.h>
33
34 #include <ddb/db_sym.h>
35
36 /*
37 * We import from the symbol-table dependent routines:
38 */
39 extern db_sym_t X_db_lookup();
40 extern db_sym_t X_db_search_symbol();
41 extern boolean_t X_db_line_at_pc();
42 extern void X_db_symbol_values();
43
44 /*
45 * Multiple symbol tables
46 */
47 #ifndef MAXLKMS
48 #define MAXLKMS 20
49 #endif
50
51 #ifndef MAXNOSYMTABS
52 #define MAXNOSYMTABS MAXLKMS+1 /* Room for kernel + LKM's */
53 #endif
54
55 db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},};
56
57 db_symtab_t *db_last_symtab;
58
59 db_sym_t db_lookup(); /* forward */
60
61 /*
62 * Add symbol table, with given name, to list of symbol tables.
63 */
64 int
65 db_add_symbol_table(start, end, name, ref)
66 char *start;
67 char *end;
68 char *name;
69 char *ref;
70 {
71 int slot;
72
73 for (slot = 0; slot < MAXNOSYMTABS; slot++) {
74 if (db_symtabs[slot].name == NULL)
75 break;
76 }
77 if (slot >= MAXNOSYMTABS) {
78 printf ("No slots left for %s symbol table", name);
79 return(-1);
80 }
81
82 db_symtabs[slot].start = start;
83 db_symtabs[slot].end = end;
84 db_symtabs[slot].name = name;
85 db_symtabs[slot].private = ref;
86
87 return(slot);
88 }
89
90 /*
91 * Delete a symbol table. Caller is responsible for freeing storage.
92 */
93 void
94 db_del_symbol_table(name)
95 char *name;
96 {
97 int slot;
98
99 for (slot = 0; slot < MAXNOSYMTABS; slot++) {
100 if (db_symtabs[slot].name &&
101 ! strcmp(db_symtabs[slot].name, name))
102 break;
103 }
104 if (slot >= MAXNOSYMTABS) {
105 printf ("Unable to find symbol table slot for %s.", name);
106 return;
107 }
108
109 db_symtabs[slot].start = 0;
110 db_symtabs[slot].end = 0;
111 db_symtabs[slot].name = 0;
112 db_symtabs[slot].private = 0;
113 }
114
115 /*
116 * db_qualify("vm_map", "netbsd") returns "netbsd:vm_map".
117 *
118 * Note: return value points to static data whose content is
119 * overwritten by each call... but in practice this seems okay.
120 */
121 static char *
122 db_qualify(sym, symtabname)
123 db_sym_t sym;
124 register char *symtabname;
125 {
126 char *symname;
127 static char tmp[256];
128 register char *s;
129
130 db_symbol_values(sym, &symname, 0);
131 s = tmp;
132 while (*s++ = *symtabname++) {
133 }
134 s[-1] = ':';
135 while (*s++ = *symname++) {
136 }
137 return tmp;
138 }
139
140
141 boolean_t
142 db_eqname(src, dst, c)
143 char *src;
144 char *dst;
145 char c;
146 {
147 if (!strcmp(src, dst))
148 return (TRUE);
149 if (src[0] == c)
150 return (!strcmp(src+1,dst));
151 return (FALSE);
152 }
153
154 boolean_t
155 db_value_of_name(name, valuep)
156 char *name;
157 db_expr_t *valuep;
158 {
159 db_sym_t sym;
160
161 sym = db_lookup(name);
162 if (sym == DB_SYM_NULL)
163 return (FALSE);
164 db_symbol_values(sym, &name, valuep);
165 return (TRUE);
166 }
167
168
169 /*
170 * Lookup a symbol.
171 * If the symbol has a qualifier (e.g., ux:vm_map),
172 * then only the specified symbol table will be searched;
173 * otherwise, all symbol tables will be searched.
174 */
175 db_sym_t
176 db_lookup(symstr)
177 char *symstr;
178 {
179 db_sym_t sp;
180 register int i;
181 int symtab_start = 0;
182 int symtab_end = MAXNOSYMTABS;
183 register char *cp;
184
185 /*
186 * Look for, remove, and remember any symbol table specifier.
187 */
188 for (cp = symstr; *cp; cp++) {
189 if (*cp == ':') {
190 *cp = '\0';
191 for (i = 0; i < MAXNOSYMTABS; i++) {
192 if (db_symtabs[i].name &&
193 ! strcmp(symstr, db_symtabs[i].name)) {
194 symtab_start = i;
195 symtab_end = i + 1;
196 break;
197 }
198 }
199 *cp = ':';
200 if (i == MAXNOSYMTABS) {
201 db_error("invalid symbol table name");
202 /*NOTREACHED*/
203 }
204 symstr = cp+1;
205 }
206 }
207
208 /*
209 * Look in the specified set of symbol tables.
210 * Return on first match.
211 */
212 for (i = symtab_start; i < symtab_end; i++) {
213 if (db_symtabs[i].name &&
214 (sp = X_db_lookup(&db_symtabs[i], symstr))) {
215 db_last_symtab = &db_symtabs[i];
216 return sp;
217 }
218 }
219 return 0;
220 }
221
222 /*
223 * Does this symbol name appear in more than one symbol table?
224 * Used by db_symbol_values to decide whether to qualify a symbol.
225 */
226 boolean_t db_qualify_ambiguous_names = FALSE;
227
228 boolean_t
229 db_symbol_is_ambiguous(sym)
230 db_sym_t sym;
231 {
232 char *sym_name;
233 register int i;
234 register
235 boolean_t found_once = FALSE;
236
237 if (!db_qualify_ambiguous_names)
238 return FALSE;
239
240 db_symbol_values(sym, &sym_name, 0);
241 for (i = 0; i < MAXNOSYMTABS; i++) {
242 if (db_symtabs[i].name &&
243 X_db_lookup(&db_symtabs[i], sym_name)) {
244 if (found_once)
245 return TRUE;
246 found_once = TRUE;
247 }
248 }
249 return FALSE;
250 }
251
252 /*
253 * Find the closest symbol to val, and return its name
254 * and the difference between val and the symbol found.
255 */
256 db_sym_t
257 db_search_symbol( val, strategy, offp)
258 register db_addr_t val;
259 db_strategy_t strategy;
260 db_expr_t *offp;
261 {
262 register
263 unsigned int diff;
264 unsigned int newdiff;
265 register int i;
266 db_sym_t ret = DB_SYM_NULL, sym;
267
268 newdiff = diff = ~0;
269 db_last_symtab = 0;
270 for (i = 0; i < MAXNOSYMTABS; i++) {
271 if (!db_symtabs[i].name)
272 continue;
273 sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
274 if (newdiff < diff) {
275 db_last_symtab = &db_symtabs[i];
276 diff = newdiff;
277 ret = sym;
278 }
279 }
280 *offp = diff;
281 return ret;
282 }
283
284 /*
285 * Return name and value of a symbol
286 */
287 void
288 db_symbol_values(sym, namep, valuep)
289 db_sym_t sym;
290 char **namep;
291 db_expr_t *valuep;
292 {
293 db_expr_t value;
294
295 if (sym == DB_SYM_NULL) {
296 *namep = 0;
297 return;
298 }
299
300 X_db_symbol_values(sym, namep, &value);
301
302 if (db_symbol_is_ambiguous(sym))
303 *namep = db_qualify(sym, db_last_symtab->name);
304 if (valuep)
305 *valuep = value;
306 }
307
308
309 /*
310 * Print a the closest symbol to value
311 *
312 * After matching the symbol according to the given strategy
313 * we print it in the name+offset format, provided the symbol's
314 * value is close enough (eg smaller than db_maxoff).
315 * We also attempt to print [filename:linenum] when applicable
316 * (eg for procedure names).
317 *
318 * If we could not find a reasonable name+offset representation,
319 * then we just print the value in hex. Small values might get
320 * bogus symbol associations, e.g. 3 might get some absolute
321 * value like _INCLUDE_VERSION or something, therefore we do
322 * not accept symbols whose value is zero (and use plain hex).
323 */
324
325 unsigned int db_maxoff = 0x10000000;
326
327 void
328 db_printsym(off, strategy)
329 db_expr_t off;
330 db_strategy_t strategy;
331 {
332 db_expr_t d;
333 char *filename;
334 char *name;
335 db_expr_t value;
336 int linenum;
337 db_sym_t cursym;
338
339 cursym = db_search_symbol(off, strategy, &d);
340 db_symbol_values(cursym, &name, &value);
341 if (name == 0 || d >= db_maxoff || value == 0) {
342 db_printf("%#n", off);
343 return;
344 }
345 db_printf("%s", name);
346 if (d)
347 db_printf("+%#r", d);
348 if (strategy == DB_STGY_PROC) {
349 if (db_line_at_pc(cursym, &filename, &linenum, off))
350 db_printf(" [%s:%d]", filename, linenum);
351 }
352 }
353
354
355 boolean_t
356 db_line_at_pc( sym, filename, linenum, pc)
357 db_sym_t sym;
358 char **filename;
359 int *linenum;
360 db_expr_t pc;
361 {
362 return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
363 }
364
365 int
366 db_sym_numargs(sym, nargp, argnames)
367 db_sym_t sym;
368 int *nargp;
369 char **argnames;
370 {
371 return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
372 }
373