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