db_sym.c revision 1.6 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.6 1993/12/18 04:46:39 mycroft Exp $
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 }
203 symstr = cp+1;
204 }
205 }
206
207 /*
208 * Look in the specified set of symbol tables.
209 * Return on first match.
210 */
211 for (i = symtab_start; i < symtab_end; i++) {
212 if (db_symtabs[i].name &&
213 (sp = X_db_lookup(&db_symtabs[i], symstr))) {
214 db_last_symtab = &db_symtabs[i];
215 return sp;
216 }
217 }
218 return 0;
219 }
220
221 /*
222 * Does this symbol name appear in more than one symbol table?
223 * Used by db_symbol_values to decide whether to qualify a symbol.
224 */
225 boolean_t db_qualify_ambiguous_names = FALSE;
226
227 boolean_t
228 db_symbol_is_ambiguous(sym)
229 db_sym_t sym;
230 {
231 char *sym_name;
232 register int i;
233 register
234 boolean_t found_once = FALSE;
235
236 if (!db_qualify_ambiguous_names)
237 return FALSE;
238
239 db_symbol_values(sym, &sym_name, 0);
240 for (i = 0; i < MAXNOSYMTABS; i++) {
241 if (db_symtabs[i].name &&
242 X_db_lookup(&db_symtabs[i], sym_name)) {
243 if (found_once)
244 return TRUE;
245 found_once = TRUE;
246 }
247 }
248 return FALSE;
249 }
250
251 /*
252 * Find the closest symbol to val, and return its name
253 * and the difference between val and the symbol found.
254 */
255 db_sym_t
256 db_search_symbol( val, strategy, offp)
257 register db_addr_t val;
258 db_strategy_t strategy;
259 db_expr_t *offp;
260 {
261 register
262 unsigned int diff;
263 unsigned int newdiff;
264 register int i;
265 db_sym_t ret = DB_SYM_NULL, sym;
266
267 newdiff = diff = ~0;
268 db_last_symtab = 0;
269 for (i = 0; i < MAXNOSYMTABS; i++) {
270 if (!db_symtabs[i].name)
271 continue;
272 sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
273 if (newdiff < diff) {
274 db_last_symtab = &db_symtabs[i];
275 diff = newdiff;
276 ret = sym;
277 }
278 }
279 *offp = diff;
280 return ret;
281 }
282
283 /*
284 * Return name and value of a symbol
285 */
286 void
287 db_symbol_values(sym, namep, valuep)
288 db_sym_t sym;
289 char **namep;
290 db_expr_t *valuep;
291 {
292 db_expr_t value;
293
294 if (sym == DB_SYM_NULL) {
295 *namep = 0;
296 return;
297 }
298
299 X_db_symbol_values(sym, namep, &value);
300
301 if (db_symbol_is_ambiguous(sym))
302 *namep = db_qualify(sym, db_last_symtab->name);
303 if (valuep)
304 *valuep = value;
305 }
306
307
308 /*
309 * Print a the closest symbol to value
310 *
311 * After matching the symbol according to the given strategy
312 * we print it in the name+offset format, provided the symbol's
313 * value is close enough (eg smaller than db_maxoff).
314 * We also attempt to print [filename:linenum] when applicable
315 * (eg for procedure names).
316 *
317 * If we could not find a reasonable name+offset representation,
318 * then we just print the value in hex. Small values might get
319 * bogus symbol associations, e.g. 3 might get some absolute
320 * value like _INCLUDE_VERSION or something, therefore we do
321 * not accept symbols whose value is zero (and use plain hex).
322 */
323
324 unsigned int db_maxoff = 0x10000000;
325
326 void
327 db_printsym(off, strategy)
328 db_expr_t off;
329 db_strategy_t strategy;
330 {
331 db_expr_t d;
332 char *filename;
333 char *name;
334 db_expr_t value;
335 int linenum;
336 db_sym_t cursym;
337
338 cursym = db_search_symbol(off, strategy, &d);
339 db_symbol_values(cursym, &name, &value);
340 if (name == 0 || d >= db_maxoff || value == 0) {
341 db_printf("%#n", off);
342 return;
343 }
344 db_printf("%s", name);
345 if (d)
346 db_printf("+%#r", d);
347 if (strategy == DB_STGY_PROC) {
348 if (db_line_at_pc(cursym, &filename, &linenum, off))
349 db_printf(" [%s:%d]", filename, linenum);
350 }
351 }
352
353
354 boolean_t
355 db_line_at_pc( sym, filename, linenum, pc)
356 db_sym_t sym;
357 char **filename;
358 int *linenum;
359 db_expr_t pc;
360 {
361 return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
362 }
363
364 int
365 db_sym_numargs(sym, nargp, argnames)
366 db_sym_t sym;
367 int *nargp;
368 char **argnames;
369 {
370 return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
371 }
372