1 /* $NetBSD: db_elf.c,v 1.26 2009/03/07 22:02:17 ad Exp $ */
4 * Copyright (c) 1997, 2009 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center, and by Andrew Doran.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: db_elf.c,v 1.26 2009/03/07 22:02:17 ad Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
42 #include <machine/pmap.h>
43 #include <machine/vmparam.h>
48 #error Must define DB_ELFSIZE!
51 #define ELFSIZE DB_ELFSIZE
53 #include <sys/exec_elf.h>
55 static char *db_elf_find_strtab(db_symtab_t
*);
57 #define STAB_TO_SYMSTART(stab) ((Elf_Sym *)((stab)->start))
58 #define STAB_TO_SYMEND(stab) ((Elf_Sym *)((stab)->end))
59 #define STAB_TO_EHDR(stab) ((Elf_Ehdr *)((stab)->private))
60 #define STAB_TO_SHDR(stab, e) ((Elf_Shdr *)((stab)->private + (e)->e_shoff))
62 static bool db_elf_sym_init(int, void *, void *, const char *);
63 static db_sym_t
db_elf_lookup(db_symtab_t
*, const char *);
64 static db_sym_t
db_elf_search_symbol(db_symtab_t
*, db_addr_t
, db_strategy_t
,
66 static void db_elf_symbol_values(db_symtab_t
*, db_sym_t
, const char **,
68 static bool db_elf_line_at_pc(db_symtab_t
*, db_sym_t
, char **, int *,
70 static bool db_elf_sym_numargs(db_symtab_t
*, db_sym_t
, int *, char **);
71 static void db_elf_forall(db_symtab_t
*, db_forall_func_t db_forall_func
,
74 const db_symformat_t db_symformat_elf
= {
85 static db_symtab_t db_symtabs
;
88 * Add symbol table, with given name, to symbol tables.
91 db_add_symbol_table(char *start
, char *end
, const char *name
, char *ref
)
94 db_symtabs
.start
= start
;
96 db_symtabs
.name
= name
;
97 db_symtabs
.private = ref
;
103 * Find the symbol table and strings; tell ddb about them.
107 int symsize
, /* size of symbol table */
108 void *symtab
, /* pointer to start of symbol table */
109 void *esymtab
, /* pointer to end of string table,
110 for checking - rounded up to integer
117 Elf_Sym
*symp
, *symtab_start
, *symtab_end
;
118 char *strtab_start
, *strtab_end
;
121 if (ALIGNED_POINTER(symtab
, long) == 0) {
122 printf("[ %s symbol table has bad start address %p ]\n",
127 symtab_start
= symtab_end
= NULL
;
128 strtab_start
= strtab_end
= NULL
;
131 * The format of the symbols loaded by the boot program is:
134 * first section header
137 * last section header
138 * first symbol or string table section
141 * last symbol or string table section
145 * Validate the Elf header.
147 elf
= (Elf_Ehdr
*)symtab
;
148 if (memcmp(elf
->e_ident
, ELFMAG
, SELFMAG
) != 0 ||
149 elf
->e_ident
[EI_CLASS
] != ELFCLASS
)
152 switch (elf
->e_machine
) {
154 ELFDEFNNAME(MACHDEP_ID_CASES
)
161 * Find the first (and, we hope, only) SHT_SYMTAB section in
162 * the file, and the SHT_STRTAB section that goes with it.
164 if (elf
->e_shoff
== 0)
166 shp
= (Elf_Shdr
*)((char *)symtab
+ elf
->e_shoff
);
167 for (i
= 0; i
< elf
->e_shnum
; i
++) {
168 if (shp
[i
].sh_type
== SHT_SYMTAB
) {
169 if (shp
[i
].sh_offset
== 0)
171 /* Got the symbol table. */
172 symtab_start
= (Elf_Sym
*)((char *)symtab
+
174 symtab_end
= (Elf_Sym
*)((char *)symtab
+
175 shp
[i
].sh_offset
+ shp
[i
].sh_size
);
176 /* Find the string table to go with it. */
178 if (shp
[j
].sh_offset
== 0)
180 strtab_start
= (char *)symtab
+ shp
[j
].sh_offset
;
181 strtab_end
= (char *)symtab
+ shp
[j
].sh_offset
+
183 /* There should only be one symbol table. */
189 * Now, sanity check the symbols against the string table.
191 if (symtab_start
== NULL
|| strtab_start
== NULL
||
192 ALIGNED_POINTER(symtab_start
, long) == 0 ||
193 ALIGNED_POINTER(strtab_start
, long) == 0)
195 for (symp
= symtab_start
; symp
< symtab_end
; symp
++)
196 if (symp
->st_name
+ strtab_start
> strtab_end
)
200 * Link the symbol table into the debugger.
202 if (db_add_symbol_table((char *)symtab_start
,
203 (char *)symtab_end
, name
, (char *)symtab
) != -1) {
210 printf("[ %s ELF symbol table not valid ]\n", name
);
215 * Internal helper function - return a pointer to the string table
216 * for the current symbol table.
219 db_elf_find_strtab(db_symtab_t
*stab
)
221 Elf_Ehdr
*elf
= STAB_TO_EHDR(stab
);
222 Elf_Shdr
*shp
= STAB_TO_SHDR(stab
, elf
);
228 * We don't load ELF header for ELF modules.
229 * Find out if this is a loadable module. If so,
230 * string table comes right after symbol table.
232 if ((Elf_Sym
*)elf
== STAB_TO_SYMSTART(stab
)) {
233 return ((char *)STAB_TO_SYMEND(stab
));
235 for (i
= 0; i
< elf
->e_shnum
; i
++) {
236 if (shp
[i
].sh_type
== SHT_SYMTAB
)
237 return ((char*)elf
+ shp
[shp
[i
].sh_link
].sh_offset
);
244 * Lookup the symbol with the given name.
247 db_elf_lookup(db_symtab_t
*stab
, const char *symstr
)
249 Elf_Sym
*symp
, *symtab_start
, *symtab_end
;
254 symtab_start
= STAB_TO_SYMSTART(stab
);
255 symtab_end
= STAB_TO_SYMEND(stab
);
257 strtab
= db_elf_find_strtab(stab
);
259 return ((db_sym_t
)0);
261 for (symp
= symtab_start
; symp
< symtab_end
; symp
++) {
262 if (symp
->st_name
!= 0 &&
263 db_eqname(strtab
+ symp
->st_name
, symstr
, 0))
264 return ((db_sym_t
)symp
);
267 return ((db_sym_t
)0);
271 * Search for the symbol with the given address (matching within the
272 * provided threshold).
275 db_elf_search_symbol(db_symtab_t
*symtab
, db_addr_t off
, db_strategy_t strategy
,
278 Elf_Sym
*rsymp
, *symp
, *symtab_start
, *symtab_end
;
279 db_addr_t diff
= *diffp
;
281 symtab
= &db_symtabs
;
283 symtab_start
= STAB_TO_SYMSTART(symtab
);
284 symtab_end
= STAB_TO_SYMEND(symtab
);
288 for (symp
= symtab_start
; symp
< symtab_end
; symp
++) {
289 if (symp
->st_name
== 0)
293 /* This prevents me from seeing anythin in locore.s -- eeh */
294 if (ELF_ST_TYPE(symp
->st_info
) != STT_OBJECT
&&
295 ELF_ST_TYPE(symp
->st_info
) != STT_FUNC
)
299 if (off
>= symp
->st_value
) {
300 if (off
- symp
->st_value
< diff
) {
301 diff
= off
- symp
->st_value
;
304 if (strategy
== DB_STGY_PROC
&&
305 ELFDEFNNAME(ST_TYPE
)(symp
->st_info
)
307 ELFDEFNNAME(ST_BIND
)(symp
->st_info
)
310 if (strategy
== DB_STGY_ANY
&&
311 ELFDEFNNAME(ST_BIND
)(symp
->st_info
)
315 } else if (off
- symp
->st_value
== diff
) {
318 else if (ELFDEFNNAME(ST_BIND
)(rsymp
->st_info
)
320 ELFDEFNNAME(ST_BIND
)(symp
->st_info
)
322 /* pick the external symbol */
334 return ((db_sym_t
)rsymp
);
338 * Return the name and value for a symbol.
341 db_elf_symbol_values(db_symtab_t
*symtab
, db_sym_t sym
, const char **namep
,
344 Elf_Sym
*symp
= (Elf_Sym
*)sym
;
347 symtab
= &db_symtabs
;
350 strtab
= db_elf_find_strtab(symtab
);
354 *namep
= strtab
+ symp
->st_name
;
358 *valuep
= symp
->st_value
;
362 * Return the file and line number of the current program counter
363 * if we can find the appropriate debugging symbol.
366 db_elf_line_at_pc(db_symtab_t
*symtab
, db_sym_t cursym
, char **filename
, int *linenum
, db_expr_t off
)
370 * XXX We don't support this (yet).
376 * Returns the number of arguments to a function and their
377 * names if we can find the appropriate debugging symbol.
380 db_elf_sym_numargs(db_symtab_t
*symtab
, db_sym_t cursym
, int *nargp
,
385 * XXX We don't support this (yet).
391 db_elf_forall(db_symtab_t
*stab
, db_forall_func_t db_forall_func
, void *arg
)
394 static char suffix
[2];
395 Elf_Sym
*symp
, *symtab_start
, *symtab_end
;
399 symtab_start
= STAB_TO_SYMSTART(stab
);
400 symtab_end
= STAB_TO_SYMEND(stab
);
402 strtab
= db_elf_find_strtab(stab
);
406 for (symp
= symtab_start
; symp
< symtab_end
; symp
++)
407 if (symp
->st_name
!= 0) {
409 switch (ELFDEFNNAME(ST_TYPE
)(symp
->st_info
)) {
425 (*db_forall_func
)(stab
, (db_sym_t
)symp
,
426 strtab
+ symp
->st_name
, suffix
, 0, arg
);
430 #endif /* DB_ELF_SYMBOLS */