db_sym.c revision 1.13 1 1.13 cgd /* $NetBSD: db_sym.c,v 1.13 1997/02/03 19:57:03 cgd Exp $ */
2 1.7 cgd
3 1.1 cgd /*
4 1.1 cgd * Mach Operating System
5 1.1 cgd * Copyright (c) 1991,1990 Carnegie Mellon University
6 1.1 cgd * All Rights Reserved.
7 1.1 cgd *
8 1.1 cgd * Permission to use, copy, modify and distribute this software and its
9 1.1 cgd * documentation is hereby granted, provided that both the copyright
10 1.1 cgd * notice and this permission notice appear in all copies of the
11 1.1 cgd * software, derivative works or modified versions, and any portions
12 1.1 cgd * thereof, and that both notices appear in supporting documentation.
13 1.1 cgd *
14 1.1 cgd * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
15 1.1 cgd * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 1.1 cgd * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 1.1 cgd *
18 1.1 cgd * Carnegie Mellon requests users of this software to return to
19 1.1 cgd *
20 1.1 cgd * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
21 1.1 cgd * School of Computer Science
22 1.1 cgd * Carnegie Mellon University
23 1.1 cgd * Pittsburgh PA 15213-3890
24 1.1 cgd *
25 1.1 cgd * any improvements or extensions that they make and grant Carnegie the
26 1.1 cgd * rights to redistribute these changes.
27 1.1 cgd */
28 1.5 mycroft
29 1.6 mycroft #include <sys/param.h>
30 1.6 mycroft #include <sys/proc.h>
31 1.6 mycroft
32 1.1 cgd #include <machine/db_machdep.h>
33 1.6 mycroft
34 1.1 cgd #include <ddb/db_sym.h>
35 1.12 christos #include <ddb/db_output.h>
36 1.12 christos #include <ddb/db_extern.h>
37 1.12 christos #include <ddb/db_command.h>
38 1.1 cgd
39 1.1 cgd /*
40 1.1 cgd * Multiple symbol tables
41 1.1 cgd */
42 1.4 brezak #ifndef MAXLKMS
43 1.4 brezak #define MAXLKMS 20
44 1.4 brezak #endif
45 1.4 brezak
46 1.3 brezak #ifndef MAXNOSYMTABS
47 1.4 brezak #define MAXNOSYMTABS MAXLKMS+1 /* Room for kernel + LKM's */
48 1.3 brezak #endif
49 1.1 cgd
50 1.1 cgd db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},};
51 1.1 cgd
52 1.1 cgd db_symtab_t *db_last_symtab;
53 1.1 cgd
54 1.12 christos static char *db_qualify __P((db_sym_t, char *));
55 1.1 cgd
56 1.1 cgd /*
57 1.1 cgd * Add symbol table, with given name, to list of symbol tables.
58 1.1 cgd */
59 1.4 brezak int
60 1.1 cgd db_add_symbol_table(start, end, name, ref)
61 1.1 cgd char *start;
62 1.1 cgd char *end;
63 1.1 cgd char *name;
64 1.1 cgd char *ref;
65 1.1 cgd {
66 1.4 brezak int slot;
67 1.4 brezak
68 1.4 brezak for (slot = 0; slot < MAXNOSYMTABS; slot++) {
69 1.4 brezak if (db_symtabs[slot].name == NULL)
70 1.4 brezak break;
71 1.4 brezak }
72 1.4 brezak if (slot >= MAXNOSYMTABS) {
73 1.12 christos db_printf("No slots left for %s symbol table", name);
74 1.4 brezak return(-1);
75 1.1 cgd }
76 1.1 cgd
77 1.4 brezak db_symtabs[slot].start = start;
78 1.4 brezak db_symtabs[slot].end = end;
79 1.4 brezak db_symtabs[slot].name = name;
80 1.4 brezak db_symtabs[slot].private = ref;
81 1.4 brezak
82 1.4 brezak return(slot);
83 1.4 brezak }
84 1.4 brezak
85 1.4 brezak /*
86 1.4 brezak * Delete a symbol table. Caller is responsible for freeing storage.
87 1.4 brezak */
88 1.4 brezak void
89 1.4 brezak db_del_symbol_table(name)
90 1.4 brezak char *name;
91 1.4 brezak {
92 1.4 brezak int slot;
93 1.4 brezak
94 1.4 brezak for (slot = 0; slot < MAXNOSYMTABS; slot++) {
95 1.4 brezak if (db_symtabs[slot].name &&
96 1.4 brezak ! strcmp(db_symtabs[slot].name, name))
97 1.4 brezak break;
98 1.4 brezak }
99 1.4 brezak if (slot >= MAXNOSYMTABS) {
100 1.12 christos db_printf("Unable to find symbol table slot for %s.", name);
101 1.4 brezak return;
102 1.4 brezak }
103 1.4 brezak
104 1.4 brezak db_symtabs[slot].start = 0;
105 1.4 brezak db_symtabs[slot].end = 0;
106 1.4 brezak db_symtabs[slot].name = 0;
107 1.4 brezak db_symtabs[slot].private = 0;
108 1.1 cgd }
109 1.1 cgd
110 1.1 cgd /*
111 1.4 brezak * db_qualify("vm_map", "netbsd") returns "netbsd:vm_map".
112 1.1 cgd *
113 1.1 cgd * Note: return value points to static data whose content is
114 1.1 cgd * overwritten by each call... but in practice this seems okay.
115 1.1 cgd */
116 1.1 cgd static char *
117 1.1 cgd db_qualify(sym, symtabname)
118 1.1 cgd db_sym_t sym;
119 1.1 cgd register char *symtabname;
120 1.1 cgd {
121 1.1 cgd char *symname;
122 1.1 cgd static char tmp[256];
123 1.1 cgd register char *s;
124 1.1 cgd
125 1.1 cgd db_symbol_values(sym, &symname, 0);
126 1.1 cgd s = tmp;
127 1.12 christos while ((*s++ = *symtabname++) != '\0')
128 1.12 christos ;
129 1.1 cgd s[-1] = ':';
130 1.12 christos while ((*s++ = *symname++) != '\0')
131 1.12 christos ;
132 1.1 cgd return tmp;
133 1.1 cgd }
134 1.1 cgd
135 1.1 cgd
136 1.1 cgd boolean_t
137 1.1 cgd db_eqname(src, dst, c)
138 1.1 cgd char *src;
139 1.1 cgd char *dst;
140 1.12 christos int c;
141 1.1 cgd {
142 1.1 cgd if (!strcmp(src, dst))
143 1.1 cgd return (TRUE);
144 1.1 cgd if (src[0] == c)
145 1.1 cgd return (!strcmp(src+1,dst));
146 1.1 cgd return (FALSE);
147 1.1 cgd }
148 1.1 cgd
149 1.1 cgd boolean_t
150 1.1 cgd db_value_of_name(name, valuep)
151 1.1 cgd char *name;
152 1.1 cgd db_expr_t *valuep;
153 1.1 cgd {
154 1.1 cgd db_sym_t sym;
155 1.1 cgd
156 1.1 cgd sym = db_lookup(name);
157 1.1 cgd if (sym == DB_SYM_NULL)
158 1.1 cgd return (FALSE);
159 1.1 cgd db_symbol_values(sym, &name, valuep);
160 1.1 cgd return (TRUE);
161 1.1 cgd }
162 1.1 cgd
163 1.1 cgd
164 1.1 cgd /*
165 1.1 cgd * Lookup a symbol.
166 1.1 cgd * If the symbol has a qualifier (e.g., ux:vm_map),
167 1.1 cgd * then only the specified symbol table will be searched;
168 1.1 cgd * otherwise, all symbol tables will be searched.
169 1.1 cgd */
170 1.1 cgd db_sym_t
171 1.1 cgd db_lookup(symstr)
172 1.1 cgd char *symstr;
173 1.1 cgd {
174 1.1 cgd db_sym_t sp;
175 1.1 cgd register int i;
176 1.1 cgd int symtab_start = 0;
177 1.4 brezak int symtab_end = MAXNOSYMTABS;
178 1.1 cgd register char *cp;
179 1.1 cgd
180 1.1 cgd /*
181 1.1 cgd * Look for, remove, and remember any symbol table specifier.
182 1.1 cgd */
183 1.1 cgd for (cp = symstr; *cp; cp++) {
184 1.1 cgd if (*cp == ':') {
185 1.1 cgd *cp = '\0';
186 1.4 brezak for (i = 0; i < MAXNOSYMTABS; i++) {
187 1.4 brezak if (db_symtabs[i].name &&
188 1.4 brezak ! strcmp(symstr, db_symtabs[i].name)) {
189 1.1 cgd symtab_start = i;
190 1.1 cgd symtab_end = i + 1;
191 1.1 cgd break;
192 1.1 cgd }
193 1.1 cgd }
194 1.1 cgd *cp = ':';
195 1.4 brezak if (i == MAXNOSYMTABS) {
196 1.1 cgd db_error("invalid symbol table name");
197 1.8 mycroft /*NOTREACHED*/
198 1.1 cgd }
199 1.1 cgd symstr = cp+1;
200 1.1 cgd }
201 1.1 cgd }
202 1.1 cgd
203 1.1 cgd /*
204 1.1 cgd * Look in the specified set of symbol tables.
205 1.1 cgd * Return on first match.
206 1.1 cgd */
207 1.1 cgd for (i = symtab_start; i < symtab_end; i++) {
208 1.4 brezak if (db_symtabs[i].name &&
209 1.4 brezak (sp = X_db_lookup(&db_symtabs[i], symstr))) {
210 1.1 cgd db_last_symtab = &db_symtabs[i];
211 1.1 cgd return sp;
212 1.1 cgd }
213 1.1 cgd }
214 1.1 cgd return 0;
215 1.1 cgd }
216 1.1 cgd
217 1.1 cgd /*
218 1.1 cgd * Does this symbol name appear in more than one symbol table?
219 1.1 cgd * Used by db_symbol_values to decide whether to qualify a symbol.
220 1.1 cgd */
221 1.1 cgd boolean_t db_qualify_ambiguous_names = FALSE;
222 1.1 cgd
223 1.1 cgd boolean_t
224 1.1 cgd db_symbol_is_ambiguous(sym)
225 1.1 cgd db_sym_t sym;
226 1.1 cgd {
227 1.1 cgd char *sym_name;
228 1.1 cgd register int i;
229 1.1 cgd register
230 1.1 cgd boolean_t found_once = FALSE;
231 1.1 cgd
232 1.1 cgd if (!db_qualify_ambiguous_names)
233 1.1 cgd return FALSE;
234 1.1 cgd
235 1.1 cgd db_symbol_values(sym, &sym_name, 0);
236 1.4 brezak for (i = 0; i < MAXNOSYMTABS; i++) {
237 1.4 brezak if (db_symtabs[i].name &&
238 1.4 brezak X_db_lookup(&db_symtabs[i], sym_name)) {
239 1.1 cgd if (found_once)
240 1.1 cgd return TRUE;
241 1.1 cgd found_once = TRUE;
242 1.1 cgd }
243 1.1 cgd }
244 1.1 cgd return FALSE;
245 1.1 cgd }
246 1.1 cgd
247 1.1 cgd /*
248 1.1 cgd * Find the closest symbol to val, and return its name
249 1.1 cgd * and the difference between val and the symbol found.
250 1.1 cgd */
251 1.1 cgd db_sym_t
252 1.1 cgd db_search_symbol( val, strategy, offp)
253 1.1 cgd register db_addr_t val;
254 1.1 cgd db_strategy_t strategy;
255 1.1 cgd db_expr_t *offp;
256 1.1 cgd {
257 1.1 cgd register
258 1.1 cgd unsigned int diff;
259 1.13 cgd db_expr_t newdiff;
260 1.1 cgd register int i;
261 1.1 cgd db_sym_t ret = DB_SYM_NULL, sym;
262 1.1 cgd
263 1.1 cgd newdiff = diff = ~0;
264 1.1 cgd db_last_symtab = 0;
265 1.4 brezak for (i = 0; i < MAXNOSYMTABS; i++) {
266 1.4 brezak if (!db_symtabs[i].name)
267 1.4 brezak continue;
268 1.1 cgd sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
269 1.1 cgd if (newdiff < diff) {
270 1.1 cgd db_last_symtab = &db_symtabs[i];
271 1.1 cgd diff = newdiff;
272 1.1 cgd ret = sym;
273 1.1 cgd }
274 1.1 cgd }
275 1.1 cgd *offp = diff;
276 1.1 cgd return ret;
277 1.1 cgd }
278 1.1 cgd
279 1.1 cgd /*
280 1.1 cgd * Return name and value of a symbol
281 1.1 cgd */
282 1.1 cgd void
283 1.1 cgd db_symbol_values(sym, namep, valuep)
284 1.1 cgd db_sym_t sym;
285 1.1 cgd char **namep;
286 1.1 cgd db_expr_t *valuep;
287 1.1 cgd {
288 1.1 cgd db_expr_t value;
289 1.1 cgd
290 1.1 cgd if (sym == DB_SYM_NULL) {
291 1.1 cgd *namep = 0;
292 1.1 cgd return;
293 1.1 cgd }
294 1.1 cgd
295 1.1 cgd X_db_symbol_values(sym, namep, &value);
296 1.1 cgd
297 1.1 cgd if (db_symbol_is_ambiguous(sym))
298 1.1 cgd *namep = db_qualify(sym, db_last_symtab->name);
299 1.1 cgd if (valuep)
300 1.1 cgd *valuep = value;
301 1.1 cgd }
302 1.1 cgd
303 1.1 cgd
304 1.1 cgd /*
305 1.1 cgd * Print a the closest symbol to value
306 1.1 cgd *
307 1.1 cgd * After matching the symbol according to the given strategy
308 1.1 cgd * we print it in the name+offset format, provided the symbol's
309 1.1 cgd * value is close enough (eg smaller than db_maxoff).
310 1.1 cgd * We also attempt to print [filename:linenum] when applicable
311 1.1 cgd * (eg for procedure names).
312 1.1 cgd *
313 1.1 cgd * If we could not find a reasonable name+offset representation,
314 1.1 cgd * then we just print the value in hex. Small values might get
315 1.1 cgd * bogus symbol associations, e.g. 3 might get some absolute
316 1.1 cgd * value like _INCLUDE_VERSION or something, therefore we do
317 1.1 cgd * not accept symbols whose value is zero (and use plain hex).
318 1.9 gwr * Also, avoid printing as "end+0x????" which is useless.
319 1.9 gwr * The variable db_lastsym is used instead of "end" in case we
320 1.9 gwr * add support for symbols in loadable driver modules.
321 1.1 cgd */
322 1.9 gwr extern char end[];
323 1.13 cgd unsigned long db_lastsym = (unsigned long)end;
324 1.13 cgd unsigned int db_maxoff = 0x10000000;
325 1.1 cgd
326 1.9 gwr
327 1.1 cgd void
328 1.1 cgd db_printsym(off, strategy)
329 1.1 cgd db_expr_t off;
330 1.1 cgd db_strategy_t strategy;
331 1.1 cgd {
332 1.1 cgd db_expr_t d;
333 1.1 cgd char *filename;
334 1.1 cgd char *name;
335 1.1 cgd db_expr_t value;
336 1.1 cgd int linenum;
337 1.1 cgd db_sym_t cursym;
338 1.1 cgd
339 1.9 gwr if (off <= db_lastsym) {
340 1.9 gwr cursym = db_search_symbol(off, strategy, &d);
341 1.9 gwr db_symbol_values(cursym, &name, &value);
342 1.9 gwr if (name && (d < db_maxoff) && value) {
343 1.9 gwr db_printf("%s", name);
344 1.9 gwr if (d)
345 1.13 cgd db_printf("+%#lr", d);
346 1.9 gwr if (strategy == DB_STGY_PROC) {
347 1.9 gwr if (db_line_at_pc(cursym, &filename, &linenum, off))
348 1.9 gwr db_printf(" [%s:%d]", filename, linenum);
349 1.9 gwr }
350 1.9 gwr return;
351 1.9 gwr }
352 1.1 cgd }
353 1.13 cgd db_printf("%#ln", off);
354 1.9 gwr return;
355 1.1 cgd }
356 1.1 cgd
357 1.1 cgd
358 1.1 cgd boolean_t
359 1.1 cgd db_line_at_pc( sym, filename, linenum, pc)
360 1.3 brezak db_sym_t sym;
361 1.3 brezak char **filename;
362 1.3 brezak int *linenum;
363 1.3 brezak db_expr_t pc;
364 1.1 cgd {
365 1.1 cgd return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
366 1.3 brezak }
367 1.3 brezak
368 1.3 brezak int
369 1.3 brezak db_sym_numargs(sym, nargp, argnames)
370 1.3 brezak db_sym_t sym;
371 1.3 brezak int *nargp;
372 1.3 brezak char **argnames;
373 1.3 brezak {
374 1.3 brezak return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
375 1.1 cgd }
376