]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/db_aout.c
xnu-201.tar.gz
[apple/xnu.git] / osfmk / ddb / db_aout.c
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 Software.Distribution@CS.CMU.EDU
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, *dbsym_start, *dbsym_end;
138 struct nlist *sp;
139 char *strtab, *dbstrtab;
140 int strlen;
141 char *estrtab, *dbestrtab;
142 unsigned long minsym = ~0;
143 unsigned long maxsym = 0;
144 boolean_t sorted;
145 boolean_t sorting;
146 extern boolean_t getsymtab(char *,
147 vm_offset_t *, int *,
148 vm_offset_t *, vm_size_t *);
149 int nsyms;
150
151
152 if (!getsymtab(symtab,
153 (vm_offset_t *)&sym_start, &nsyms,
154 (vm_offset_t *)&strtab, (vm_size_t *)&strlen)) {
155 return(FALSE);
156 }
157 sym_end = sym_start + nsyms;
158 estrtab = strtab + strlen;
159
160 /*
161 * We haven't actually started up VM yet, so we can just steal some pages to
162 * make a working copy of the symbols and strings
163 */
164
165 dbsym_start = (struct nlist *)pmap_steal_memory(((unsigned int)sym_end - (unsigned int)sym_start + 4096) & -4096); /* Get space for symbols */
166 dbstrtab = (char *)pmap_steal_memory(((unsigned int)estrtab - (unsigned int)strtab + 4096) & -4096); /* Get space for strings */
167
168 bcopy((char *)sym_start, (char *)dbsym_start, (unsigned int)sym_end - (unsigned int)sym_start); /* Copy symbols */
169 bcopy(strtab, dbstrtab, (unsigned int)estrtab - (unsigned int)strtab); /* Copy strings */
170
171 dbsym_end = dbsym_start + nsyms;
172 dbestrtab = dbstrtab + strlen;
173
174 sorting = ((dbsym_end - dbsym_start) < db_sorting_limit);
175
176 for (sp = dbsym_start; sp < dbsym_end; sp++) {
177 register long strx;
178 strx = sp->n_un.n_strx;
179 if (strx != 0) {
180 if (strx > strlen) {
181 sp->n_un.n_name = 0;
182 continue;
183 }
184 sp->n_un.n_name = dbstrtab + strx;
185 }
186 if (sp->n_type != N_ABS) {
187 if (sp->n_value > 0 && sp->n_value < minsym)
188 minsym = sp->n_value;
189 if (sp->n_value > maxsym)
190 maxsym = sp->n_value;
191 }
192 }
193
194 if (maxsym < minsym)
195 minsym = maxsym = 0;
196
197 if (sorting) {
198 db_qsort((char *) dbsym_start, dbsym_end - dbsym_start,
199 sizeof (struct nlist), aout_db_order_symbols);
200 sorted = TRUE;
201 } else
202 sorted = FALSE;
203
204 if (db_add_symbol_table(SYMTAB_AOUT,
205 (char*)dbsym_start,
206 (char*)dbsym_end,
207 name,
208 0,
209 task_addr,
210 minsym,
211 maxsym,
212 sorted))
213 {
214 /* Successfully added symbol table */
215
216 pmap_protect(kernel_pmap,
217 (vm_offset_t) dbsym_start, (vm_offset_t) dbsym_end,
218 VM_PROT_READ|VM_PROT_WRITE);
219 pmap_protect(kernel_pmap,
220 (vm_offset_t) dbstrtab, (vm_offset_t) dbestrtab,
221 VM_PROT_READ|VM_PROT_WRITE);
222 return TRUE;
223 }
224 return FALSE;
225 }
226
227 /*
228 * This KLUDGE offsets the n_values of a copied symbol table
229 */
230 void db_clone_offsetXXX(char *, long);
231 void
232 db_clone_offsetXXX(char * symtab, long offset)
233 {
234 register struct nlist *sym_start, *sym_end, *sp;
235
236 db_get_aout_symtab((int *)symtab, sym_start, sym_end);
237
238 for (sp = sym_start; sp < sym_end; sp++)
239 if (sp->n_type != N_ABS)
240 sp->n_value += offset;
241 }
242 /* end KLUDGE */
243
244 /*
245 * check file name or not (check xxxx.x pattern)
246 */
247 private boolean_t
248 aout_db_is_filename(char *name)
249 {
250 while (*name) {
251 if (*name == '.') {
252 if (name[1])
253 return(TRUE);
254 }
255 name++;
256 }
257 return(FALSE);
258 }
259
260 /*
261 * special name comparison routine with a name in the symbol table entry
262 */
263 private boolean_t
264 aout_db_eq_name(
265 struct nlist *sp,
266 char *name,
267 int incomplete)
268 {
269 register char *s1, *s2;
270
271 s1 = sp->n_un.n_name;
272 s2 = name;
273 #ifndef __NO_UNDERSCORES__
274 if (*s1 == '_' && *s2 && *s2 != '_')
275 s1++;
276 #endif /* __NO_UNDERSCORES__ */
277 while (*s2) {
278 if (*s1++ != *s2++) {
279 /*
280 * check .c .o file name comparison case
281 */
282 if (*s2 == 0 && sp->n_un.n_name <= s1 - 2
283 && s1[-2] == '.' && s1[-1] == 'o')
284 return(TRUE);
285 return(FALSE);
286 }
287 }
288 if (incomplete)
289 return(TRUE);
290 /*
291 * do special check for
292 * xxx:yyy for N_FUN
293 * xxx.ttt for N_DATA and N_BSS
294 */
295 return(*s1 == 0 || (*s1 == ':' && sp->n_type == N_FUN) ||
296 (*s1 == '.' && (sp->n_type == N_DATA || sp->n_type == N_BSS)));
297 }
298
299 /*
300 * search a symbol table with name and type
301 * fp(in,out): last found text file name symbol entry
302 */
303 private struct nlist *
304 aout_db_search_name(
305 struct nlist *sp,
306 struct nlist *ep,
307 char *name,
308 int type,
309 struct nlist **fp,
310 int incomplete)
311 {
312 struct nlist *file_sp = *fp;
313 struct nlist *found_sp = 0;
314
315 for ( ; sp < ep; sp++) {
316 if (sp->n_other)
317 sp->n_other = 0;
318 if (sp->n_type == N_TEXT && aout_db_is_filename(sp->n_un.n_name))
319 *fp = sp;
320 if (type) {
321 if (sp->n_type == type) {
322 /* dwm_debug: b26 name, mk6 added last param */
323 if (aout_db_eq_name(sp, name, 0))
324 return(sp);
325 }
326 if (sp->n_type == N_SO)
327 *fp = sp;
328 continue;
329 }
330 if (sp->n_type & N_STAB)
331 continue;
332 if (sp->n_un.n_name && aout_db_eq_name(sp, name, incomplete)) {
333 /*
334 * In case of qaulified search by a file,
335 * return it immediately with some check.
336 * Otherwise, search external one
337 */
338 if (file_sp) {
339 if ((file_sp == *fp) || (sp->n_type & N_EXT))
340 return(sp);
341 } else if ((sp->n_type & N_EXT) ||
342 (incomplete && !aout_db_is_filename(sp->n_un.n_name)))
343 return(sp);
344 else
345 found_sp = sp;
346 }
347 }
348 return(found_sp);
349 }
350
351 /*
352 * Print sorted possible completions for a symbol.
353 * Use n_other field to mark completion symbols in order
354 * to speed up sort.
355 */
356 int
357 aout_db_qualified_print_completion(
358 db_symtab_t *stab,
359 char *sym)
360 {
361 struct nlist *sp;
362 struct nlist *sp1;
363 struct nlist *ep;
364 struct nlist *ep1;
365 struct nlist *fp = 0;
366 int symlen;
367 int nsym = 0;
368 struct nlist *cur;
369 struct nlist *new;
370 char *fname;
371 int func;
372 int line;
373
374 sp = aout_db_search_name((struct nlist *)stab->start,
375 (struct nlist *)stab->end,
376 sym, 0, &fp, 1);
377 if (sp == (struct nlist *)0)
378 return 0;
379
380 symlen = strlen(sym);
381 cur = sp;
382 while (cur) {
383 if (strncmp(cur->n_un.n_name, sym, symlen) == 0)
384 cur->n_other = 1;
385 else
386 cur->n_other = 2;
387 ep = cur;
388 cur = aout_db_search_name(cur + 1, (struct nlist *)stab->end,
389 sym, 0, &fp, 1);
390 }
391
392 sp1 = sp;
393 for (;;) {
394 new = cur = sp;
395 while (++cur <= ep)
396 if (cur->n_other) {
397 if (sp1 == sp)
398 sp1 = cur;
399 if (strcmp(&cur->n_un.n_name[cur->n_other - 1],
400 &new->n_un.n_name[new->n_other - 1]) < 0)
401 new = cur;
402 else
403 ep1 = cur;
404 }
405
406 func = line = 0;
407 if ((new->n_type & N_EXT) == 0) {
408 for (cur = new - 1; cur > (struct nlist *)stab->start; cur--) {
409 if (cur->n_type == N_SO ||
410 (stab->sorted && cur->n_value < new->n_value))
411 break;
412 if (line == 0 &&
413 cur->n_type == N_SLINE &&
414 cur->n_value == new->n_value)
415 line = cur->n_desc;
416 if (func == 0 &&
417 cur->n_type == N_FUN &&
418 cur->n_value == new->n_value)
419 func = 1;
420 }
421
422 if (cur->n_type == N_SO)
423 fname = cur->n_un.n_name;
424 else
425 fname = (char *)0;
426
427 if (line == 0 || func == 0)
428 for (cur = new + 1;
429 cur < (struct nlist *)stab->end; cur++) {
430 if (cur->n_type == N_SO ||
431 (stab->sorted && cur->n_value > new->n_value))
432 break;
433 if (line == 0 &&
434 cur->n_type == N_SLINE &&
435 cur->n_value == new->n_value) {
436 line = cur->n_desc;
437 if (func)
438 break;
439 }
440 if (func == 0 &&
441 cur->n_type == N_FUN &&
442 cur->n_value == new->n_value) {
443 func = 1;
444 if (line)
445 break;
446 }
447 }
448 } else {
449 fname = (char *)0;
450 for (cur = new - 1; cur > (struct nlist *)stab->start; cur--) {
451 if (cur->n_type == N_SO ||
452 (stab->sorted && cur->n_value < new->n_value))
453 break;
454 if (func == 0 &&
455 cur->n_type == N_FUN &&
456 cur->n_value == new->n_value)
457 func = 1;
458 }
459 if (func == 0)
460 for (cur = new + 1;
461 cur < (struct nlist *)stab->end; cur++) {
462 if (cur->n_type == N_SO ||
463 (stab->sorted && cur->n_value > new->n_value))
464 break;
465 if (cur->n_type == N_FUN &&
466 cur->n_value == new->n_value) {
467 func = 1;
468 break;
469 }
470 }
471 }
472
473 db_sym_print_completion(stab, &new->n_un.n_name[new->n_other - 1],
474 func, fname, line);
475 nsym++;
476 new->n_other = 0;
477
478 if (new == sp) {
479 if (sp1 == sp)
480 break;
481 sp = sp1;
482 } else if (new == sp1)
483 sp1 = sp;
484
485 if (new == ep)
486 ep = ep1;
487 }
488 return nsym;
489 }
490
491 /*
492 * search a (possibly incomplete) symbol with file, func and line qualification
493 */
494 private int
495 aout_db_qualified_search(
496 db_symtab_t *stab,
497 char *file,
498 char *sym,
499 int line,
500 db_sym_t *ret,
501 char **name,
502 int *len)
503 {
504 register struct nlist *sp = (struct nlist *)stab->start;
505 struct nlist *ep = (struct nlist *)stab->end;
506 struct nlist *fp = 0;
507 struct nlist *found_sp;
508 unsigned long func_top;
509 boolean_t in_file;
510 int nsym = 0;
511 int i;
512 char *p;
513
514 if (file == 0 && sym == 0)
515 return(0);
516 if (file) {
517 if ((sp = aout_db_search_name(sp, ep, file, N_TEXT, &fp, 0)) == 0)
518 return(0);
519 }
520 if (sym) {
521 for (;;) {
522 sp = aout_db_search_name(sp, ep, sym, (line > 0)? N_FUN: 0, &fp,
523 (ret == (db_sym_t *)0));
524 if (sp == 0)
525 return(nsym);
526 if (ret)
527 break;
528
529 if (strncmp(sp->n_un.n_name, sym, strlen(sym)) == 0)
530 p = sp->n_un.n_name;
531 else
532 p = &sp->n_un.n_name[1];
533
534 if (*name == (char *)0) {
535 *name = p;
536 *len = strlen(p);
537 } else {
538 for (i = 0; i < *len; i++)
539 if ((*name)[i] != p[i]) {
540 *len = i;
541 break;
542 }
543 }
544
545 nsym++;
546 sp++;
547 }
548 }
549 if (line > 0) {
550 if (file && !aout_db_eq_name(fp, file, 0))
551 return(0);
552 found_sp = 0;
553 if (sp->n_type == N_FUN) {
554 /*
555 * qualfied by function name
556 * search backward because line number entries
557 * for the function are above it in this case.
558 */
559 func_top = sp->n_value;
560 if (stab->sorted) {
561 /* symbols with the same value may have been mixed up */
562 do {
563 sp++;
564 } while (sp->n_value == func_top);
565 }
566 for (sp--; sp >= (struct nlist *)stab->start; sp--) {
567 if (sp->n_type != N_SLINE)
568 continue;
569 if (sp->n_value < func_top)
570 break;
571 if (sp->n_desc <= line) {
572 if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
573 found_sp = sp;
574 if (sp->n_desc == line)
575 break;
576 }
577 }
578 if (sp->n_type != N_SLINE || sp->n_value < func_top)
579 return(0);
580 } else {
581 /*
582 * qualified by only file name
583 * search forward in this case
584 */
585 in_file = TRUE;
586 if (stab->sorted) {
587 /* symbols with the same value may have been mixed up */
588 func_top = sp->n_value;
589 do {
590 sp--;
591 } while (sp->n_value == func_top);
592 }
593 for (sp++; sp < ep; sp++) {
594 if (sp->n_type == N_TEXT
595 && aout_db_is_filename(sp->n_un.n_name))
596 break; /* enter into another file */
597 if (sp->n_type == N_SOL) {
598 in_file = aout_db_eq_name(sp, file, 0);
599 continue;
600 }
601 if (!in_file || sp->n_type != N_SLINE)
602 continue;
603 if (sp->n_desc <= line) {
604 if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
605 found_sp = sp;
606 if (sp->n_desc == line)
607 break;
608 }
609 }
610 }
611 sp = found_sp;
612 }
613 *ret = (db_sym_t) sp;
614 return(1);
615 }
616
617 /*
618 * lookup symbol by name
619 */
620 db_sym_t
621 aout_db_lookup(
622 db_symtab_t *stab,
623 char * symstr)
624 {
625 return(db_sym_parse_and_lookup(aout_db_qualified_search, stab, symstr));
626 }
627
628 /*
629 * lookup (possibly incomplete) symbol by name
630 */
631 int
632 aout_db_lookup_incomplete(
633 db_symtab_t *stab,
634 char * symstr,
635 char ** name,
636 int *len,
637 int *toadd)
638 {
639 return(db_sym_parse_and_lookup_incomplete(aout_db_qualified_search,
640 stab, symstr, name, len, toadd));
641 }
642
643 /*
644 * Display possible completion for the symbol
645 */
646 int
647 aout_db_print_completion(stab, symstr)
648 db_symtab_t *stab;
649 char * symstr;
650 {
651
652 return(db_sym_parse_and_print_completion(aout_db_qualified_print_completion,
653 stab, symstr));
654 }
655
656 db_sym_t
657 aout_db_search_symbol(
658 db_symtab_t *symtab,
659 db_addr_t off,
660 db_strategy_t strategy,
661 db_expr_t *diffp) /* in/out */
662 {
663 register unsigned long diff = *diffp;
664 register struct nlist *symp = 0;
665 struct nlist *sp, *ep, *cp;
666 boolean_t first_pass = FALSE;
667
668 sp = (struct nlist *)symtab->start;
669 ep = (struct nlist *)symtab->end;
670
671 if (symtab->sorted) {
672 struct nlist target;
673
674 target.n_value = off;
675 target.n_un.n_name = (char *) 0;
676 target.n_other = (char) 0;
677 db_qsort_limit_search((char *) &target, (char **) &sp, (char **) &ep,
678 sizeof (struct nlist), aout_db_compare_symbols);
679 first_pass = TRUE;
680 }
681
682 try_again:
683 for (cp = ep-1; cp >= sp; cp--) {
684 if (cp->n_un.n_name == 0)
685 continue;
686 if ((cp->n_type & N_STAB) != 0)
687 continue;
688 if (strategy == DB_STGY_XTRN && (cp->n_type & N_EXT) == 0)
689 continue;
690 if (off >= cp->n_value) {
691 if (off - cp->n_value < diff) {
692 diff = off - cp->n_value;
693 symp = cp;
694 if (diff == 0 && (cp->n_type & N_EXT))
695 break;
696 }
697 else if (off - cp->n_value == diff) {
698 if (symp == 0)
699 symp = cp;
700 else if ((symp->n_type & N_EXT) == 0 &&
701 (cp->n_type & N_EXT) != 0)
702 symp = cp; /* pick the external symbol */
703 }
704 }
705 }
706 if (symp == 0) {
707 if (first_pass) {
708 first_pass = FALSE;
709 sp = (struct nlist *) symtab->start;
710 goto try_again;
711 }
712 *diffp = off;
713 }
714 else {
715 *diffp = diff;
716 }
717 return ((db_sym_t)symp);
718 }
719
720 /*
721 * Return the name and value for a symbol.
722 */
723 void
724 aout_db_symbol_values(
725 db_sym_t sym,
726 char **namep,
727 db_expr_t *valuep)
728 {
729 register struct nlist *sp;
730
731 sp = (struct nlist *)sym;
732 if (namep)
733 *namep = sp->n_un.n_name;
734 if (valuep)
735 *valuep = sp->n_value;
736 }
737
738 #define X_DB_MAX_DIFF 8 /* maximum allowable diff at the end of line */
739 extern int db_search_maxoff; /* maximum acceptable offset */
740
741 /*
742 * search symbol by value
743 */
744 db_sym_t
745 aout_db_search_by_addr(
746 db_symtab_t *stab,
747 db_addr_t addr,
748 char **file,
749 char **func,
750 int *line,
751 db_expr_t *diff,
752 int *args)
753 {
754 struct nlist *sp, *cp;
755 register struct nlist *line_sp, *func_sp, *file_sp, *line_func;
756 unsigned long func_diff, line_diff;
757 boolean_t found_line = FALSE;
758 struct nlist *ep = (struct nlist *)stab->end;
759 boolean_t first_pass = FALSE;
760
761 /*
762 * 92-May-16
763 * Added init of these two... not sure if it's correct, but
764 * can't be worse than random values.... -- jfriedl@omron.co.jp
765 */
766 func_diff = line_diff = /*HUGE*/0x0fffffff;
767
768 line_sp = func_sp = file_sp = line_func = 0;
769 *file = *func = 0;
770 *line = 0;
771 *args = -1;
772
773 sp = (struct nlist *)stab->start;
774 if (stab->sorted) {
775 struct nlist target;
776
777 target.n_value = addr;
778 target.n_un.n_name = (char *) 0;
779 target.n_other = (char) 0;
780 db_qsort_limit_search((char *) &target, (char **) &sp,
781 (char **) &ep, sizeof (struct nlist),
782 aout_db_compare_symbols);
783 first_pass = TRUE;
784 }
785
786 for (cp = sp; cp < ep; cp++) {
787 switch(cp->n_type) {
788 case N_SLINE:
789 if (cp->n_value <= addr) {
790 if (line_sp == 0 || line_diff >= addr - cp->n_value) {
791 if (line_func)
792 line_func = 0;
793 line_sp = cp;
794 line_diff = addr - cp->n_value;
795 }
796 }
797 if (cp->n_value >= addr && line_sp)
798 found_line = TRUE;
799 continue;
800 case N_FUN:
801 if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF))
802 && line_func == 0)
803 line_func = cp;
804 continue;
805 case N_SO:
806 if (cp->n_value > addr)
807 continue;
808 if (file_sp == 0 || file_sp->n_value <= cp->n_value)
809 file_sp = cp;
810 continue;
811 case N_TEXT:
812 if (aout_db_is_filename(cp->n_un.n_name)) {
813 if (cp->n_value > addr)
814 continue;
815 if (file_sp == 0 || file_sp->n_value <= cp->n_value)
816 file_sp = cp;
817 } else if (cp->n_value <= addr &&
818 (func_sp == 0 || func_diff > addr - cp->n_value)) {
819 func_sp = cp;
820 func_diff = addr - cp->n_value;
821 }
822 continue;
823 case N_TEXT|N_EXT:
824 if (cp->n_value <= addr &&
825 (func_sp == 0 || func_diff >= addr - cp->n_value)) {
826 func_sp = cp;
827 func_diff = addr - cp->n_value;
828 if (func_diff == 0 && file_sp && func_sp && line_sp == 0)
829 break;
830 }
831 default:
832 if (stab->sorted) {
833 if ((cp->n_value > addr) &&
834 (cp->n_value - addr > db_search_maxoff))
835 break;
836 }
837 continue;
838 }
839 break;
840 }
841 if (first_pass && (!file_sp || !line_sp || !func_sp)) {
842 first_pass = FALSE;
843 cp = sp;
844 sp = (struct nlist *)stab->start;
845 for (; cp >= sp; cp--) {
846 switch(cp->n_type) {
847 case N_SLINE:
848 if (line_sp)
849 found_line = TRUE;
850 continue;
851 case N_FUN:
852 if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF))
853 && line_func == 0)
854 line_func = cp;
855 continue;
856 case N_SO:
857 if (file_sp == 0)
858 file_sp = cp;
859 continue;
860 case N_TEXT:
861 if (aout_db_is_filename(cp->n_un.n_name)) {
862 if (file_sp == 0)
863 file_sp = cp;
864 } else if (func_sp == 0) {
865 func_sp = cp;
866 func_diff = addr - cp->n_value;
867 }
868 continue;
869 case N_TEXT|N_EXT:
870 if (func_sp == 0) {
871 func_sp = cp;
872 func_diff = addr - cp->n_value;
873 if (func_diff == 0 && file_sp && func_sp
874 && line_sp == 0)
875 break;
876 }
877 default:
878 if (line_sp && file_sp &&
879 addr - cp->n_value > db_search_maxoff)
880 break;
881 continue;
882 }
883 break;
884 }
885 }
886 #if 0
887 /*
888 * XXX - barbou@gr.osf.org
889 * I don't know if that code is useful to something, but it makes the -gline
890 * option of gcc useless.
891 */
892 if (line_sp) {
893 if (line_func == 0 || func_sp == 0
894 || line_func->n_value != func_sp->n_value)
895 line_sp = 0;
896 }
897 #else
898 if (line_sp && !found_line) {
899 line_sp = 0;
900 }
901 #endif
902 *diff = 0;
903 if (file_sp) {
904 *diff = addr - file_sp->n_value;
905 *file = file_sp->n_un.n_name;
906 }
907 if (line_sp) {
908 *diff = addr - line_sp->n_value;
909 *line = line_sp->n_desc;
910 }
911 if (func_sp) {
912 *diff = addr - func_sp->n_value;
913 *func = (func_sp->n_un.n_name[0] == '_')?
914 func_sp->n_un.n_name + 1: func_sp->n_un.n_name;
915 if (line_func && (line_func->n_desc & 0x4000))
916 *args = line_func->n_desc & 0x3ff;
917 }
918 return((db_sym_t) func_sp);
919 }
920
921 /*
922 * Find filename and lineno within, given the current pc.
923 */
924 boolean_t
925 aout_db_line_at_pc(
926 db_symtab_t *stab,
927 db_sym_t sym,
928 char **file,
929 int *line,
930 db_expr_t pc)
931 {
932 char *func;
933 db_expr_t diff;
934 boolean_t found;
935 int args;
936
937 found = (aout_db_search_by_addr(stab, (unsigned)pc, file, &func, line,
938 &diff, &args)
939 != DB_SYM_NULL);
940 return(found && func && *file);
941 }
942
943 /*
944 * Initialization routine for a.out files.
945 */
946 void
947 aout_db_init(void)
948 {
949 extern struct mach_header _mh_execute_header;
950
951 aout_db_sym_init((char *) &_mh_execute_header,
952 (char *)0, "mach", (char *)0);
953 }
954
955 #endif /* DB_NO_AOUT */