]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/db_gcc_aout.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
31 * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
33 * Permission is hereby granted to use, copy, modify and freely distribute
34 * the software in this file and its documentation for any purpose without
35 * fee, provided that the above copyright notice appears in all copies and
36 * that both the copyright notice and this permission notice appear in
37 * supporting documentation. Further, provided that the name of Open
38 * Software Foundation, Inc. ("OSF") not be used in advertising or
39 * publicity pertaining to distribution of the software without prior
40 * written permission from OSF. OSF makes no representations about the
41 * suitability of this software for any purpose. It is provided "as is"
42 * without express or implied warranty.
47 * Revision 1.1.1.1 1998/09/22 21:05:36 wsanchez
48 * Import of Mac OS X kernel (~semeria)
50 * Revision 1.1.1.1 1998/03/07 02:25:37 wsanchez
51 * Import of OSF Mach kernel (~mburg)
53 * Revision 1.2.2.3 1994/01/28 17:23:00 chasb
55 * [1994/01/27 19:40:16 chasb]
57 * Revision 1.2.2.2 1993/06/09 02:27:36 gm
58 * Added to OSF/1 R1.3 from NMK15.0.
59 * [1993/06/02 21:04:03 jeffc]
61 * Revision 1.2 1993/04/19 16:13:10 devrcs
62 * pick up file_io.h from bootstrap directory
63 * [1993/02/27 15:01:09 david]
65 * Added new arguments and a missing one to db_add_symbol_table
69 * Added gcc symbol table handling based on db_aout.c (Revsion 2.4)
72 * Revision 1.1 1992/09/30 02:02:23 robert
79 * Revision 2.1 91/07/31 13:13:51 jeffreyh
82 * 31-Jul-91 Jeffrey Heller (tak) at Open Software Foundation
83 * Added gcc symbol table handling based on db_aout.c (Revsion 2.4)
88 * Mach Operating System
89 * Copyright (c) 1991,1990 Carnegie Mellon University
90 * All Rights Reserved.
92 * Permission to use, copy, modify and distribute this software and its
93 * documentation is hereby granted, provided that both the copyright
94 * notice and this permission notice appear in all copies of the
95 * software, derivative works or modified versions, and any portions
96 * thereof, and that both notices appear in supporting documentation.
98 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
99 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
100 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
102 * Carnegie Mellon requests users of this software to return to
104 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
105 * School of Computer Science
106 * Carnegie Mellon University
107 * Pittsburgh PA 15213-3890
109 * any improvements or extensions that they make and grant Carnegie Mellon
110 * the rights to redistribute these changes.
115 * Symbol table routines for a.out format files.
118 #include <mach/boolean.h>
119 #include <machine/db_machdep.h> /* data types */
120 #include <ddb/db_sym.h>
124 #include <ddb/nlist.h> /* a.out symbol table */
125 #include <i386/stab.h>
128 * An a.out symbol table as loaded into the kernel debugger:
130 * symtab -> size of symbol entries, in bytes
131 * sp -> first symbol entry
133 * ep -> last symbol entry + 1
134 * strtab == start of string table
135 * size of string table in bytes,
136 * including this word
141 * Find pointers to the start and end of the symbol entries,
142 * given a pointer to the start of the symbol table.
144 #define db_get_aout_symtab(symtab, sp, ep) \
145 (sp = (struct nlist *)((symtab) + 1), \
146 ep = (struct nlist *)((char *)sp + *(symtab)))
148 X_db_sym_init(symtab
, esymtab
, name
)
149 int * symtab
; /* pointer to start of symbol table */
150 char * esymtab
; /* pointer to end of string table,
151 for checking - rounded up to integer
155 register struct nlist
*sym_start
, *sym_end
;
156 register struct nlist
*sp
;
157 register char * strtab
;
160 db_get_aout_symtab(symtab
, sym_start
, sym_end
);
162 strtab
= (char *)sym_end
;
163 strlen
= *(int *)strtab
;
165 if (strtab
+ ((strlen
+ sizeof(int) - 1) & ~(sizeof(int)-1))
168 db_printf("[ %s symbol table not valid ]\n", name
);
172 db_printf("[ preserving %#x bytes of %s symbol table ]\n",
173 esymtab
- (char *)symtab
, name
);
175 for (sp
= sym_start
; sp
< sym_end
; sp
++) {
177 strx
= sp
->n_un
.n_strx
;
180 db_printf("Bad string table index (%#x)\n", strx
);
184 sp
->n_un
.n_name
= strtab
+ strx
;
188 db_add_symbol_table(sym_start
, sym_end
, name
, (char *)symtab
,
193 * check file name or not (check xxxx.x pattern)
196 X_db_is_filename(name
)
210 * special name comparison routine with a name in the symbol table entry
213 X_db_eq_name(sp
, name
)
217 register char *s1
, *s2
;
219 s1
= sp
->n_un
.n_name
;
221 if (*s1
== '_' && *s2
&& *s2
!= '_')
224 if (*s1
++ != *s2
++) {
226 * check .c .o file name comparison case
228 if (*s2
== 0 && sp
->n_un
.n_name
<= s1
- 2
229 && s1
[-2] == '.' && s1
[-1] == 'o')
235 * do special check for
237 * xxx.ttt for N_DATA and N_BSS
239 return(*s1
== 0 || (*s1
== ':' && sp
->n_type
== N_FUN
) ||
240 (*s1
== '.' && (sp
->n_type
== N_DATA
|| sp
->n_type
== N_BSS
)));
244 * search a symbol table with name and type
245 * fp(in,out): last found text file name symbol entry
248 X_db_search_name(sp
, ep
, name
, type
, fp
)
249 register struct nlist
*sp
;
255 struct nlist
*file_sp
= *fp
;
256 struct nlist
*found_sp
= 0;
258 for ( ; sp
< ep
; sp
++) {
259 if (sp
->n_type
== N_TEXT
&& X_db_is_filename(sp
->n_un
.n_name
))
262 if (sp
->n_type
== type
) {
263 if (X_db_eq_name(sp
, name
))
266 if (sp
->n_type
== N_SO
)
270 if (sp
->n_type
& N_STAB
)
272 if (sp
->n_un
.n_name
&& X_db_eq_name(sp
, name
)) {
274 * In case of qaulified search by a file,
275 * return it immediately with some check.
276 * Otherwise, search external one
279 if ((file_sp
== *fp
) || (sp
->n_type
& N_EXT
))
281 } else if (sp
->n_type
& N_EXT
)
291 * search a symbol with file, func and line qualification
294 X_db_qualified_search(stab
, file
, sym
, line
)
300 register struct nlist
*sp
= (struct nlist
*)stab
->start
;
301 struct nlist
*ep
= (struct nlist
*)stab
->end
;
302 struct nlist
*fp
= 0;
303 struct nlist
*found_sp
;
307 if (file
== 0 && sym
== 0)
310 if ((sp
= X_db_search_name(sp
, ep
, file
, N_TEXT
, &fp
)) == 0)
314 sp
= X_db_search_name(sp
, ep
, sym
, (line
> 0)? N_FUN
: 0, &fp
);
319 if (file
&& !X_db_eq_name(fp
, file
))
322 if (sp
->n_type
== N_FUN
) {
324 * qualfied by function name
325 * search backward because line number entries
326 * for the function are above it in this case.
328 func_top
= sp
->n_value
;
329 for (sp
--; sp
>= (struct nlist
*)stab
->start
; sp
--) {
330 if (sp
->n_type
!= N_SLINE
)
332 if (sp
->n_value
< func_top
)
334 if (sp
->n_desc
<= line
) {
335 if (found_sp
== 0 || found_sp
->n_desc
< sp
->n_desc
)
337 if (sp
->n_desc
== line
)
341 if (sp
->n_type
!= N_SLINE
|| sp
->n_value
< func_top
)
345 * qualified by only file name
346 * search forward in this case
349 for (sp
++; sp
< ep
; sp
++) {
350 if (sp
->n_type
== N_TEXT
351 && X_db_is_filename(sp
->n_un
.n_name
))
352 break; /* enter into another file */
353 if (sp
->n_type
== N_SOL
) {
354 in_file
= X_db_eq_name(sp
, file
);
357 if (!in_file
|| sp
->n_type
!= N_SLINE
)
359 if (sp
->n_desc
<= line
) {
360 if (found_sp
== 0 || found_sp
->n_desc
< sp
->n_desc
)
362 if (sp
->n_desc
== line
)
373 * lookup symbol by name
376 X_db_lookup(stab
, symstr
)
387 struct nlist
*found
= 0;
390 * disassemble component: [file_name:]symbol[:line_nubmer]
392 component
[0] = symstr
;
393 component
[1] = component
[2] = 0;
394 for (p
= symstr
, n
= 1; *p
; p
++) {
399 component
[n
++] = p
+1;
407 if (*p
>= '0' && *p
<= '9') {
410 for (line_number
= 0; *p
; p
++) {
411 if (*p
< '0' || *p
> '9')
413 line_number
= line_number
*10 + *p
- '0';
419 if (X_db_is_filename(component
[0])) {
420 file_name
= component
[0];
424 sym_name
= component
[0];
427 file_name
= component
[0];
428 sym_name
= component
[1];
430 found
= X_db_qualified_search(stab
, file_name
, sym_name
, line_number
);
434 component
[n
][-1] = ':';
435 return((db_sym_t
) found
);
439 X_db_search_symbol(symtab
, off
, strategy
, diffp
)
440 db_symtab_t
* symtab
;
443 db_strategy_t strategy
;
444 db_expr_t
*diffp
; /* in/out */
446 register unsigned int diff
= *diffp
;
447 register struct nlist
*symp
= 0;
448 register struct nlist
*sp
, *ep
;
450 sp
= (struct nlist
*)symtab
->start
;
451 ep
= (struct nlist
*)symtab
->end
;
453 for (; sp
< ep
; sp
++) {
454 if (sp
->n_un
.n_name
== 0)
456 if ((sp
->n_type
& N_STAB
) != 0)
458 if (off
>= sp
->n_value
) {
459 if (off
- sp
->n_value
< diff
) {
460 diff
= off
- sp
->n_value
;
462 if (diff
== 0 && (sp
->n_type
& N_EXT
))
465 else if (off
- sp
->n_value
== diff
) {
468 else if ((symp
->n_type
& N_EXT
) == 0 &&
469 (sp
->n_type
& N_EXT
) != 0)
470 symp
= sp
; /* pick the external symbol */
480 return ((db_sym_t
)symp
);
484 * Return the name and value for a symbol.
487 X_db_symbol_values(sym
, namep
, valuep
)
492 register struct nlist
*sp
;
494 sp
= (struct nlist
*)sym
;
496 *namep
= sp
->n_un
.n_name
;
498 *valuep
= sp
->n_value
;
501 #define X_DB_MAX_DIFF 8 /* maximum allowable diff at the end of line */
504 * search symbol by value
506 X_db_search_by_addr(stab
, addr
, file
, func
, line
, diff
)
508 register unsigned addr
;
514 register struct nlist
*sp
;
515 register struct nlist
*line_sp
, *func_sp
, *file_sp
, *line_func
;
516 register func_diff
, line_diff
;
517 boolean_t found_line
= FALSE
;
518 struct nlist
*ep
= (struct nlist
*)stab
->end
;
520 line_sp
= func_sp
= file_sp
= line_func
= 0;
523 for (sp
= (struct nlist
*)stab
->start
; sp
< ep
; sp
++) {
526 if (sp
->n_value
<= addr
) {
527 if (line_sp
== 0 || line_diff
>= addr
- sp
->n_value
) {
531 line_diff
= addr
- sp
->n_value
;
534 if (sp
->n_value
>= addr
&& line_sp
)
538 if ((found_line
|| (line_sp
&& line_diff
< X_DB_MAX_DIFF
))
543 if (X_db_is_filename(sp
->n_un
.n_name
)) {
544 if (sp
->n_value
> addr
)
546 if (file_sp
== 0 || file_sp
->n_value
< sp
->n_value
)
548 } else if (sp
->n_value
<= addr
&&
549 (func_sp
== 0 || func_diff
> addr
- sp
->n_value
)) {
551 func_diff
= addr
- sp
->n_value
;
555 if (sp
->n_value
<= addr
&&
556 (func_sp
== 0 || func_diff
>= addr
- sp
->n_value
)) {
558 func_diff
= addr
- sp
->n_value
;
559 if (func_diff
== 0 && file_sp
&& func_sp
)
568 if (line_func
== 0 || func_sp
== 0
569 || line_func
->n_value
!= func_sp
->n_value
)
573 *diff
= addr
- file_sp
->n_value
;
574 *file
= file_sp
->n_un
.n_name
;
577 *diff
= addr
- func_sp
->n_value
;
578 *func
= (func_sp
->n_un
.n_name
[0] == '_')?
579 func_sp
->n_un
.n_name
+ 1: func_sp
->n_un
.n_name
;
582 *diff
= addr
- line_sp
->n_value
;
583 *line
= line_sp
->n_desc
;
585 return(file_sp
|| func_sp
|| line_sp
);
590 X_db_line_at_pc(stab
, sym
, file
, line
, pc
)
601 found
= X_db_search_by_addr(stab
,(unsigned)pc
,file
,&func
,line
,&diff
);
602 return(found
&& func
&& *file
);
606 * Initialization routine for a.out files.
613 if (esym
> (char *)&end
) {
614 X_db_sym_init((int *)&end
, esym
, "mach");
619 * Read symbol table from file.
620 * (should be somewhere else)
622 #include <bootstrap/file_io.h>
623 #include <vm/vm_kern.h>
625 read_symtab_from_file(fp
, symtab_name
)
630 kern_return_t result
;
635 vm_size_t table_size
;
638 if (!get_symtab(fp
, &symoff
, &symsize
)) {
639 boot_printf("[ error %d reading %s file header ]\n",
640 result
, symtab_name
);
644 stroff
= symoff
+ symsize
;
645 result
= read_file(fp
, (vm_offset_t
)stroff
,
646 (vm_offset_t
)&strsize
, sizeof(strsize
), &resid
);
647 if (result
|| resid
) {
648 boot_printf("[ no valid symbol table present for %s ]\n",
653 table_size
= sizeof(int) + symsize
+ strsize
;
654 table_size
= (table_size
+ sizeof(int)-1) & ~(sizeof(int)-1);
656 result
= kmem_alloc_wired(kernel_map
, &symtab
, table_size
);
658 boot_printf("[ error %d allocating space for %s symbol table ]\n",
659 result
, symtab_name
);
663 *(int *)symtab
= symsize
;
665 result
= read_file(fp
, symoff
,
666 symtab
+ sizeof(int), symsize
, &resid
);
667 if (result
|| resid
) {
668 boot_printf("[ error %d reading %s symbol table ]\n",
669 result
, symtab_name
);
673 result
= read_file(fp
, stroff
,
674 symtab
+ sizeof(int) + symsize
, strsize
, &resid
);
675 if (result
|| resid
) {
676 boot_printf("[ error %d reading %s string table ]\n",
677 result
, symtab_name
);
681 X_db_sym_init((int *)symtab
,
682 (char *)(symtab
+ table_size
),
687 #endif /* DB_GCC_AOUT */