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