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