db_sym.c revision 1.4 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 (at) 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 /*
27 * db_sym.c,v 1.2 1993/05/20 03:39:31 cgd Exp
28 *
29 * HISTORY
30 * db_sym.c,v
31 * Revision 1.2 1993/05/20 03:39:31 cgd
32 * add explicit rcs id
33 *
34 * Revision 1.1.1.1 1993/03/21 09:46:27 cgd
35 * initial import of 386bsd-0.1 sources
36 *
37 * Revision 1.1 1992/03/25 21:45:27 pace
38 * Initial revision
39 *
40 * Revision 2.5 91/02/05 17:07:07 mrt
41 * Changed to new Mach copyright
42 * [91/01/31 16:19:17 mrt]
43 *
44 * Revision 2.4 90/10/25 14:44:05 rwd
45 * Changed db_printsym to print unsigned.
46 * [90/10/19 rpd]
47 *
48 * Revision 2.3 90/09/09 23:19:56 rpd
49 * Avoid totally incorrect guesses of symbol names for small values.
50 * [90/08/30 17:39:48 af]
51 *
52 * Revision 2.2 90/08/27 21:52:18 dbg
53 * Removed nlist.h. Fixed some type declarations.
54 * Qualifier character is ':'.
55 * [90/08/20 dbg]
56 * Modularized symtab info into a new db_symtab_t type.
57 * Modified db_add_symbol_table and others accordingly.
58 * Defined db_sym_t, a new (opaque) type used to represent
59 * symbols. This should support all sort of future symtable
60 * formats. Functions like db_qualify take a db_sym_t now.
61 * New db_symbol_values() function to explode the content
62 * of a db_sym_t.
63 * db_search_symbol() replaces db_find_sym_and_offset(), which is
64 * now a macro defined in our (new) header file. This new
65 * function accepts more restrictive searches, which are
66 * entirely delegated to the symtab-specific code.
67 * Accordingly, db_printsym() accepts a strategy parameter.
68 * New db_line_at_pc() function.
69 * Renamed misleading db_eqsym into db_eqname.
70 * [90/08/20 10:47:06 af]
71 *
72 * Created.
73 * [90/07/25 dbg]
74 *
75 * Revision 2.1 90/07/26 16:43:52 dbg
76 * Created.
77 *
78 */
79 /*
80 * Author: David B. Golub, Carnegie Mellon University
81 * Date: 7/90
82 */
83 #include "param.h"
84 #include "proc.h"
85 #include <machine/db_machdep.h>
86 #include <ddb/db_sym.h>
87
88 /*
89 * We import from the symbol-table dependent routines:
90 */
91 extern db_sym_t X_db_lookup();
92 extern db_sym_t X_db_search_symbol();
93 extern boolean_t X_db_line_at_pc();
94 extern void X_db_symbol_values();
95
96 /*
97 * Multiple symbol tables
98 */
99 #ifndef MAXLKMS
100 #define MAXLKMS 20
101 #endif
102
103 #ifndef MAXNOSYMTABS
104 #define MAXNOSYMTABS MAXLKMS+1 /* Room for kernel + LKM's */
105 #endif
106
107 db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},};
108
109 db_symtab_t *db_last_symtab;
110
111 db_sym_t db_lookup(); /* forward */
112
113 /*
114 * Add symbol table, with given name, to list of symbol tables.
115 */
116 int
117 db_add_symbol_table(start, end, name, ref)
118 char *start;
119 char *end;
120 char *name;
121 char *ref;
122 {
123 int slot;
124
125 for (slot = 0; slot < MAXNOSYMTABS; slot++) {
126 if (db_symtabs[slot].name == NULL)
127 break;
128 }
129 if (slot >= MAXNOSYMTABS) {
130 printf ("No slots left for %s symbol table", name);
131 return(-1);
132 }
133
134 db_symtabs[slot].start = start;
135 db_symtabs[slot].end = end;
136 db_symtabs[slot].name = name;
137 db_symtabs[slot].private = ref;
138
139 return(slot);
140 }
141
142 /*
143 * Delete a symbol table. Caller is responsible for freeing storage.
144 */
145 void
146 db_del_symbol_table(name)
147 char *name;
148 {
149 int slot;
150
151 for (slot = 0; slot < MAXNOSYMTABS; slot++) {
152 if (db_symtabs[slot].name &&
153 ! strcmp(db_symtabs[slot].name, name))
154 break;
155 }
156 if (slot >= MAXNOSYMTABS) {
157 printf ("Unable to find symbol table slot for %s.", name);
158 return;
159 }
160
161 db_symtabs[slot].start = 0;
162 db_symtabs[slot].end = 0;
163 db_symtabs[slot].name = 0;
164 db_symtabs[slot].private = 0;
165 }
166
167 /*
168 * db_qualify("vm_map", "netbsd") returns "netbsd:vm_map".
169 *
170 * Note: return value points to static data whose content is
171 * overwritten by each call... but in practice this seems okay.
172 */
173 static char *
174 db_qualify(sym, symtabname)
175 db_sym_t sym;
176 register char *symtabname;
177 {
178 char *symname;
179 static char tmp[256];
180 register char *s;
181
182 db_symbol_values(sym, &symname, 0);
183 s = tmp;
184 while (*s++ = *symtabname++) {
185 }
186 s[-1] = ':';
187 while (*s++ = *symname++) {
188 }
189 return tmp;
190 }
191
192
193 boolean_t
194 db_eqname(src, dst, c)
195 char *src;
196 char *dst;
197 char c;
198 {
199 if (!strcmp(src, dst))
200 return (TRUE);
201 if (src[0] == c)
202 return (!strcmp(src+1,dst));
203 return (FALSE);
204 }
205
206 boolean_t
207 db_value_of_name(name, valuep)
208 char *name;
209 db_expr_t *valuep;
210 {
211 db_sym_t sym;
212
213 sym = db_lookup(name);
214 if (sym == DB_SYM_NULL)
215 return (FALSE);
216 db_symbol_values(sym, &name, valuep);
217 return (TRUE);
218 }
219
220
221 /*
222 * Lookup a symbol.
223 * If the symbol has a qualifier (e.g., ux:vm_map),
224 * then only the specified symbol table will be searched;
225 * otherwise, all symbol tables will be searched.
226 */
227 db_sym_t
228 db_lookup(symstr)
229 char *symstr;
230 {
231 db_sym_t sp;
232 register int i;
233 int symtab_start = 0;
234 int symtab_end = MAXNOSYMTABS;
235 register char *cp;
236
237 /*
238 * Look for, remove, and remember any symbol table specifier.
239 */
240 for (cp = symstr; *cp; cp++) {
241 if (*cp == ':') {
242 *cp = '\0';
243 for (i = 0; i < MAXNOSYMTABS; i++) {
244 if (db_symtabs[i].name &&
245 ! strcmp(symstr, db_symtabs[i].name)) {
246 symtab_start = i;
247 symtab_end = i + 1;
248 break;
249 }
250 }
251 *cp = ':';
252 if (i == MAXNOSYMTABS) {
253 db_error("invalid symbol table name");
254 }
255 symstr = cp+1;
256 }
257 }
258
259 /*
260 * Look in the specified set of symbol tables.
261 * Return on first match.
262 */
263 for (i = symtab_start; i < symtab_end; i++) {
264 if (db_symtabs[i].name &&
265 (sp = X_db_lookup(&db_symtabs[i], symstr))) {
266 db_last_symtab = &db_symtabs[i];
267 return sp;
268 }
269 }
270 return 0;
271 }
272
273 /*
274 * Does this symbol name appear in more than one symbol table?
275 * Used by db_symbol_values to decide whether to qualify a symbol.
276 */
277 boolean_t db_qualify_ambiguous_names = FALSE;
278
279 boolean_t
280 db_symbol_is_ambiguous(sym)
281 db_sym_t sym;
282 {
283 char *sym_name;
284 register int i;
285 register
286 boolean_t found_once = FALSE;
287
288 if (!db_qualify_ambiguous_names)
289 return FALSE;
290
291 db_symbol_values(sym, &sym_name, 0);
292 for (i = 0; i < MAXNOSYMTABS; i++) {
293 if (db_symtabs[i].name &&
294 X_db_lookup(&db_symtabs[i], sym_name)) {
295 if (found_once)
296 return TRUE;
297 found_once = TRUE;
298 }
299 }
300 return FALSE;
301 }
302
303 /*
304 * Find the closest symbol to val, and return its name
305 * and the difference between val and the symbol found.
306 */
307 db_sym_t
308 db_search_symbol( val, strategy, offp)
309 register db_addr_t val;
310 db_strategy_t strategy;
311 db_expr_t *offp;
312 {
313 register
314 unsigned int diff;
315 unsigned int newdiff;
316 register int i;
317 db_sym_t ret = DB_SYM_NULL, sym;
318
319 newdiff = diff = ~0;
320 db_last_symtab = 0;
321 for (i = 0; i < MAXNOSYMTABS; i++) {
322 if (!db_symtabs[i].name)
323 continue;
324 sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
325 if (newdiff < diff) {
326 db_last_symtab = &db_symtabs[i];
327 diff = newdiff;
328 ret = sym;
329 }
330 }
331 *offp = diff;
332 return ret;
333 }
334
335 /*
336 * Return name and value of a symbol
337 */
338 void
339 db_symbol_values(sym, namep, valuep)
340 db_sym_t sym;
341 char **namep;
342 db_expr_t *valuep;
343 {
344 db_expr_t value;
345
346 if (sym == DB_SYM_NULL) {
347 *namep = 0;
348 return;
349 }
350
351 X_db_symbol_values(sym, namep, &value);
352
353 if (db_symbol_is_ambiguous(sym))
354 *namep = db_qualify(sym, db_last_symtab->name);
355 if (valuep)
356 *valuep = value;
357 }
358
359
360 /*
361 * Print a the closest symbol to value
362 *
363 * After matching the symbol according to the given strategy
364 * we print it in the name+offset format, provided the symbol's
365 * value is close enough (eg smaller than db_maxoff).
366 * We also attempt to print [filename:linenum] when applicable
367 * (eg for procedure names).
368 *
369 * If we could not find a reasonable name+offset representation,
370 * then we just print the value in hex. Small values might get
371 * bogus symbol associations, e.g. 3 might get some absolute
372 * value like _INCLUDE_VERSION or something, therefore we do
373 * not accept symbols whose value is zero (and use plain hex).
374 */
375
376 unsigned int db_maxoff = 0x10000000;
377
378 void
379 db_printsym(off, strategy)
380 db_expr_t off;
381 db_strategy_t strategy;
382 {
383 db_expr_t d;
384 char *filename;
385 char *name;
386 db_expr_t value;
387 int linenum;
388 db_sym_t cursym;
389
390 cursym = db_search_symbol(off, strategy, &d);
391 db_symbol_values(cursym, &name, &value);
392 if (name == 0 || d >= db_maxoff || value == 0) {
393 db_printf("%#n", off);
394 return;
395 }
396 db_printf("%s", name);
397 if (d)
398 db_printf("+%#r", d);
399 if (strategy == DB_STGY_PROC) {
400 if (db_line_at_pc(cursym, &filename, &linenum, off))
401 db_printf(" [%s:%d]", filename, linenum);
402 }
403 }
404
405
406 boolean_t
407 db_line_at_pc( sym, filename, linenum, pc)
408 db_sym_t sym;
409 char **filename;
410 int *linenum;
411 db_expr_t pc;
412 {
413 return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
414 }
415
416 int
417 db_sym_numargs(sym, nargp, argnames)
418 db_sym_t sym;
419 int *nargp;
420 char **argnames;
421 {
422 return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
423 }
424