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