1 /* $NetBSD: db_aout.c,v 1.40 2007/02/21 22:59:56 thorpej Exp $ */
4 * Mach Operating System
5 * Copyright (c) 1991,1990 Carnegie Mellon University
8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: db_aout.c,v 1.40 2007/02/21 22:59:56 thorpej Exp $");
32 #include <sys/param.h>
33 #include <sys/systm.h>
36 #include <machine/db_machdep.h>
38 #include <ddb/db_sym.h>
39 #include <ddb/db_output.h>
40 #include <ddb/db_extern.h>
42 #ifdef DB_AOUT_SYMBOLS
44 #include <ddb/db_aout.h>
46 static bool db_aout_sym_init(int, void *, void *, const char *);
47 static db_sym_t
db_aout_lookup(db_symtab_t
*, const char *);
48 static db_sym_t
db_aout_search_symbol(db_symtab_t
*, db_addr_t
, db_strategy_t
,
50 static void db_aout_symbol_values(db_symtab_t
*, db_sym_t
, const char **,
52 static bool db_aout_line_at_pc(db_symtab_t
*, db_sym_t
, char **, int *,
54 static bool db_aout_sym_numargs(db_symtab_t
*, db_sym_t
, int *, char **);
55 static void db_aout_forall(db_symtab_t
*, db_forall_func_t db_forall_func
,
57 static int db_add_symbol_table(char *, char *, const char *, char *);
59 /* Only one symbol table, please */
60 static db_symtab_t db_symtabs
;
63 const db_symformat_t db_symformat_aout
= {
67 db_aout_search_symbol
,
68 db_aout_symbol_values
,
75 * An a.out symbol table as loaded into the kernel debugger:
77 * symtab -> size of symbol entries, in bytes
78 * sp -> first symbol entry
80 * ep -> last symbol entry + 1
81 * strtab == start of string table
82 * size of string table in bytes,
88 * Find the symbol table and strings; tell ddb about them.
92 int symsize
, /* size of symbol table */
93 void *vsymtab
, /* pointer to start of symbol table */
94 void *vesymtab
, /* pointer to end of string table,
95 for checking - rounded up to integer
100 struct nlist
*sym_start
, *sym_end
;
106 if (ALIGNED_POINTER(vsymtab
, long) == 0) {
107 printf("[ %s symbol table has bad start address %p ]\n",
113 * Find pointers to the start and end of the symbol entries,
114 * given a pointer to the start of the symbol table.
116 sym_start
= (struct nlist
*)vsymtab
;
117 sym_end
= (struct nlist
*)((char *)sym_start
+ symsize
);
119 strtab
= (char *)sym_end
;
120 if (ALIGNED_POINTER(strtab
, int) == 0) {
121 printf("[ %s symbol table has bad string table address %p ]\n",
125 slen
= *(int *)strtab
;
127 estrtab
= strtab
+ slen
;
129 #define round_to_size(x) \
130 (((vaddr_t)(x) + sizeof(vsize_t) - 1) & ~(sizeof(vsize_t) - 1))
132 if (round_to_size(estrtab
) != round_to_size(vesymtab
)) {
133 printf("[ %s a.out symbol table not valid ]\n", name
);
138 for (sp
= sym_start
; sp
< sym_end
; sp
++) {
140 strx
= sp
->n_un
.n_strx
;
143 printf("[ %s has bad a.out string table "
144 "index (0x%x) ]\n", name
, strx
);
149 sp
->n_un
.n_name
= strtab
+ strx
;
156 if (db_add_symbol_table((char *)sym_start
, (char *)sym_end
, name
,
158 printf("[ using %ld bytes of %s a.out symbol table ]\n",
159 (long)vesymtab
- (long)vsymtab
, name
);
167 db_aout_lookup(db_symtab_t
*stab
, const char *symstr
)
169 struct nlist
*sp
, *ep
;
173 sp
= (struct nlist
*)stab
->start
;
174 ep
= (struct nlist
*)stab
->end
;
176 for (; sp
< ep
; sp
++) {
177 if (sp
->n_un
.n_name
== 0)
179 if ((sp
->n_type
& N_STAB
) == 0 &&
180 sp
->n_un
.n_name
!= 0 &&
181 db_eqname(sp
->n_un
.n_name
, symstr
, '_'))
182 return ((db_sym_t
)sp
);
184 return ((db_sym_t
)0);
188 db_aout_search_symbol(db_symtab_t
*symtab
, db_addr_t off
,
189 db_strategy_t strategy
, db_expr_t
*diffp
)
191 unsigned int diff
= *diffp
;
192 struct nlist
*symp
= 0;
193 struct nlist
*sp
, *ep
;
195 symtab
= &db_symtabs
;
197 sp
= (struct nlist
*)symtab
->start
;
198 ep
= (struct nlist
*)symtab
->end
;
200 for (; sp
< ep
; sp
++) {
201 if (sp
->n_un
.n_name
== 0)
203 if ((sp
->n_type
& N_STAB
) != 0 || (sp
->n_type
& N_TYPE
) == N_FN
)
205 if (off
>= sp
->n_value
) {
206 if (off
- sp
->n_value
< diff
) {
207 diff
= off
- sp
->n_value
;
210 ((strategy
== DB_STGY_PROC
&&
211 sp
->n_type
== (N_TEXT
|N_EXT
)) ||
212 (strategy
== DB_STGY_ANY
&&
213 (sp
->n_type
& N_EXT
))))
216 else if (off
- sp
->n_value
== diff
) {
219 else if ((symp
->n_type
& N_EXT
) == 0 &&
220 (sp
->n_type
& N_EXT
) != 0)
221 /* pick the external symbol */
230 return ((db_sym_t
)symp
);
234 * Return the name and value for a symbol.
237 db_aout_symbol_values(db_symtab_t
*symtab
, db_sym_t sym
,
238 const char **namep
, db_expr_t
*valuep
)
242 sp
= (struct nlist
*)sym
;
244 *namep
= sp
->n_un
.n_name
;
246 *valuep
= sp
->n_value
;
251 db_aout_line_at_pc(db_symtab_t
*symtab
, db_sym_t cursym
,
252 char **filename
, int *linenum
, db_expr_t off
)
254 struct nlist
*sp
, *ep
;
255 unsigned long sodiff
= -1UL, lndiff
= -1UL, ln
= 0;
258 symtab
= &db_symtabs
;
260 sp
= (struct nlist
*)symtab
->start
;
261 ep
= (struct nlist
*)symtab
->end
;
263 /* XXX - gcc specific */
264 #define NEWSRC(str) ((str) != NULL && \
265 (str)[0] == 'g' && strcmp((str), "gcc_compiled.") == 0)
267 for (; sp
< ep
; sp
++) {
270 * Prevent bogus linenumbers in case module not compiled
271 * with debugging options
274 if (sp
->n_value
<= off
&& (off
- sp
->n_value
) <= sodiff
&&
275 NEWSRC(sp
->n_un
.n_name
)) {
277 if ((sp
->n_type
& N_TYPE
) == N_FN
|| NEWSRC(sp
->n_un
.n_name
)) {
278 sodiff
= lndiff
= -1UL;
283 if (sp
->n_type
== N_SO
) {
284 if (sp
->n_value
<= off
&& (off
- sp
->n_value
) < sodiff
) {
285 sodiff
= off
- sp
->n_value
;
286 fname
= sp
->n_un
.n_name
;
291 if (sp
->n_type
!= N_SLINE
)
294 if (sp
->n_value
> off
)
297 if (off
- sp
->n_value
< lndiff
) {
298 lndiff
= off
- sp
->n_value
;
303 if (fname
!= NULL
&& ln
!= 0) {
313 db_aout_sym_numargs(db_symtab_t
*symtab
, db_sym_t cursym
, int *nargp
,
316 struct nlist
*sp
, *ep
;
318 int maxnarg
= *nargp
, nargs
= 0;
319 static char question
[] = "???";
321 if ((struct nlist
*)cursym
== NULL
)
324 symtab
= &db_symtabs
;
326 addr
= ((struct nlist
*)cursym
)->n_value
;
327 sp
= (struct nlist
*)symtab
->start
;
328 ep
= (struct nlist
*)symtab
->end
;
330 for (; sp
< ep
; sp
++) {
331 if (sp
->n_type
== N_FUN
&& sp
->n_value
== addr
) {
332 while (++sp
< ep
&& sp
->n_type
== N_PSYM
) {
333 if (nargs
>= maxnarg
)
336 *argnamep
++ = sp
->n_un
.n_name
?
337 sp
->n_un
.n_name
: question
;
339 /* XXX - remove trailers */
340 char *cp
= *(argnamep
-1);
341 while (*cp
!= '\0' && *cp
!= ':') cp
++;
342 if (*cp
== ':') *cp
= '\0';
353 db_aout_forall(db_symtab_t
*stab
, db_forall_func_t db_forall_func
, void *arg
)
355 static char suffix
[2];
356 struct nlist
*sp
, *ep
;
360 sp
= (struct nlist
*)stab
->start
;
361 ep
= (struct nlist
*)stab
->end
;
363 for (; sp
< ep
; sp
++) {
364 if (sp
->n_un
.n_name
== 0)
366 if ((sp
->n_type
& N_STAB
) == 0 && sp
->n_un
.n_name
!= 0) {
368 switch(sp
->n_type
& N_TYPE
) {
387 (*db_forall_func
)(stab
, (db_sym_t
)sp
, sp
->n_un
.n_name
,
395 * Add symbol table, with given name, to symbol tables.
398 db_add_symbol_table(char *start
, char *end
, const char *name
, char *ref
)
401 db_symtabs
.start
= start
;
402 db_symtabs
.end
= end
;
403 db_symtabs
.name
= name
;
404 db_symtabs
.private = ref
;
409 #endif /* DB_AOUT_SYMBOLS */