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