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