|
|
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: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Mach Operating System
27: * Copyright (c) 1991,1990 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50: /*
51: */
52: /*
53: * Author: David B. Golub, Carnegie Mellon University
54: * Date: 7/90
55: */
56: /*
57: * Symbol table routines for a.out format files.
58: */
59: #include <mach/boolean.h>
60: #include <mach/std_types.h>
61: #include <machine/db_machdep.h> /* data types */
62: #include <string.h> /* For strcpy(), strcmp() */
63: #include <ddb/db_aout.h>
64: #include <ddb/db_output.h> /* For db_printf() */
65: #include <ddb/db_sym.h>
66:
67: #ifndef DB_NO_AOUT
68:
69: #include <ddb/nlist.h> /* a.out symbol table */
70: #include <ddb/stab.h>
71:
72: #define private static
73:
74: private int aout_db_order_symbols(char *, char *);
75: private int aout_db_compare_symbols(char *, char *);
76: private boolean_t aout_db_is_filename(char *);
77: private boolean_t aout_db_eq_name(struct nlist *, char *, int);
78:
79: /*
80: * An a.out symbol table as loaded into the kernel debugger:
81: *
82: * symtab -> size of symbol entries, in bytes
83: * sp -> first symbol entry
84: * ...
85: * ep -> last symbol entry + 1
86: * strtab == start of string table
87: * size of string table in bytes,
88: * including this word
89: * -> strings
90: */
91:
92: /*
93: * Find pointers to the start and end of the symbol entries,
94: * given a pointer to the start of the symbol table.
95: */
96: #define db_get_aout_symtab(symtab, sp, ep) \
97: (sp = (struct nlist *)(((vm_offset_t *)(symtab)) + 1), \
98: ep = (struct nlist *)((char *)sp + *((int *)(symtab))))
99:
100: char *db_sorting_sym_end;
101:
102: private int
103: aout_db_order_symbols(
104: char *s1,
105: char *s2)
106: {
107: struct nlist *sym1 = (struct nlist *) s1;
108: struct nlist *sym2 = (struct nlist *) s2;
109:
110: if (sym1->n_value != sym2->n_value)
111: return (sym1->n_value - sym2->n_value);
112: else {
113: return (sym1->n_un.n_name - sym2->n_un.n_name);
114: }
115: }
116:
117: private int
118: aout_db_compare_symbols(
119: char *sym1,
120: char *sym2)
121: {
122: return (((struct nlist *) sym1)->n_value -
123: ((struct nlist *) sym2)->n_value);
124: }
125:
126: int db_sorting_limit = 50000;
127:
128: boolean_t
129: aout_db_sym_init(
130: char * symtab, /* pointer to start of symbol table */
131: char * esymtab, /* pointer to end of string table,
132: for checking - may be rounded up to
133: integer boundary */
134: char * name,
135: char * task_addr) /* use for this task only */
136: {
137: struct nlist *sym_start, *sym_end;
138: struct nlist *sp;
139: char * strtab;
140: int strlen;
141: char * estrtab;
142: unsigned long minsym = ~0;
143: unsigned long maxsym = 0;
144: boolean_t sorted;
145: boolean_t sorting;
146: #ifdef __MACHO__
147: extern boolean_t getsymtab(char *,
148: vm_offset_t *, int *,
149: vm_offset_t *, vm_size_t *);
150: int nsyms;
151: #endif
152:
153:
154: #ifdef __MACHO__
155: if (!getsymtab(symtab,
156: (vm_offset_t *)&sym_start, &nsyms,
157: (vm_offset_t *)&strtab, (vm_size_t *)&strlen)) {
158: return(FALSE);
159: }
160: sym_end = sym_start + nsyms;
161: estrtab = strtab + strlen;
162: #else
163: db_get_aout_symtab(symtab, sym_start, sym_end);
164:
165: db_sorting_sym_end = (char *)sym_end;
166: strtab = (char *)sym_end;
167: strlen = *(int *)strtab;
168: estrtab = strtab + strlen;
169: #endif
170:
171: #ifndef __MACHO__
172: #define round_to_size(x) \
173: (((vm_offset_t)(x) + sizeof(vm_size_t) - 1) & ~(sizeof(vm_size_t) - 1))
174:
175: if (round_to_size(estrtab) != round_to_size(esymtab))
176: return (FALSE);
177:
178: #undef round_to_size
179: #endif
180:
181: sorting = ((sym_end - sym_start) < db_sorting_limit);
182:
183: for (sp = sym_start; sp < sym_end; sp++) {
184: register long strx;
185: strx = sp->n_un.n_strx;
186: if (strx != 0) {
187: if (strx > strlen) {
188: sp->n_un.n_name = 0;
189: continue;
190: }
191: sp->n_un.n_name = strtab + strx;
192: }
193: if (sp->n_type != N_ABS) {
194: if (sp->n_value > 0 && sp->n_value < minsym)
195: minsym = sp->n_value;
196: if (sp->n_value > maxsym)
197: maxsym = sp->n_value;
198: }
199: }
200: if (maxsym < minsym)
201: minsym = maxsym = 0;
202:
203: if (sorting) {
204: db_qsort((char *) sym_start, sym_end - sym_start,
205: sizeof (struct nlist), aout_db_order_symbols);
206: sorted = TRUE;
207: } else
208: sorted = FALSE;
209:
210: if (db_add_symbol_table(SYMTAB_AOUT,
211: (char*)sym_start,
212: (char*)sym_end,
213: name,
214: symtab,
215: task_addr,
216: minsym,
217: maxsym,
218: sorted))
219: {
220: /* Successfully added symbol table */
221:
222: pmap_protect(kernel_pmap,
223: (vm_offset_t) sym_start, (vm_offset_t) sym_end,
224: VM_PROT_READ|VM_PROT_WRITE);
225: pmap_protect(kernel_pmap,
226: (vm_offset_t) strtab, (vm_offset_t) estrtab,
227: VM_PROT_READ|VM_PROT_WRITE);
228: return TRUE;
229: }
230: return FALSE;
231: }
232:
233: /*
234: * This KLUDGE offsets the n_values of a copied symbol table
235: */
236: void db_clone_offsetXXX(char *, long);
237: void
238: db_clone_offsetXXX(char * symtab, long offset)
239: {
240: register struct nlist *sym_start, *sym_end, *sp;
241:
242: db_get_aout_symtab((int *)symtab, sym_start, sym_end);
243:
244: for (sp = sym_start; sp < sym_end; sp++)
245: if (sp->n_type != N_ABS)
246: sp->n_value += offset;
247: }
248: /* end KLUDGE */
249:
250: /*
251: * check file name or not (check xxxx.x pattern)
252: */
253: private boolean_t
254: aout_db_is_filename(char *name)
255: {
256: while (*name) {
257: if (*name == '.') {
258: if (name[1])
259: return(TRUE);
260: }
261: name++;
262: }
263: return(FALSE);
264: }
265:
266: /*
267: * special name comparison routine with a name in the symbol table entry
268: */
269: private boolean_t
270: aout_db_eq_name(
271: struct nlist *sp,
272: char *name,
273: int incomplete)
274: {
275: register char *s1, *s2;
276:
277: s1 = sp->n_un.n_name;
278: s2 = name;
279: #ifndef __NO_UNDERSCORES__
280: if (*s1 == '_' && *s2 && *s2 != '_')
281: s1++;
282: #endif /* __NO_UNDERSCORES__ */
283: while (*s2) {
284: if (*s1++ != *s2++) {
285: /*
286: * check .c .o file name comparison case
287: */
288: if (*s2 == 0 && sp->n_un.n_name <= s1 - 2
289: && s1[-2] == '.' && s1[-1] == 'o')
290: return(TRUE);
291: return(FALSE);
292: }
293: }
294: if (incomplete)
295: return(TRUE);
296: /*
297: * do special check for
298: * xxx:yyy for N_FUN
299: * xxx.ttt for N_DATA and N_BSS
300: */
301: return(*s1 == 0 || (*s1 == ':' && sp->n_type == N_FUN) ||
302: (*s1 == '.' && (sp->n_type == N_DATA || sp->n_type == N_BSS)));
303: }
304:
305: /*
306: * search a symbol table with name and type
307: * fp(in,out): last found text file name symbol entry
308: */
309: private struct nlist *
310: aout_db_search_name(
311: struct nlist *sp,
312: struct nlist *ep,
313: char *name,
314: int type,
315: struct nlist **fp,
316: int incomplete)
317: {
318: struct nlist *file_sp = *fp;
319: struct nlist *found_sp = 0;
320:
321: for ( ; sp < ep; sp++) {
322: if (sp->n_other)
323: sp->n_other = 0;
324: if (sp->n_type == N_TEXT && aout_db_is_filename(sp->n_un.n_name))
325: *fp = sp;
326: if (type) {
327: if (sp->n_type == type) {
328: /* dwm_debug: b26 name, mk6 added last param */
329: if (aout_db_eq_name(sp, name, 0))
330: return(sp);
331: }
332: if (sp->n_type == N_SO)
333: *fp = sp;
334: continue;
335: }
336: if (sp->n_type & N_STAB)
337: continue;
338: if (sp->n_un.n_name && aout_db_eq_name(sp, name, incomplete)) {
339: /*
340: * In case of qaulified search by a file,
341: * return it immediately with some check.
342: * Otherwise, search external one
343: */
344: if (file_sp) {
345: if ((file_sp == *fp) || (sp->n_type & N_EXT))
346: return(sp);
347: } else if ((sp->n_type & N_EXT) ||
348: (incomplete && !aout_db_is_filename(sp->n_un.n_name)))
349: return(sp);
350: else
351: found_sp = sp;
352: }
353: }
354: return(found_sp);
355: }
356:
357: /*
358: * Print sorted possible completions for a symbol.
359: * Use n_other field to mark completion symbols in order
360: * to speed up sort.
361: */
362: int
363: aout_db_qualified_print_completion(
364: db_symtab_t *stab,
365: char *sym)
366: {
367: struct nlist *sp;
368: struct nlist *sp1;
369: struct nlist *ep;
370: struct nlist *ep1;
371: struct nlist *fp = 0;
372: int symlen;
373: int nsym = 0;
374: struct nlist *cur;
375: struct nlist *new;
376: char *fname;
377: int func;
378: int line;
379:
380: sp = aout_db_search_name((struct nlist *)stab->start,
381: (struct nlist *)stab->end,
382: sym, 0, &fp, 1);
383: if (sp == (struct nlist *)0)
384: return 0;
385:
386: symlen = strlen(sym);
387: cur = sp;
388: while (cur) {
389: if (strncmp(cur->n_un.n_name, sym, symlen) == 0)
390: cur->n_other = 1;
391: else
392: cur->n_other = 2;
393: ep = cur;
394: cur = aout_db_search_name(cur + 1, (struct nlist *)stab->end,
395: sym, 0, &fp, 1);
396: }
397:
398: sp1 = sp;
399: for (;;) {
400: new = cur = sp;
401: while (++cur <= ep)
402: if (cur->n_other) {
403: if (sp1 == sp)
404: sp1 = cur;
405: if (strcmp(&cur->n_un.n_name[cur->n_other - 1],
406: &new->n_un.n_name[new->n_other - 1]) < 0)
407: new = cur;
408: else
409: ep1 = cur;
410: }
411:
412: func = line = 0;
413: if ((new->n_type & N_EXT) == 0) {
414: for (cur = new - 1; cur > (struct nlist *)stab->start; cur--) {
415: if (cur->n_type == N_SO ||
416: (stab->sorted && cur->n_value < new->n_value))
417: break;
418: if (line == 0 &&
419: cur->n_type == N_SLINE &&
420: cur->n_value == new->n_value)
421: line = cur->n_desc;
422: if (func == 0 &&
423: cur->n_type == N_FUN &&
424: cur->n_value == new->n_value)
425: func = 1;
426: }
427:
428: if (cur->n_type == N_SO)
429: fname = cur->n_un.n_name;
430: else
431: fname = (char *)0;
432:
433: if (line == 0 || func == 0)
434: for (cur = new + 1;
435: cur < (struct nlist *)stab->end; cur++) {
436: if (cur->n_type == N_SO ||
437: (stab->sorted && cur->n_value > new->n_value))
438: break;
439: if (line == 0 &&
440: cur->n_type == N_SLINE &&
441: cur->n_value == new->n_value) {
442: line = cur->n_desc;
443: if (func)
444: break;
445: }
446: if (func == 0 &&
447: cur->n_type == N_FUN &&
448: cur->n_value == new->n_value) {
449: func = 1;
450: if (line)
451: break;
452: }
453: }
454: } else {
455: fname = (char *)0;
456: for (cur = new - 1; cur > (struct nlist *)stab->start; cur--) {
457: if (cur->n_type == N_SO ||
458: (stab->sorted && cur->n_value < new->n_value))
459: break;
460: if (func == 0 &&
461: cur->n_type == N_FUN &&
462: cur->n_value == new->n_value)
463: func = 1;
464: }
465: if (func == 0)
466: for (cur = new + 1;
467: cur < (struct nlist *)stab->end; cur++) {
468: if (cur->n_type == N_SO ||
469: (stab->sorted && cur->n_value > new->n_value))
470: break;
471: if (cur->n_type == N_FUN &&
472: cur->n_value == new->n_value) {
473: func = 1;
474: break;
475: }
476: }
477: }
478:
479: db_sym_print_completion(stab, &new->n_un.n_name[new->n_other - 1],
480: func, fname, line);
481: nsym++;
482: new->n_other = 0;
483:
484: if (new == sp) {
485: if (sp1 == sp)
486: break;
487: sp = sp1;
488: } else if (new == sp1)
489: sp1 = sp;
490:
491: if (new == ep)
492: ep = ep1;
493: }
494: return nsym;
495: }
496:
497: /*
498: * search a (possibly incomplete) symbol with file, func and line qualification
499: */
500: private int
501: aout_db_qualified_search(
502: db_symtab_t *stab,
503: char *file,
504: char *sym,
505: int line,
506: db_sym_t *ret,
507: char **name,
508: int *len)
509: {
510: register struct nlist *sp = (struct nlist *)stab->start;
511: struct nlist *ep = (struct nlist *)stab->end;
512: struct nlist *fp = 0;
513: struct nlist *found_sp;
514: unsigned long func_top;
515: boolean_t in_file;
516: int nsym = 0;
517: int i;
518: char *p;
519:
520: if (file == 0 && sym == 0)
521: return(0);
522: if (file) {
523: if ((sp = aout_db_search_name(sp, ep, file, N_TEXT, &fp, 0)) == 0)
524: return(0);
525: }
526: if (sym) {
527: for (;;) {
528: sp = aout_db_search_name(sp, ep, sym, (line > 0)? N_FUN: 0, &fp,
529: (ret == (db_sym_t *)0));
530: if (sp == 0)
531: return(nsym);
532: if (ret)
533: break;
534:
535: if (strncmp(sp->n_un.n_name, sym, strlen(sym)) == 0)
536: p = sp->n_un.n_name;
537: else
538: p = &sp->n_un.n_name[1];
539:
540: if (*name == (char *)0) {
541: *name = p;
542: *len = strlen(p);
543: } else {
544: for (i = 0; i < *len; i++)
545: if ((*name)[i] != p[i]) {
546: *len = i;
547: break;
548: }
549: }
550:
551: nsym++;
552: sp++;
553: }
554: }
555: if (line > 0) {
556: if (file && !aout_db_eq_name(fp, file, 0))
557: return(0);
558: found_sp = 0;
559: if (sp->n_type == N_FUN) {
560: /*
561: * qualfied by function name
562: * search backward because line number entries
563: * for the function are above it in this case.
564: */
565: func_top = sp->n_value;
566: if (stab->sorted) {
567: /* symbols with the same value may have been mixed up */
568: do {
569: sp++;
570: } while (sp->n_value == func_top);
571: }
572: for (sp--; sp >= (struct nlist *)stab->start; sp--) {
573: if (sp->n_type != N_SLINE)
574: continue;
575: if (sp->n_value < func_top)
576: break;
577: if (sp->n_desc <= line) {
578: if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
579: found_sp = sp;
580: if (sp->n_desc == line)
581: break;
582: }
583: }
584: if (sp->n_type != N_SLINE || sp->n_value < func_top)
585: return(0);
586: } else {
587: /*
588: * qualified by only file name
589: * search forward in this case
590: */
591: in_file = TRUE;
592: if (stab->sorted) {
593: /* symbols with the same value may have been mixed up */
594: func_top = sp->n_value;
595: do {
596: sp--;
597: } while (sp->n_value == func_top);
598: }
599: for (sp++; sp < ep; sp++) {
600: if (sp->n_type == N_TEXT
601: && aout_db_is_filename(sp->n_un.n_name))
602: break; /* enter into another file */
603: if (sp->n_type == N_SOL) {
604: in_file = aout_db_eq_name(sp, file, 0);
605: continue;
606: }
607: if (!in_file || sp->n_type != N_SLINE)
608: continue;
609: if (sp->n_desc <= line) {
610: if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
611: found_sp = sp;
612: if (sp->n_desc == line)
613: break;
614: }
615: }
616: }
617: sp = found_sp;
618: }
619: *ret = (db_sym_t) sp;
620: return(1);
621: }
622:
623: /*
624: * lookup symbol by name
625: */
626: db_sym_t
627: aout_db_lookup(
628: db_symtab_t *stab,
629: char * symstr)
630: {
631: return(db_sym_parse_and_lookup(aout_db_qualified_search, stab, symstr));
632: }
633:
634: /*
635: * lookup (possibly incomplete) symbol by name
636: */
637: int
638: aout_db_lookup_incomplete(
639: db_symtab_t *stab,
640: char * symstr,
641: char ** name,
642: int *len,
643: int *toadd)
644: {
645: return(db_sym_parse_and_lookup_incomplete(aout_db_qualified_search,
646: stab, symstr, name, len, toadd));
647: }
648:
649: /*
650: * Display possible completion for the symbol
651: */
652: int
653: aout_db_print_completion(stab, symstr)
654: db_symtab_t *stab;
655: char * symstr;
656: {
657:
658: return(db_sym_parse_and_print_completion(aout_db_qualified_print_completion,
659: stab, symstr));
660: }
661:
662: db_sym_t
663: aout_db_search_symbol(
664: db_symtab_t *symtab,
665: db_addr_t off,
666: db_strategy_t strategy,
667: db_expr_t *diffp) /* in/out */
668: {
669: register unsigned long diff = *diffp;
670: register struct nlist *symp = 0;
671: struct nlist *sp, *ep, *cp;
672: boolean_t first_pass = FALSE;
673:
674: sp = (struct nlist *)symtab->start;
675: ep = (struct nlist *)symtab->end;
676:
677: if (symtab->sorted) {
678: struct nlist target;
679:
680: target.n_value = off;
681: target.n_un.n_name = (char *) 0;
682: target.n_other = (char) 0;
683: db_qsort_limit_search((char *) &target, (char **) &sp, (char **) &ep,
684: sizeof (struct nlist), aout_db_compare_symbols);
685: first_pass = TRUE;
686: }
687:
688: try_again:
689: for (cp = ep-1; cp >= sp; cp--) {
690: if (cp->n_un.n_name == 0)
691: continue;
692: if ((cp->n_type & N_STAB) != 0)
693: continue;
694: if (strategy == DB_STGY_XTRN && (cp->n_type & N_EXT) == 0)
695: continue;
696: if (off >= cp->n_value) {
697: if (off - cp->n_value < diff) {
698: diff = off - cp->n_value;
699: symp = cp;
700: if (diff == 0 && (cp->n_type & N_EXT))
701: break;
702: }
703: else if (off - cp->n_value == diff) {
704: if (symp == 0)
705: symp = cp;
706: else if ((symp->n_type & N_EXT) == 0 &&
707: (cp->n_type & N_EXT) != 0)
708: symp = cp; /* pick the external symbol */
709: }
710: }
711: }
712: if (symp == 0) {
713: if (first_pass) {
714: first_pass = FALSE;
715: sp = (struct nlist *) symtab->start;
716: goto try_again;
717: }
718: *diffp = off;
719: }
720: else {
721: *diffp = diff;
722: }
723: return ((db_sym_t)symp);
724: }
725:
726: /*
727: * Return the name and value for a symbol.
728: */
729: void
730: aout_db_symbol_values(
731: db_sym_t sym,
732: char **namep,
733: db_expr_t *valuep)
734: {
735: register struct nlist *sp;
736:
737: sp = (struct nlist *)sym;
738: if (namep)
739: *namep = sp->n_un.n_name;
740: if (valuep)
741: *valuep = sp->n_value;
742: }
743:
744: #define X_DB_MAX_DIFF 8 /* maximum allowable diff at the end of line */
745: extern int db_search_maxoff; /* maximum acceptable offset */
746:
747: /*
748: * search symbol by value
749: */
750: db_sym_t
751: aout_db_search_by_addr(
752: db_symtab_t *stab,
753: db_addr_t addr,
754: char **file,
755: char **func,
756: int *line,
757: db_expr_t *diff,
758: int *args)
759: {
760: struct nlist *sp, *cp;
761: register struct nlist *line_sp, *func_sp, *file_sp, *line_func;
762: unsigned long func_diff, line_diff;
763: boolean_t found_line = FALSE;
764: struct nlist *ep = (struct nlist *)stab->end;
765: boolean_t first_pass = FALSE;
766:
767: /*
768: * 92-May-16
769: * Added init of these two... not sure if it's correct, but
770: * can't be worse than random values.... -- [email protected]
771: */
772: func_diff = line_diff = /*HUGE*/0x0fffffff;
773:
774: line_sp = func_sp = file_sp = line_func = 0;
775: *file = *func = 0;
776: *line = 0;
777: *args = -1;
778:
779: sp = (struct nlist *)stab->start;
780: if (stab->sorted) {
781: struct nlist target;
782:
783: target.n_value = addr;
784: target.n_un.n_name = (char *) 0;
785: target.n_other = (char) 0;
786: db_qsort_limit_search((char *) &target, (char **) &sp,
787: (char **) &ep, sizeof (struct nlist),
788: aout_db_compare_symbols);
789: first_pass = TRUE;
790: }
791:
792: for (cp = sp; cp < ep; cp++) {
793: switch(cp->n_type) {
794: case N_SLINE:
795: if (cp->n_value <= addr) {
796: if (line_sp == 0 || line_diff >= addr - cp->n_value) {
797: if (line_func)
798: line_func = 0;
799: line_sp = cp;
800: line_diff = addr - cp->n_value;
801: }
802: }
803: if (cp->n_value >= addr && line_sp)
804: found_line = TRUE;
805: continue;
806: case N_FUN:
807: if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF))
808: && line_func == 0)
809: line_func = cp;
810: continue;
811: case N_SO:
812: if (cp->n_value > addr)
813: continue;
814: if (file_sp == 0 || file_sp->n_value <= cp->n_value)
815: file_sp = cp;
816: continue;
817: case N_TEXT:
818: if (aout_db_is_filename(cp->n_un.n_name)) {
819: if (cp->n_value > addr)
820: continue;
821: if (file_sp == 0 || file_sp->n_value <= cp->n_value)
822: file_sp = cp;
823: } else if (cp->n_value <= addr &&
824: (func_sp == 0 || func_diff > addr - cp->n_value)) {
825: func_sp = cp;
826: func_diff = addr - cp->n_value;
827: }
828: continue;
829: case N_TEXT|N_EXT:
830: if (cp->n_value <= addr &&
831: (func_sp == 0 || func_diff >= addr - cp->n_value)) {
832: func_sp = cp;
833: func_diff = addr - cp->n_value;
834: if (func_diff == 0 && file_sp && func_sp && line_sp == 0)
835: break;
836: }
837: default:
838: if (stab->sorted) {
839: if ((cp->n_value > addr) &&
840: (cp->n_value - addr > db_search_maxoff))
841: break;
842: }
843: continue;
844: }
845: break;
846: }
847: if (first_pass && (!file_sp || !line_sp || !func_sp)) {
848: first_pass = FALSE;
849: cp = sp;
850: sp = (struct nlist *)stab->start;
851: for (; cp >= sp; cp--) {
852: switch(cp->n_type) {
853: case N_SLINE:
854: if (line_sp)
855: found_line = TRUE;
856: continue;
857: case N_FUN:
858: if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF))
859: && line_func == 0)
860: line_func = cp;
861: continue;
862: case N_SO:
863: if (file_sp == 0)
864: file_sp = cp;
865: continue;
866: case N_TEXT:
867: if (aout_db_is_filename(cp->n_un.n_name)) {
868: if (file_sp == 0)
869: file_sp = cp;
870: } else if (func_sp == 0) {
871: func_sp = cp;
872: func_diff = addr - cp->n_value;
873: }
874: continue;
875: case N_TEXT|N_EXT:
876: if (func_sp == 0) {
877: func_sp = cp;
878: func_diff = addr - cp->n_value;
879: if (func_diff == 0 && file_sp && func_sp
880: && line_sp == 0)
881: break;
882: }
883: default:
884: if (line_sp && file_sp &&
885: addr - cp->n_value > db_search_maxoff)
886: break;
887: continue;
888: }
889: break;
890: }
891: }
892: #if 0
893: /*
894: * XXX - [email protected]
895: * I don't know if that code is useful to something, but it makes the -gline
896: * option of gcc useless.
897: */
898: if (line_sp) {
899: if (line_func == 0 || func_sp == 0
900: || line_func->n_value != func_sp->n_value)
901: line_sp = 0;
902: }
903: #else
904: if (line_sp && !found_line) {
905: line_sp = 0;
906: }
907: #endif
908: *diff = 0;
909: if (file_sp) {
910: *diff = addr - file_sp->n_value;
911: *file = file_sp->n_un.n_name;
912: }
913: if (line_sp) {
914: *diff = addr - line_sp->n_value;
915: *line = line_sp->n_desc;
916: }
917: if (func_sp) {
918: *diff = addr - func_sp->n_value;
919: *func = (func_sp->n_un.n_name[0] == '_')?
920: func_sp->n_un.n_name + 1: func_sp->n_un.n_name;
921: if (line_func && (line_func->n_desc & 0x4000))
922: *args = line_func->n_desc & 0x3ff;
923: }
924: return((db_sym_t) func_sp);
925: }
926:
927: /*
928: * Find filename and lineno within, given the current pc.
929: */
930: boolean_t
931: aout_db_line_at_pc(
932: db_symtab_t *stab,
933: db_sym_t sym,
934: char **file,
935: int *line,
936: db_expr_t pc)
937: {
938: char *func;
939: db_expr_t diff;
940: boolean_t found;
941: int args;
942:
943: found = (aout_db_search_by_addr(stab, (unsigned)pc, file, &func, line,
944: &diff, &args)
945: != DB_SYM_NULL);
946: return(found && func && *file);
947: }
948:
949: /*
950: * Initialization routine for a.out files.
951: */
952: void
953: aout_db_init(void)
954: {
955: #ifndef __MACHO__
956: extern vm_offset_t kern_sym_start;
957: extern vm_size_t kern_sym_size;
958: #else
959: extern struct mach_header _mh_execute_header;
960: #endif
961:
962: #ifndef __MACHO__
963: if (kern_sym_size != 0)
964: aout_db_sym_init((char *) kern_sym_start,
965: (char *)(kern_sym_start + kern_sym_size),
966: "mach",
967: (char *)0);
968: #else
969: aout_db_sym_init((char *) &_mh_execute_header,
970: (char *)0, "mach", (char *)0);
971: #endif
972: }
973:
974: #endif /* DB_NO_AOUT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.