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