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