2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
16 * Carnegie Mellon requests users of this software to return to
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
26 * $FreeBSD: src/sys/ddb/db_aout.c,v 1.27 1999/08/28 00:41:05 peter Exp $
27 * $DragonFly: src/sys/ddb/db_aout.c,v 1.8 2006/12/28 21:24:01 dillon Exp $
31 * Author: David B. Golub, Carnegie Mellon University
35 * Symbol table routines for a.out format files.
40 #include <sys/param.h>
41 #include <sys/systm.h>
43 #include <machine/bootinfo.h>
46 #include <ddb/db_sym.h>
48 #define _AOUT_INCLUDE_
53 * An a.out symbol table as loaded into the kernel debugger:
55 * symtab -> size of symbol entries, in bytes
56 * sp -> first symbol entry
58 * ep -> last symbol entry + 1
59 * strtab == start of string table
60 * size of string table in bytes,
65 static void X_db_sym_init (int *symtab
, char *esymtab
, char *name
);
67 * Find pointers to the start and end of the symbol entries,
68 * given a pointer to the start of the symbol table.
70 #define db_get_aout_symtab(symtab, sp, ep) \
71 (sp = (struct nlist *)((symtab) + 1), \
72 ep = (struct nlist *)((char *)sp + *(symtab)))
76 * symtab: pointer to start of symbol table
77 * esymtab: pointer to end of string table, for checking - rounded up to
81 X_db_sym_init(int *symtab
, char *esymtab
, char *name
)
83 struct nlist
*sym_start
, *sym_end
;
89 kprintf ("DDB: no symbols\n");
93 db_get_aout_symtab(symtab
, sym_start
, sym_end
);
95 strtab
= (char *)sym_end
;
96 strlen
= *(int *)strtab
;
98 if (strtab
+ ((strlen
+ sizeof(int) - 1) & ~(sizeof(int)-1))
101 db_printf("[ %s symbol table not valid ]\n", name
);
105 db_printf("[ preserving %#x bytes of %s symbol table ]\n",
106 esymtab
- (char *)symtab
, name
);
108 for (sp
= sym_start
; sp
< sym_end
; sp
++) {
110 strx
= sp
->n_un
.n_strx
;
113 db_printf("Bad string table index (%#x)\n", strx
);
117 sp
->n_un
.n_name
= strtab
+ strx
;
121 db_add_symbol_table((char *)sym_start
, (char *)sym_end
, name
,
126 X_db_lookup(db_symtab_t
*stab
, const char *symstr
)
128 struct nlist
*sp
, *ep
;
130 sp
= (struct nlist
*)stab
->start
;
131 ep
= (struct nlist
*)stab
->end
;
133 for (; sp
< ep
; sp
++) {
134 if (sp
->n_un
.n_name
== 0)
136 if ((sp
->n_type
& N_STAB
) == 0 &&
137 sp
->n_un
.n_name
!= 0 &&
138 db_eqname(sp
->n_un
.n_name
, symstr
, '_'))
140 return ((db_sym_t
)sp
);
143 return ((db_sym_t
)0);
151 X_db_search_symbol(db_symtab_t
*symtab
, db_addr_t off
, db_strategy_t strategy
,
154 unsigned int diff
= *diffp
;
155 struct nlist
*symp
= 0;
156 struct nlist
*sp
, *ep
;
158 sp
= (struct nlist
*)symtab
->start
;
159 ep
= (struct nlist
*)symtab
->end
;
161 for (; sp
< ep
; sp
++) {
162 if (sp
->n_un
.n_name
== 0)
164 if ((sp
->n_type
& N_STAB
) != 0 || (sp
->n_type
& N_TYPE
) == N_FN
)
166 if (off
>= sp
->n_value
) {
167 if (off
- sp
->n_value
< diff
) {
168 diff
= off
- sp
->n_value
;
171 if (strategy
== DB_STGY_PROC
&&
172 sp
->n_type
== (N_TEXT
|N_EXT
))
174 if (strategy
== DB_STGY_ANY
&&
175 (sp
->n_type
& N_EXT
))
179 else if (off
- sp
->n_value
== diff
) {
182 else if ((symp
->n_type
& N_EXT
) == 0 &&
183 (sp
->n_type
& N_EXT
) != 0)
184 symp
= sp
; /* pick the external symbol */
194 return ((db_sym_t
)symp
);
198 * Return the name and value for a symbol.
201 X_db_symbol_values(db_symtab_t
*symtab
, c_db_sym_t sym
, const char **namep
,
204 const struct nlist
*sp
;
206 sp
= (const struct nlist
*)sym
;
208 *namep
= sp
->n_un
.n_name
;
210 *valuep
= sp
->n_value
;
215 X_db_line_at_pc(db_symtab_t
*symtab
, c_db_sym_t cursym
, char **filename
,
216 int *linenum
, db_expr_t off
)
218 struct nlist
*sp
, *ep
;
219 unsigned long sodiff
= -1UL, lndiff
= -1UL, ln
= 0;
222 sp
= (struct nlist
*)symtab
->start
;
223 ep
= (struct nlist
*)symtab
->end
;
226 * XXX - this used to remove "gcc_compiled.", but that is obsolete. We
227 * now remove unwanted names using symorder.
229 #define NEWSRC(str) 0
231 for (; sp
< ep
; sp
++) {
234 * Prevent bogus linenumbers in case module not compiled
235 * with debugging options
238 if (sp
->n_value
<= off
&& (off
- sp
->n_value
) <= sodiff
&&
239 NEWSRC(sp
->n_un
.n_name
)) {
241 if ((sp
->n_type
& N_TYPE
) == N_FN
|| NEWSRC(sp
->n_un
.n_name
)) {
242 sodiff
= lndiff
= -1UL;
247 if (sp
->n_type
== N_SO
&& *sp
->n_un
.n_name
!= '/') {
248 if (sp
->n_value
<= off
&& (off
- sp
->n_value
) < sodiff
) {
249 sodiff
= off
- sp
->n_value
;
250 fname
= sp
->n_un
.n_name
;
255 if (sp
->n_type
!= N_SLINE
)
258 if (sp
->n_value
> off
)
261 if (off
- sp
->n_value
< lndiff
) {
262 lndiff
= off
- sp
->n_value
;
267 if (fname
!= NULL
&& ln
!= 0) {
277 X_db_sym_numargs(db_symtab_t
*symtab
, c_db_sym_t cursym
, int *nargp
,
280 struct nlist
*sp
, *ep
;
282 int maxnarg
= *nargp
, nargs
= 0;
287 addr
= ((const struct nlist
*)cursym
)->n_value
;
288 sp
= (struct nlist
*)symtab
->start
;
289 ep
= (struct nlist
*)symtab
->end
;
291 for (; sp
< ep
; sp
++) {
292 if (sp
->n_type
== N_FUN
&& sp
->n_value
== addr
) {
293 while (++sp
< ep
&& sp
->n_type
== N_PSYM
) {
294 if (nargs
>= maxnarg
)
297 *argnamep
++ = sp
->n_un
.n_name
?sp
->n_un
.n_name
:"???";
299 /* XXX - remove trailers */
300 char *cp
= *(argnamep
-1);
301 while (*cp
!= '\0' && *cp
!= ':') cp
++;
302 if (*cp
== ':') *cp
= '\0';
313 * Initialization routine for a.out files.
319 if (bootinfo
.bi_esymtab
!= bootinfo
.bi_symtab
)
320 X_db_sym_init((int *)bootinfo
.bi_symtab
,
321 (char *)((bootinfo
.bi_esymtab
+ sizeof(int) - 1)
322 & ~(sizeof(int) - 1)),
329 * Read symbol table from file.
330 * (should be somewhere else)
332 #include <boot_ufs/file_io.h>
333 #include <vm/vm_kern.h>
335 read_symtab_from_file(struct file
*fp
, char *symtab_name
)
338 kern_return_t result
;
343 vm_size_t table_size
;
346 if (!get_symtab(fp
, &symoff
, &symsize
)) {
347 boot_printf("[ error %d reading %s file header ]\n",
348 result
, symtab_name
);
352 stroff
= symoff
+ symsize
;
353 result
= read_file(fp
, (vm_offset_t
)stroff
,
354 (vm_offset_t
)&strsize
, sizeof(strsize
), &resid
);
355 if (result
|| resid
) {
356 boot_printf("[ no valid symbol table present for %s ]\n",
361 table_size
= sizeof(int) + symsize
+ strsize
;
362 table_size
= (table_size
+ sizeof(int)-1) & ~(sizeof(int)-1);
364 symtab
= kmem_alloc_wired(&kernel_map
, table_size
);
366 *(int *)symtab
= symsize
;
368 result
= read_file(fp
, symoff
,
369 symtab
+ sizeof(int), symsize
, &resid
);
370 if (result
|| resid
) {
371 boot_printf("[ error %d reading %s symbol table ]\n",
372 result
, symtab_name
);
376 result
= read_file(fp
, stroff
,
377 symtab
+ sizeof(int) + symsize
, strsize
, &resid
);
378 if (result
|| resid
) {
379 boot_printf("[ error %d reading %s string table ]\n",
380 result
, symtab_name
);
384 X_db_sym_init((int *)symtab
,
385 (char *)(symtab
+ table_size
),