|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1992,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 "AS IS"
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 [email protected]
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 Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * Author: David B. Golub, Carnegie Mellon University
28: * Date: 7/90
29: */
30:
31: #include "mach_kdb.h"
32: #if MACH_KDB
33:
34: #include <mach/std_types.h>
35: #include <kern/strings.h>
36: #include <machine/db_machdep.h>
37: #include <ddb/db_sym.h>
38: #include <ddb/db_task_thread.h>
39:
40: #include <vm/vm_map.h> /* vm_map_t */
41:
42: /*
43: * Multiple symbol tables
44: */
45: #define MAXNOSYMTABS 5 /* mach, bootstrap, ux, emulator, 1 spare */
46:
47: db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},};
48: int db_nsymtab = 0;
49:
50: db_symtab_t *db_last_symtab;
51:
52: db_sym_t db_lookup(); /* forward */
53:
54: /*
55: * Add symbol table, with given name, to list of symbol tables.
56: */
57: boolean_t
58: db_add_symbol_table(type, start, end, name, ref, map_pointer)
59: int type;
60: char *start;
61: char *end;
62: char *name;
63: char *ref;
64: char *map_pointer;
65: {
66: register db_symtab_t *st;
67: extern vm_map_t kernel_map;
68:
69: if (db_nsymtab >= MAXNOSYMTABS)
70: return (FALSE);
71:
72: st = &db_symtabs[db_nsymtab];
73: st->type = type;
74: st->start = start;
75: st->end = end;
76: st->private = ref;
77: st->map_pointer = (map_pointer == (char *)kernel_map)? 0: map_pointer;
78: strcpy(st->name, name);
79:
80: db_nsymtab++;
81:
82: return (TRUE);
83: }
84:
85: /*
86: * db_qualify("vm_map", "ux") returns "ux::vm_map".
87: *
88: * Note: return value points to static data whose content is
89: * overwritten by each call... but in practice this seems okay.
90: */
91: static char *
92: db_qualify(symname, symtabname)
93: char *symname;
94: register char *symtabname;
95: {
96: static char tmp[256];
97: register char *s;
98:
99: s = tmp;
100: while (*s++ = *symtabname++) {
101: }
102: s[-1] = ':';
103: *s++ = ':';
104: while (*s++ = *symname++) {
105: }
106: return tmp;
107: }
108:
109:
110: boolean_t
111: db_eqname( char* src, char* dst, char c )
112: {
113: if (!strcmp(src, dst))
114: return (TRUE);
115: if (src[0] == c)
116: return (!strcmp(src+1,dst));
117: return (FALSE);
118: }
119:
120: boolean_t
121: db_value_of_name(name, valuep)
122: char *name;
123: db_expr_t *valuep;
124: {
125: db_sym_t sym;
126:
127: sym = db_lookup(name);
128: if (sym == DB_SYM_NULL)
129: return (FALSE);
130: db_symbol_values(0, sym, &name, valuep);
131: return (TRUE);
132: }
133:
134: /*
135: * Lookup a symbol.
136: * If the symbol has a qualifier (e.g., ux::vm_map),
137: * then only the specified symbol table will be searched;
138: * otherwise, all symbol tables will be searched.
139: */
140: db_sym_t
141: db_lookup(symstr)
142: char *symstr;
143: {
144: db_sym_t sp;
145: register int i;
146: int symtab_start = 0;
147: int symtab_end = db_nsymtab;
148: register char *cp;
149:
150: /*
151: * Look for, remove, and remember any symbol table specifier.
152: */
153: for (cp = symstr; *cp; cp++) {
154: if (*cp == ':' && cp[1] == ':') {
155: *cp = '\0';
156: for (i = 0; i < db_nsymtab; i++) {
157: if (! strcmp(symstr, db_symtabs[i].name)) {
158: symtab_start = i;
159: symtab_end = i + 1;
160: break;
161: }
162: }
163: *cp = ':';
164: if (i == db_nsymtab)
165: db_error("Invalid symbol table name\n");
166: symstr = cp+2;
167: }
168: }
169:
170: /*
171: * Look in the specified set of symbol tables.
172: * Return on first match.
173: */
174: for (i = symtab_start; i < symtab_end; i++) {
175: if (sp = X_db_lookup(&db_symtabs[i], symstr)) {
176: db_last_symtab = &db_symtabs[i];
177: return sp;
178: }
179: }
180: return 0;
181: }
182:
183: /*
184: * Common utility routine to parse a symbol string into a file
185: * name, a symbol name and line number.
186: * This routine is called from X_db_lookup if the object dependent
187: * handler supports qualified search with a file name or a line number.
188: * It parses the symbol string, and call an object dependent routine
189: * with parsed file name, symbol name and line number.
190: */
191: db_sym_t
192: db_sym_parse_and_lookup(func, symtab, symstr)
193: db_sym_t (*func)();
194: db_symtab_t *symtab;
195: char *symstr;
196: {
197: register char *p;
198: register n;
199: int n_name;
200: int line_number;
201: char *file_name = 0;
202: char *sym_name = 0;
203: char *component[3];
204: db_sym_t found = DB_SYM_NULL;
205:
206: /*
207: * disassemble the symbol into components:
208: * [file_name:]symbol[:line_nubmer]
209: */
210: component[0] = symstr;
211: component[1] = component[2] = 0;
212: for (p = symstr, n = 1; *p; p++) {
213: if (*p == ':') {
214: if (n >= 3)
215: break;
216: *p = 0;
217: component[n++] = p+1;
218: }
219: }
220: if (*p != 0)
221: goto out;
222: line_number = 0;
223: n_name = n;
224: p = component[n-1];
225: if (*p >= '0' && *p <= '9') {
226: if (n == 1)
227: goto out;
228: for (line_number = 0; *p; p++) {
229: if (*p < '0' || *p > '9')
230: goto out;
231: line_number = line_number*10 + *p - '0';
232: }
233: n_name--;
234: } else if (n >= 3)
235: goto out;
236: if (n_name == 1) {
237: for (p = component[0]; *p && *p != '.'; p++);
238: if (*p == '.') {
239: file_name = component[0];
240: sym_name = 0;
241: } else {
242: file_name = 0;
243: sym_name = component[0];
244: }
245: } else {
246: file_name = component[0];
247: sym_name = component[1];
248: }
249: found = func(symtab, file_name, sym_name, line_number);
250:
251: out:
252: while (--n >= 1)
253: component[n][-1] = ':';
254: return(found);
255: }
256:
257: /*
258: * Does this symbol name appear in more than one symbol table?
259: * Used by db_symbol_values to decide whether to qualify a symbol.
260: */
261: boolean_t db_qualify_ambiguous_names = FALSE;
262:
263: boolean_t
264: db_name_is_ambiguous(sym_name)
265: char *sym_name;
266: {
267: register int i;
268: register
269: boolean_t found_once = FALSE;
270:
271: if (!db_qualify_ambiguous_names)
272: return FALSE;
273:
274: for (i = 0; i < db_nsymtab; i++) {
275: if (X_db_lookup(&db_symtabs[i], sym_name)) {
276: if (found_once)
277: return TRUE;
278: found_once = TRUE;
279: }
280: }
281: return FALSE;
282: }
283:
284:
285: db_sym_t db_search_in_task_symbol();
286:
287: /*
288: * Find the closest symbol to val, and return its name
289: * and the difference between val and the symbol found.
290: *
291: * Logic change. If the task argument is non NULL and a
292: * matching symbol is found in a symbol table which explictly
293: * specifies its map to be task->map, that symbol will have
294: * precedence over any symbol from a symbol table will a null
295: * map. This allows overlapping kernel/user maps to work correctly.
296: *
297: */
298: db_sym_t
299: db_search_task_symbol(val, strategy, offp, task)
300: register db_addr_t val;
301: db_strategy_t strategy;
302: db_addr_t *offp; /* better be unsigned */
303: task_t task;
304: {
305: db_sym_t ret;
306:
307: if (task != TASK_NULL)
308: ret = db_search_in_task_symbol(val, strategy, offp, task);
309: else
310: {
311: ret = db_search_in_task_symbol(val, strategy, offp, task);
312: /*
313: db_search_in_task_symbol will return success with
314: a very large offset when it should have failed.
315: */
316: if (ret == DB_SYM_NULL || (*offp) > 0x1000000)
317: {
318: task = db_current_task();
319: ret = db_search_in_task_symbol(val, strategy, offp, task);
320: }
321: }
322:
323: return ret;
324: }
325:
326: db_sym_t
327: db_search_in_task_symbol(val, strategy, offp, task)
328: register db_addr_t val;
329: db_strategy_t strategy;
330: db_addr_t *offp;
331: task_t task;
332: {
333: register vm_size_t diff;
334: vm_size_t newdiff;
335: register int i;
336: db_symtab_t *sp;
337: db_sym_t ret = DB_SYM_NULL, sym;
338: vm_map_t map_for_val;
339:
340: map_for_val = (task == TASK_NULL)? VM_MAP_NULL: task->map;
341: newdiff = diff = ~0;
342: db_last_symtab = (db_symtab_t *) 0;
343: for (sp = &db_symtabs[0], i = 0; i < db_nsymtab; sp++, i++)
344: {
345: newdiff = ~0;
346: if ((vm_map_t)sp->map_pointer == VM_MAP_NULL ||
347: (vm_map_t)sp->map_pointer == map_for_val)
348: {
349: sym = X_db_search_symbol(sp, val, strategy, (db_expr_t*)&newdiff);
350: if (sym == DB_SYM_NULL)
351: continue;
352: if (db_last_symtab == (db_symtab_t *) 0)
353: { /* first hit */
354: db_last_symtab = sp;
355: diff = newdiff;
356: ret = sym;
357: continue;
358: }
359: if ((vm_map_t) sp->map_pointer == VM_MAP_NULL &&
360: (vm_map_t) db_last_symtab->map_pointer == VM_MAP_NULL &&
361: newdiff < diff )
362: { /* closer null map match */
363: db_last_symtab = sp;
364: diff = newdiff;
365: ret = sym;
366: continue;
367: }
368: if ((vm_map_t) sp->map_pointer != VM_MAP_NULL &&
369: (newdiff < 0x100000) &&
370: ((vm_map_t) db_last_symtab->map_pointer == VM_MAP_NULL ||
371: newdiff < diff ))
372: { /* update if new is in matching map and symbol is "close",
373: and
374: old is VM_MAP_NULL or old in is matching map but is further away
375: */
376: db_last_symtab = sp;
377: diff = newdiff;
378: ret = sym;
379: continue;
380: }
381: }
382: }
383:
384: *offp = diff;
385: return ret;
386: }
387:
388: /*
389: * Return name and value of a symbol
390: */
391: void
392: db_symbol_values(stab, sym, namep, valuep)
393: db_symtab_t *stab;
394: db_sym_t sym;
395: char **namep;
396: db_expr_t *valuep;
397: {
398: db_expr_t value;
399: char *name;
400:
401: if (sym == DB_SYM_NULL) {
402: *namep = 0;
403: return;
404: }
405: if (stab == 0)
406: stab = db_last_symtab;
407:
408: X_db_symbol_values(stab, sym, &name, &value);
409:
410: if (db_name_is_ambiguous(name))
411: *namep = db_qualify(name, db_last_symtab->name);
412: else
413: *namep = name;
414: if (valuep)
415: *valuep = value;
416: }
417:
418:
419: /*
420: * Print the closest symbol to value
421: *
422: * After matching the symbol according to the given strategy
423: * we print it in the name+offset format, provided the symbol's
424: * value is close enough (eg smaller than db_maxoff).
425: * We also attempt to print [filename:linenum] when applicable
426: * (eg for procedure names).
427: *
428: * If we could not find a reasonable name+offset representation,
429: * then we just print the value in hex. Small values might get
430: * bogus symbol associations, e.g. 3 might get some absolute
431: * value like _INCLUDE_VERSION or something, therefore we do
432: * not accept symbols whose value is zero (and use plain hex).
433: */
434:
435: unsigned int db_maxoff = 0x4000;
436:
437: void
438: db_task_printsym(off, strategy, task)
439: db_expr_t off;
440: db_strategy_t strategy;
441: task_t task;
442: {
443: db_addr_t d;
444: char *filename;
445: char *name;
446: db_expr_t value;
447: int linenum;
448: db_sym_t cursym;
449:
450: cursym = db_search_task_symbol(off, strategy, &d, task);
451: db_symbol_values(0, cursym, &name, &value);
452: if (name == 0 || d >= db_maxoff || value == 0) {
453: db_printf("%#n", off);
454: return;
455: }
456: db_printf("%s", name);
457: if (d)
458: db_printf("+0x%x", d);
459: if (strategy == DB_STGY_PROC) {
460: if (db_line_at_pc(cursym, &filename, &linenum, off)) {
461: db_printf(" [%s", filename);
462: if (linenum > 0)
463: db_printf(":%d", linenum);
464: db_printf("]");
465: }
466: }
467: }
468:
469: void
470: db_printsym(off, strategy)
471: db_expr_t off;
472: db_strategy_t strategy;
473: {
474: db_task_printsym(off, strategy, TASK_NULL);
475: }
476:
477: boolean_t
478: db_line_at_pc( sym, filename, linenum, pc)
479: db_sym_t sym;
480: char **filename;
481: int *linenum;
482: db_expr_t pc;
483: {
484: return (db_last_symtab) ?
485: X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc) :
486: FALSE;
487: }
488:
489: /*
490: * Switch into symbol-table specific routines
491: */
492:
493: extern boolean_t aout_db_sym_init(), aout_db_line_at_pc();
494: extern db_sym_t aout_db_lookup(), aout_db_search_symbol();
495: extern void aout_db_symbol_values();
496:
497: extern boolean_t coff_db_sym_init(), coff_db_line_at_pc();
498: extern db_sym_t coff_db_lookup(), coff_db_search_symbol();
499: extern void coff_db_symbol_values();
500:
501: struct db_sym_switch x_db[] = {
502:
503: /* BSD a.out format (really, sdb/dbx(1) symtabs) */
504: #ifdef DB_NO_AOUT
505: { 0,},
506: #else /* DB_NO_AOUT */
507: { aout_db_sym_init, aout_db_lookup, aout_db_search_symbol,
508: aout_db_line_at_pc, aout_db_symbol_values },
509: #endif /* DB_NO_AOUT */
510:
511: #ifdef DB_NO_COFF
512: { 0,},
513: #else /* DB_NO_COFF */
514: { coff_db_sym_init, coff_db_lookup, coff_db_search_symbol,
515: coff_db_line_at_pc, coff_db_symbol_values },
516: #endif /* DB_NO_COFF */
517:
518: /* Machdep, not inited here */
519: { 0,}
520:
521: };
522:
523: #endif MACH_KDB
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.