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