|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * COPYRIGHT NOTICE
24: *
25: * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
26: *
27: * Permission is hereby granted to use, copy, modify and freely distribute
28: * the software in this file and its documentation for any purpose without
29: * fee, provided that the above copyright notice appears in all copies and
30: * that both the copyright notice and this permission notice appear in
31: * supporting documentation. Further, provided that the name of Open
32: * Software Foundation, Inc. ("OSF") not be used in advertising or
33: * publicity pertaining to distribution of the software without prior
34: * written permission from OSF. OSF makes no representations about the
35: * suitability of this software for any purpose. It is provided "as is"
36: * without express or implied warranty.
37: */
38: /*
39: * HISTORY
40: *
41: * Revision 1.1.1.1 1998/09/22 21:05:36 wsanchez
42: * Import of Mac OS X kernel (~semeria)
43: *
44: * Revision 1.1.1.1 1998/03/07 02:25:37 wsanchez
45: * Import of OSF Mach kernel (~mburg)
46: *
47: * Revision 1.2.2.3 1994/01/28 17:23:00 chasb
48: * Expand Copyrights
49: * [1994/01/27 19:40:16 chasb]
50: *
51: * Revision 1.2.2.2 1993/06/09 02:27:36 gm
52: * Added to OSF/1 R1.3 from NMK15.0.
53: * [1993/06/02 21:04:03 jeffc]
54: *
55: * Revision 1.2 1993/04/19 16:13:10 devrcs
56: * pick up file_io.h from bootstrap directory
57: * [1993/02/27 15:01:09 david]
58: *
59: * Added new arguments and a missing one to db_add_symbol_table
60: * [[email protected]]
61: * [92/12/03 bernadat]
62: *
63: * Added gcc symbol table handling based on db_aout.c (Revsion 2.4)
64: * [91/07/31 tak]
65: *
66: * Revision 1.1 1992/09/30 02:02:23 robert
67: * Initial revision
68: *
69: * $EndLog$
70: */
71: /* CMU_HIST */
72: /*
73: * Revision 2.1 91/07/31 13:13:51 jeffreyh
74: * Created.
75: *
76: * 31-Jul-91 Jeffrey Heller (tak) at Open Software Foundation
77: * Added gcc symbol table handling based on db_aout.c (Revsion 2.4)
78: *
79: */
80: /* CMU_ENDHIST */
81: /*
82: * Mach Operating System
83: * Copyright (c) 1991,1990 Carnegie Mellon University
84: * All Rights Reserved.
85: *
86: * Permission to use, copy, modify and distribute this software and its
87: * documentation is hereby granted, provided that both the copyright
88: * notice and this permission notice appear in all copies of the
89: * software, derivative works or modified versions, and any portions
90: * thereof, and that both notices appear in supporting documentation.
91: *
92: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
93: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
94: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
95: *
96: * Carnegie Mellon requests users of this software to return to
97: *
98: * Software Distribution Coordinator or [email protected]
99: * School of Computer Science
100: * Carnegie Mellon University
101: * Pittsburgh PA 15213-3890
102: *
103: * any improvements or extensions that they make and grant Carnegie Mellon
104: * the rights to redistribute these changes.
105: */
106: /*
107: */
108: /*
109: * Symbol table routines for a.out format files.
110: */
111:
112: #include <mach/boolean.h>
113: #include <machine/db_machdep.h> /* data types */
114: #include <ddb/db_sym.h>
115:
116: #ifdef DB_GCC_AOUT
117:
118: #include <ddb/nlist.h> /* a.out symbol table */
119: #include <i386/stab.h>
120:
121: /*
122: * An a.out symbol table as loaded into the kernel debugger:
123: *
124: * symtab -> size of symbol entries, in bytes
125: * sp -> first symbol entry
126: * ...
127: * ep -> last symbol entry + 1
128: * strtab == start of string table
129: * size of string table in bytes,
130: * including this word
131: * -> strings
132: */
133:
134: /*
135: * Find pointers to the start and end of the symbol entries,
136: * given a pointer to the start of the symbol table.
137: */
138: #define db_get_aout_symtab(symtab, sp, ep) \
139: (sp = (struct nlist *)((symtab) + 1), \
140: ep = (struct nlist *)((char *)sp + *(symtab)))
141:
142: X_db_sym_init(symtab, esymtab, name)
143: int * symtab; /* pointer to start of symbol table */
144: char * esymtab; /* pointer to end of string table,
145: for checking - rounded up to integer
146: boundary */
147: char * name;
148: {
149: register struct nlist *sym_start, *sym_end;
150: register struct nlist *sp;
151: register char * strtab;
152: register int strlen;
153:
154: db_get_aout_symtab(symtab, sym_start, sym_end);
155:
156: strtab = (char *)sym_end;
157: strlen = *(int *)strtab;
158:
159: if (strtab + ((strlen + sizeof(int) - 1) & ~(sizeof(int)-1))
160: != esymtab)
161: {
162: db_printf("[ %s symbol table not valid ]\n", name);
163: return;
164: }
165:
166: db_printf("[ preserving %#x bytes of %s symbol table ]\n",
167: esymtab - (char *)symtab, name);
168:
169: for (sp = sym_start; sp < sym_end; sp++) {
170: register int strx;
171: strx = sp->n_un.n_strx;
172: if (strx != 0) {
173: if (strx > strlen) {
174: db_printf("Bad string table index (%#x)\n", strx);
175: sp->n_un.n_name = 0;
176: continue;
177: }
178: sp->n_un.n_name = strtab + strx;
179: }
180: }
181:
182: db_add_symbol_table(sym_start, sym_end, name, (char *)symtab,
183: 0, 0, 0, FALSE);
184: }
185:
186: /*
187: * check file name or not (check xxxx.x pattern)
188: */
189: boolean_t
190: X_db_is_filename(name)
191: register char *name;
192: {
193: while (*name) {
194: if (*name == '.') {
195: if (name[1])
196: return(TRUE);
197: }
198: name++;
199: }
200: return(FALSE);
201: }
202:
203: /*
204: * special name comparison routine with a name in the symbol table entry
205: */
206: boolean_t
207: X_db_eq_name(sp, name)
208: struct nlist *sp;
209: char *name;
210: {
211: register char *s1, *s2;
212:
213: s1 = sp->n_un.n_name;
214: s2 = name;
215: if (*s1 == '_' && *s2 && *s2 != '_')
216: s1++;
217: while (*s2) {
218: if (*s1++ != *s2++) {
219: /*
220: * check .c .o file name comparison case
221: */
222: if (*s2 == 0 && sp->n_un.n_name <= s1 - 2
223: && s1[-2] == '.' && s1[-1] == 'o')
224: return(TRUE);
225: return(FALSE);
226: }
227: }
228: /*
229: * do special check for
230: * xxx:yyy for N_FUN
231: * xxx.ttt for N_DATA and N_BSS
232: */
233: return(*s1 == 0 || (*s1 == ':' && sp->n_type == N_FUN) ||
234: (*s1 == '.' && (sp->n_type == N_DATA || sp->n_type == N_BSS)));
235: }
236:
237: /*
238: * search a symbol table with name and type
239: * fp(in,out): last found text file name symbol entry
240: */
241: struct nlist *
242: X_db_search_name(sp, ep, name, type, fp)
243: register struct nlist *sp;
244: struct nlist *ep;
245: char *name;
246: int type;
247: struct nlist **fp;
248: {
249: struct nlist *file_sp = *fp;
250: struct nlist *found_sp = 0;
251:
252: for ( ; sp < ep; sp++) {
253: if (sp->n_type == N_TEXT && X_db_is_filename(sp->n_un.n_name))
254: *fp = sp;
255: if (type) {
256: if (sp->n_type == type) {
257: if (X_db_eq_name(sp, name))
258: return(sp);
259: }
260: if (sp->n_type == N_SO)
261: *fp = sp;
262: continue;
263: }
264: if (sp->n_type & N_STAB)
265: continue;
266: if (sp->n_un.n_name && X_db_eq_name(sp, name)) {
267: /*
268: * In case of qaulified search by a file,
269: * return it immediately with some check.
270: * Otherwise, search external one
271: */
272: if (file_sp) {
273: if ((file_sp == *fp) || (sp->n_type & N_EXT))
274: return(sp);
275: } else if (sp->n_type & N_EXT)
276: return(sp);
277: else
278: found_sp = sp;
279: }
280: }
281: return(found_sp);
282: }
283:
284: /*
285: * search a symbol with file, func and line qualification
286: */
287: struct nlist *
288: X_db_qualified_search(stab, file, sym, line)
289: db_symtab_t *stab;
290: char *file;
291: char *sym;
292: int line;
293: {
294: register struct nlist *sp = (struct nlist *)stab->start;
295: struct nlist *ep = (struct nlist *)stab->end;
296: struct nlist *fp = 0;
297: struct nlist *found_sp;
298: unsigned func_top;
299: boolean_t in_file;
300:
301: if (file == 0 && sym == 0)
302: return(0);
303: if (file) {
304: if ((sp = X_db_search_name(sp, ep, file, N_TEXT, &fp)) == 0)
305: return(0);
306: }
307: if (sym) {
308: sp = X_db_search_name(sp, ep, sym, (line > 0)? N_FUN: 0, &fp);
309: if (sp == 0)
310: return(0);
311: }
312: if (line > 0) {
313: if (file && !X_db_eq_name(fp, file))
314: return(0);
315: found_sp = 0;
316: if (sp->n_type == N_FUN) {
317: /*
318: * qualfied by function name
319: * search backward because line number entries
320: * for the function are above it in this case.
321: */
322: func_top = sp->n_value;
323: for (sp--; sp >= (struct nlist *)stab->start; sp--) {
324: if (sp->n_type != N_SLINE)
325: continue;
326: if (sp->n_value < func_top)
327: break;
328: if (sp->n_desc <= line) {
329: if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
330: found_sp = sp;
331: if (sp->n_desc == line)
332: break;
333: }
334: }
335: if (sp->n_type != N_SLINE || sp->n_value < func_top)
336: return(0);
337: } else {
338: /*
339: * qualified by only file name
340: * search forward in this case
341: */
342: in_file = TRUE;
343: for (sp++; sp < ep; sp++) {
344: if (sp->n_type == N_TEXT
345: && X_db_is_filename(sp->n_un.n_name))
346: break; /* enter into another file */
347: if (sp->n_type == N_SOL) {
348: in_file = X_db_eq_name(sp, file);
349: continue;
350: }
351: if (!in_file || sp->n_type != N_SLINE)
352: continue;
353: if (sp->n_desc <= line) {
354: if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
355: found_sp = sp;
356: if (sp->n_desc == line)
357: break;
358: }
359: }
360: }
361: sp = found_sp;
362: }
363: return(sp);
364: }
365:
366: /*
367: * lookup symbol by name
368: */
369: db_sym_t
370: X_db_lookup(stab, symstr)
371: db_symtab_t *stab;
372: char * symstr;
373: {
374: register char *p;
375: register n;
376: int n_name;
377: int line_number;
378: char *file_name = 0;
379: char *sym_name = 0;
380: char *component[3];
381: struct nlist *found = 0;
382:
383: /*
384: * disassemble component: [file_name:]symbol[:line_nubmer]
385: */
386: component[0] = symstr;
387: component[1] = component[2] = 0;
388: for (p = symstr, n = 1; *p; p++) {
389: if (*p == ':') {
390: if (n >= 3)
391: break;
392: *p = 0;
393: component[n++] = p+1;
394: }
395: }
396: if (*p != 0)
397: goto out;
398: line_number = 0;
399: n_name = n;
400: p = component[n-1];
401: if (*p >= '0' && *p <= '9') {
402: if (n == 1)
403: goto out;
404: for (line_number = 0; *p; p++) {
405: if (*p < '0' || *p > '9')
406: goto out;
407: line_number = line_number*10 + *p - '0';
408: }
409: n_name--;
410: } else if (n >= 3)
411: goto out;
412: if (n_name == 1) {
413: if (X_db_is_filename(component[0])) {
414: file_name = component[0];
415: sym_name = 0;
416: } else {
417: file_name = 0;
418: sym_name = component[0];
419: }
420: } else {
421: file_name = component[0];
422: sym_name = component[1];
423: }
424: found = X_db_qualified_search(stab, file_name, sym_name, line_number);
425:
426: out:
427: while (--n > 1)
428: component[n][-1] = ':';
429: return((db_sym_t) found);
430: }
431:
432: db_sym_t
433: X_db_search_symbol(symtab, off, strategy, diffp)
434: db_symtab_t * symtab;
435: register
436: db_addr_t off;
437: db_strategy_t strategy;
438: db_expr_t *diffp; /* in/out */
439: {
440: register unsigned int diff = *diffp;
441: register struct nlist *symp = 0;
442: register struct nlist *sp, *ep;
443:
444: sp = (struct nlist *)symtab->start;
445: ep = (struct nlist *)symtab->end;
446:
447: for (; sp < ep; sp++) {
448: if (sp->n_un.n_name == 0)
449: continue;
450: if ((sp->n_type & N_STAB) != 0)
451: continue;
452: if (off >= sp->n_value) {
453: if (off - sp->n_value < diff) {
454: diff = off - sp->n_value;
455: symp = sp;
456: if (diff == 0 && (sp->n_type & N_EXT))
457: break;
458: }
459: else if (off - sp->n_value == diff) {
460: if (symp == 0)
461: symp = sp;
462: else if ((symp->n_type & N_EXT) == 0 &&
463: (sp->n_type & N_EXT) != 0)
464: symp = sp; /* pick the external symbol */
465: }
466: }
467: }
468: if (symp == 0) {
469: *diffp = off;
470: }
471: else {
472: *diffp = diff;
473: }
474: return ((db_sym_t)symp);
475: }
476:
477: /*
478: * Return the name and value for a symbol.
479: */
480: void
481: X_db_symbol_values(sym, namep, valuep)
482: db_sym_t sym;
483: char **namep;
484: db_expr_t *valuep;
485: {
486: register struct nlist *sp;
487:
488: sp = (struct nlist *)sym;
489: if (namep)
490: *namep = sp->n_un.n_name;
491: if (valuep)
492: *valuep = sp->n_value;
493: }
494:
495: #define X_DB_MAX_DIFF 8 /* maximum allowable diff at the end of line */
496:
497: /*
498: * search symbol by value
499: */
500: X_db_search_by_addr(stab, addr, file, func, line, diff)
501: db_symtab_t *stab;
502: register unsigned addr;
503: char **file;
504: char **func;
505: int *line;
506: unsigned *diff;
507: {
508: register struct nlist *sp;
509: register struct nlist *line_sp, *func_sp, *file_sp, *line_func;
510: register func_diff, line_diff;
511: boolean_t found_line = FALSE;
512: struct nlist *ep = (struct nlist *)stab->end;
513:
514: line_sp = func_sp = file_sp = line_func = 0;
515: *file = *func = 0;
516: *line = 0;
517: for (sp = (struct nlist *)stab->start; sp < ep; sp++) {
518: switch(sp->n_type) {
519: case N_SLINE:
520: if (sp->n_value <= addr) {
521: if (line_sp == 0 || line_diff >= addr - sp->n_value) {
522: if (line_func)
523: line_func = 0;
524: line_sp = sp;
525: line_diff = addr - sp->n_value;
526: }
527: }
528: if (sp->n_value >= addr && line_sp)
529: found_line = TRUE;
530: continue;
531: case N_FUN:
532: if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF))
533: && line_func == 0)
534: line_func = sp;
535: continue;
536: case N_TEXT:
537: if (X_db_is_filename(sp->n_un.n_name)) {
538: if (sp->n_value > addr)
539: continue;
540: if (file_sp == 0 || file_sp->n_value < sp->n_value)
541: file_sp = sp;
542: } else if (sp->n_value <= addr &&
543: (func_sp == 0 || func_diff > addr - sp->n_value)) {
544: func_sp = sp;
545: func_diff = addr - sp->n_value;
546: }
547: continue;
548: case N_TEXT|N_EXT:
549: if (sp->n_value <= addr &&
550: (func_sp == 0 || func_diff >= addr - sp->n_value)) {
551: func_sp = sp;
552: func_diff = addr - sp->n_value;
553: if (func_diff == 0 && file_sp && func_sp)
554: break;
555: }
556: default:
557: continue;
558: }
559: break;
560: }
561: if (line_sp) {
562: if (line_func == 0 || func_sp == 0
563: || line_func->n_value != func_sp->n_value)
564: line_sp = 0;
565: }
566: if (file_sp) {
567: *diff = addr - file_sp->n_value;
568: *file = file_sp->n_un.n_name;
569: }
570: if (func_sp) {
571: *diff = addr - func_sp->n_value;
572: *func = (func_sp->n_un.n_name[0] == '_')?
573: func_sp->n_un.n_name + 1: func_sp->n_un.n_name;
574: }
575: if (line_sp) {
576: *diff = addr - line_sp->n_value;
577: *line = line_sp->n_desc;
578: }
579: return(file_sp || func_sp || line_sp);
580: }
581:
582: /* ARGSUSED */
583: boolean_t
584: X_db_line_at_pc(stab, sym, file, line, pc)
585: db_symtab_t *stab;
586: db_sym_t sym;
587: char **file;
588: int *line;
589: db_expr_t pc;
590: {
591: char *func;
592: unsigned diff;
593: boolean_t found;
594:
595: found = X_db_search_by_addr(stab,(unsigned)pc,file,&func,line,&diff);
596: return(found && func && *file);
597: }
598:
599: /*
600: * Initialization routine for a.out files.
601: */
602: kdb_init()
603: {
604: extern char *esym;
605: extern int end;
606:
607: if (esym > (char *)&end) {
608: X_db_sym_init((int *)&end, esym, "mach");
609: }
610: }
611:
612: /*
613: * Read symbol table from file.
614: * (should be somewhere else)
615: */
616: #include <bootstrap/file_io.h>
617: #include <vm/vm_kern.h>
618:
619: read_symtab_from_file(fp, symtab_name)
620: struct file *fp;
621: char * symtab_name;
622: {
623: vm_size_t resid;
624: kern_return_t result;
625: vm_offset_t symoff;
626: vm_size_t symsize;
627: vm_offset_t stroff;
628: vm_size_t strsize;
629: vm_size_t table_size;
630: vm_offset_t symtab;
631:
632: if (!get_symtab(fp, &symoff, &symsize)) {
633: boot_printf("[ error %d reading %s file header ]\n",
634: result, symtab_name);
635: return;
636: }
637:
638: stroff = symoff + symsize;
639: result = read_file(fp, (vm_offset_t)stroff,
640: (vm_offset_t)&strsize, sizeof(strsize), &resid);
641: if (result || resid) {
642: boot_printf("[ no valid symbol table present for %s ]\n",
643: symtab_name);
644: return;
645: }
646:
647: table_size = sizeof(int) + symsize + strsize;
648: table_size = (table_size + sizeof(int)-1) & ~(sizeof(int)-1);
649:
650: result = kmem_alloc_wired(kernel_map, &symtab, table_size);
651: if (result) {
652: boot_printf("[ error %d allocating space for %s symbol table ]\n",
653: result, symtab_name);
654: return;
655: }
656:
657: *(int *)symtab = symsize;
658:
659: result = read_file(fp, symoff,
660: symtab + sizeof(int), symsize, &resid);
661: if (result || resid) {
662: boot_printf("[ error %d reading %s symbol table ]\n",
663: result, symtab_name);
664: return;
665: }
666:
667: result = read_file(fp, stroff,
668: symtab + sizeof(int) + symsize, strsize, &resid);
669: if (result || resid) {
670: boot_printf("[ error %d reading %s string table ]\n",
671: result, symtab_name);
672: return;
673: }
674:
675: X_db_sym_init((int *)symtab,
676: (char *)(symtab + table_size),
677: symtab_name);
678:
679: }
680:
681: #endif /* DB_GCC_AOUT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.