|
|
1.1.1.2 root 1: /*
1.1 root 2: * Mach Operating System
3: * Copyright (c) 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: */
1.1.1.3 root 30:
1.1 root 31: #if MACH_KDB
32:
33: /*
34: * Symbol table routines for a.out format files.
35: */
36:
1.1.1.3 root 37: #include <string.h>
1.1 root 38: #include <mach/std_types.h>
39: #include <machine/db_machdep.h> /* data types */
1.1.1.3 root 40: #include <ddb/db_output.h>
1.1 root 41: #include <ddb/db_sym.h>
1.1.1.4 ! root 42: #include <ddb/db_aout.h>
1.1 root 43:
44: #ifndef DB_NO_AOUT
45:
46: #include <ddb/nlist.h> /* a.out symbol table */
47: #include <ddb/stab.h>
48:
49: #define private static
50:
51: /*
52: * An a.out symbol table as loaded into the kernel debugger:
53: *
54: * symtab -> size of symbol entries, in bytes
55: * sp -> first symbol entry
56: * ...
57: * ep -> last symbol entry + 1
58: * strtab == start of string table
59: * size of string table in bytes,
60: * including this word
61: * -> strings
62: */
63:
64: /*
65: * Find pointers to the start and end of the symbol entries,
66: * given a pointer to the start of the symbol table.
67: */
68: #define db_get_aout_symtab(symtab, sp, ep) \
69: (sp = (struct nlist *)((vm_offset_t *)(symtab) + 1), \
70: ep = (struct nlist *)((char *)sp + *((int*)symtab)))
71:
72: boolean_t
1.1.1.4 ! root 73: aout_db_sym_init(
! 74: char * symtab, /* pointer to start of symbol table */
! 75: char * esymtab, /* pointer to end of string table,
1.1 root 76: for checking - may be rounded up to
77: integer boundary */
1.1.1.4 ! root 78: char * name,
! 79: char * task_addr) /* use for this task only */
1.1 root 80: {
1.1.1.4 ! root 81: struct nlist *sym_start, *sym_end;
! 82: struct nlist *sp;
! 83: char * strtab;
! 84: int strlen;
1.1 root 85: char * estrtab;
86:
87: db_get_aout_symtab(symtab, sym_start, sym_end);
88:
89: strtab = (char *)sym_end;
90: strlen = *(int *)strtab;
91: estrtab = strtab + strlen;
92:
93: #define round_to_size(x) \
94: (((vm_offset_t)(x) + sizeof(vm_size_t) - 1) & ~(sizeof(vm_size_t) - 1))
95:
96: if (round_to_size(estrtab) != round_to_size(esymtab)) {
97: db_printf("[ %s symbol table not valid ]\n", name);
98: return (FALSE);
99: }
100:
101: #undef round_to_size
102:
103: for (sp = sym_start; sp < sym_end; sp++) {
1.1.1.4 ! root 104: long strx;
1.1 root 105: strx = sp->n_un.n_strx;
106: if (strx != 0) {
107: if (strx > strlen) {
108: db_printf("Bad string table index (%#x)\n", strx);
109: sp->n_un.n_name = 0;
110: continue;
111: }
112: sp->n_un.n_name = strtab + strx;
113: }
114: }
115:
116: if (db_add_symbol_table(SYMTAB_AOUT,
117: (char *)sym_start,
118: (char *)sym_end,
119: name,
120: symtab,
121: task_addr))
122: {
123: /* Successfully added symbol table */
124: db_printf("[ preserving %d bytes of %s symbol table ]\n",
125: esymtab - (char *)symtab, name);
126: return TRUE;
127: }
128: else
129: return FALSE;
130: }
131:
132: /*
133: * check file name or not (check xxxx.x pattern)
134: */
1.1.1.4 ! root 135: private boolean_t __attribute__ ((pure))
1.1 root 136: aout_db_is_filename(name)
1.1.1.4 ! root 137: const char *name;
1.1 root 138: {
139: while (*name) {
140: if (*name == '.') {
141: if (name[1])
142: return(TRUE);
143: }
144: name++;
145: }
146: return(FALSE);
147: }
148:
149: /*
150: * special name comparison routine with a name in the symbol table entry
151: */
1.1.1.4 ! root 152: private boolean_t __attribute__ ((pure))
1.1 root 153: aout_db_eq_name(sp, name)
1.1.1.4 ! root 154: const struct nlist *sp;
! 155: const char *name;
1.1 root 156: {
1.1.1.4 ! root 157: const char *s1, *s2;
1.1 root 158:
159: s1 = sp->n_un.n_name;
160: s2 = name;
161: if (*s1 == '_' && *s2 && *s2 != '_')
162: s1++;
163: while (*s2) {
164: if (*s1++ != *s2++) {
165: /*
166: * check .c .o file name comparison case
167: */
1.1.1.2 root 168: if (*s2 == 0 && sp->n_un.n_name <= s1 - 2
1.1 root 169: && s1[-2] == '.' && s1[-1] == 'o')
170: return(TRUE);
171: return(FALSE);
172: }
173: }
174: /*
175: * do special check for
176: * xxx:yyy for N_FUN
177: * xxx.ttt for N_DATA and N_BSS
178: */
1.1.1.2 root 179: return(*s1 == 0 || (*s1 == ':' && sp->n_type == N_FUN) ||
1.1 root 180: (*s1 == '.' && (sp->n_type == N_DATA || sp->n_type == N_BSS)));
181: }
182:
183: /*
184: * search a symbol table with name and type
185: * fp(in,out): last found text file name symbol entry
186: */
187: private struct nlist *
188: aout_db_search_name(sp, ep, name, type, fp)
1.1.1.4 ! root 189: struct nlist *sp;
! 190: const struct nlist *ep;
! 191: const char *name;
! 192: int type;
! 193: struct nlist **fp;
1.1 root 194: {
195: struct nlist *file_sp = *fp;
196: struct nlist *found_sp = 0;
197:
198: for ( ; sp < ep; sp++) {
199: if (sp->n_type == N_TEXT && aout_db_is_filename(sp->n_un.n_name))
200: *fp = sp;
201: if (type) {
202: if (sp->n_type == type) {
203: if (aout_db_eq_name(sp, name))
204: return(sp);
205: }
206: if (sp->n_type == N_SO)
207: *fp = sp;
208: continue;
209: }
210: if (sp->n_type & N_STAB)
211: continue;
212: if (sp->n_un.n_name && aout_db_eq_name(sp, name)) {
213: /*
214: * In case of qaulified search by a file,
215: * return it immediately with some check.
216: * Otherwise, search external one
217: */
218: if (file_sp) {
219: if ((file_sp == *fp) || (sp->n_type & N_EXT))
220: return(sp);
221: } else if (sp->n_type & N_EXT)
222: return(sp);
223: else
224: found_sp = sp;
225: }
226: }
227: return(found_sp);
228: }
229:
230: /*
231: * search a symbol with file, func and line qualification
232: */
233: private db_sym_t
234: aout_db_qualified_search(stab, file, sym, line)
235: db_symtab_t *stab;
1.1.1.4 ! root 236: const char *file;
! 237: const char *sym;
1.1 root 238: int line;
239: {
1.1.1.4 ! root 240: struct nlist *sp = (struct nlist *)stab->start;
1.1 root 241: struct nlist *ep = (struct nlist *)stab->end;
242: struct nlist *fp = 0;
243: struct nlist *found_sp;
244: unsigned long func_top;
245: boolean_t in_file;
246:
247: if (file == 0 && sym == 0)
1.1.1.4 ! root 248: return(DB_SYM_NULL);
1.1 root 249: if (file) {
250: if ((sp = aout_db_search_name(sp, ep, file, N_TEXT, &fp)) == 0)
1.1.1.4 ! root 251: return(DB_SYM_NULL);
1.1 root 252: }
253: if (sym) {
254: sp = aout_db_search_name(sp, ep, sym, (line > 0)? N_FUN: 0, &fp);
255: if (sp == 0)
1.1.1.4 ! root 256: return(DB_SYM_NULL);
1.1 root 257: }
258: if (line > 0) {
259: if (file && !aout_db_eq_name(fp, file))
1.1.1.4 ! root 260: return(DB_SYM_NULL);
1.1 root 261: found_sp = 0;
262: if (sp->n_type == N_FUN) {
263: /*
264: * qualified by function name
265: * search backward because line number entries
266: * for the function are above it in this case.
267: */
268: func_top = sp->n_value;
269: for (sp--; sp >= (struct nlist *)stab->start; sp--) {
270: if (sp->n_type != N_SLINE)
271: continue;
272: if (sp->n_value < func_top)
273: break;
274: if (sp->n_desc <= line) {
275: if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
276: found_sp = sp;
277: if (sp->n_desc == line)
278: break;
279: }
280: }
281: if (sp->n_type != N_SLINE || sp->n_value < func_top)
1.1.1.4 ! root 282: return(DB_SYM_NULL);
1.1 root 283: } else {
284: /*
285: * qualified by only file name
286: * search forward in this case
287: */
288: in_file = TRUE;
289: for (sp++; sp < ep; sp++) {
1.1.1.2 root 290: if (sp->n_type == N_TEXT
1.1 root 291: && aout_db_is_filename(sp->n_un.n_name))
292: break; /* enter into another file */
293: if (sp->n_type == N_SOL) {
294: in_file = aout_db_eq_name(sp, file);
295: continue;
296: }
297: if (!in_file || sp->n_type != N_SLINE)
298: continue;
299: if (sp->n_desc <= line) {
300: if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
301: found_sp = sp;
302: if (sp->n_desc == line)
303: break;
304: }
305: }
306: }
307: sp = found_sp;
308: }
309: return((db_sym_t) sp);
310: }
311:
312: /*
313: * lookup symbol by name
314: */
315: db_sym_t
1.1.1.4 ! root 316: aout_db_lookup(
! 317: db_symtab_t *stab,
! 318: char * symstr)
1.1 root 319: {
320: return(db_sym_parse_and_lookup(aout_db_qualified_search, stab, symstr));
321: }
322:
323: db_sym_t
1.1.1.4 ! root 324: aout_db_search_symbol(
! 325: db_symtab_t * symtab,
! 326: db_addr_t off,
! 327: db_strategy_t strategy,
! 328: db_expr_t *diffp) /* in/out */
1.1 root 329: {
1.1.1.4 ! root 330: unsigned long diff = *diffp;
! 331: struct nlist *symp = 0;
! 332: struct nlist *sp, *ep;
1.1 root 333:
334: sp = (struct nlist *)symtab->start;
335: ep = (struct nlist *)symtab->end;
336:
337: for (; sp < ep; sp++) {
338: if (sp->n_un.n_name == 0)
339: continue;
340: if ((sp->n_type & N_STAB) != 0)
341: continue;
342: if (strategy == DB_STGY_XTRN && (sp->n_type & N_EXT) == 0)
343: continue;
344: if (off >= sp->n_value) {
345:
346: unsigned int type = sp->n_type;
347:
348: if (type == N_FN) continue;
349: if (off - sp->n_value < diff) {
350: diff = off - sp->n_value;
351: symp = sp;
352: if (diff == 0 && (type & N_EXT))
353: break;
354: }
355: else if (off - sp->n_value == diff) {
356: if (symp == 0)
357: symp = sp;
358: else if ((symp->n_type & N_EXT) == 0 &&
359: (type & N_EXT) != 0)
360: symp = sp; /* pick the external symbol */
361: }
362: }
363: }
364: if (symp == 0) {
365: *diffp = off;
366: }
367: else {
368: *diffp = diff;
369: }
370: return ((db_sym_t)symp);
371: }
372:
373: /*
374: * Return the name and value for a symbol.
375: */
376: void
1.1.1.4 ! root 377: aout_db_symbol_values(
! 378: db_symtab_t *stab,
! 379: db_sym_t sym,
! 380: char **namep,
! 381: db_expr_t *valuep)
1.1 root 382: {
1.1.1.4 ! root 383: struct nlist *sp;
1.1 root 384:
385: sp = (struct nlist *)sym;
386: if (namep)
387: *namep = sp->n_un.n_name;
388: if (valuep)
389: *valuep = sp->n_value;
390: }
391:
392: #define X_DB_MAX_DIFF 8 /* maximum allowable diff at the end of line */
393:
394: /*
395: * search symbol by value
396: */
397: private boolean_t
398: aout_db_search_by_addr(stab, addr, file, func, line, diff)
1.1.1.4 ! root 399: const db_symtab_t *stab;
! 400: vm_offset_t addr;
! 401: char **file;
! 402: char **func;
! 403: int *line;
! 404: unsigned long *diff;
1.1 root 405: {
1.1.1.4 ! root 406: struct nlist *sp;
! 407: struct nlist *line_sp, *func_sp, *file_sp, *line_func;
! 408: vm_size_t func_diff, line_diff;
1.1 root 409: boolean_t found_line = FALSE;
410: struct nlist *ep = (struct nlist *)stab->end;
411:
412: line_sp = func_sp = file_sp = line_func = 0;
413: *file = *func = 0;
414: *line = 0;
415: func_diff = line_diff = ~0;
416: for (sp = (struct nlist *)stab->start; sp < ep; sp++) {
417: switch(sp->n_type) {
418: case N_SLINE:
419: if (sp->n_value <= addr) {
420: if (line_sp == 0 || line_diff >= addr - sp->n_value) {
421: if (line_func)
422: line_func = 0;
423: line_sp = sp;
424: line_diff = addr - sp->n_value;
425: }
426: }
427: if (sp->n_value >= addr && line_sp)
428: found_line = TRUE;
429: continue;
430: case N_FUN:
431: if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF))
432: && line_func == 0)
433: line_func = sp;
434: continue;
435: case N_SO:
436: if (sp->n_value > addr)
437: continue;
438: if (file_sp == 0 || file_sp->n_value <= sp->n_value)
439: file_sp = sp;
440: continue;
441: case N_TEXT:
442: if (aout_db_is_filename(sp->n_un.n_name)) {
443: if (sp->n_value > addr)
444: continue;
445: if (file_sp == 0 || file_sp->n_value <= sp->n_value)
446: file_sp = sp;
447: } else if (sp->n_value <= addr &&
448: (func_sp == 0 || func_diff > addr - sp->n_value)) {
449: func_sp = sp;
450: func_diff = addr - sp->n_value;
451: }
452: continue;
453: case N_TEXT|N_EXT:
454: if (sp->n_value <= addr &&
455: (func_sp == 0 || func_diff >= addr - sp->n_value)) {
456: func_sp = sp;
457: func_diff = addr - sp->n_value;
458: if (func_diff == 0 && file_sp && func_sp)
459: break;
460: }
461: default:
462: continue;
463: }
464: break;
465: }
466: if (line_sp) {
467: if (line_func == 0 || func_sp == 0
468: || line_func->n_value != func_sp->n_value)
469: line_sp = 0;
470: }
471: if (file_sp) {
472: *diff = addr - file_sp->n_value;
473: *file = file_sp->n_un.n_name;
474: }
475: if (func_sp) {
476: *diff = addr - func_sp->n_value;
477: *func = (func_sp->n_un.n_name[0] == '_')?
478: func_sp->n_un.n_name + 1: func_sp->n_un.n_name;
479: }
480: if (line_sp) {
481: *diff = addr - line_sp->n_value;
482: *line = line_sp->n_desc;
483: }
484: return(file_sp || func_sp || line_sp);
485: }
486:
487: /*
488: * Find filename and lineno within, given the current pc.
489: */
490: boolean_t
491: aout_db_line_at_pc(stab, sym, file, line, pc)
492: db_symtab_t *stab;
493: db_sym_t sym;
494: char **file;
495: int *line;
1.1.1.4 ! root 496: db_addr_t pc;
1.1 root 497: {
498: char *func;
499: unsigned long diff;
500: boolean_t found;
501:
1.1.1.4 ! root 502: found = aout_db_search_by_addr(stab, pc, file, &func, line, &diff);
1.1 root 503: return(found && func && *file);
504: }
505:
506: #endif /* DB_NO_AOUT */
507:
1.1.1.2 root 508: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.