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