1 /* $OpenBSD: db_elf.c,v 1.9 2008/06/26 05:42:14 ray Exp $ */
2 /* $NetBSD: db_elf.c,v 1.13 2000/07/07 21:55:18 jhawk Exp $ */
5 * Copyright (c) 1997 The NetBSD Foundation, Inc.
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10 * NASA Ames Research Center.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/systm.h>
40 #include <machine/db_machdep.h>
42 #include <ddb/db_sym.h>
43 #include <ddb/db_output.h>
44 #include <ddb/db_extern.h>
49 #error Must define DB_ELFSIZE!
52 #define ELFSIZE DB_ELFSIZE
54 #include <sys/exec_elf.h>
56 static char *db_elf_find_strtab(db_symtab_t
*);
58 #define STAB_TO_SYMSTART(stab) ((Elf_Sym *)((stab)->start))
59 #define STAB_TO_SYMEND(stab) ((Elf_Sym *)((stab)->end))
60 #define STAB_TO_EHDR(stab) ((Elf_Ehdr *)((stab)->private))
61 #define STAB_TO_SHDR(stab, e) ((Elf_Shdr *)((stab)->private + (e)->e_shoff))
63 boolean_t
db_elf_sym_init(int, void *, void *, const char *);
64 db_sym_t
db_elf_lookup(db_symtab_t
*, char *);
65 db_sym_t
db_elf_search_symbol(db_symtab_t
*, db_addr_t
,
66 db_strategy_t
, db_expr_t
*);
67 void db_elf_symbol_values(db_symtab_t
*, db_sym_t
,
68 char **, db_expr_t
*);
69 boolean_t
db_elf_line_at_pc(db_symtab_t
*, db_sym_t
,
70 char **, int *, db_expr_t
);
71 boolean_t
db_elf_sym_numargs(db_symtab_t
*, db_sym_t
, int *,
73 void db_elf_forall(db_symtab_t
*,
74 db_forall_func_t db_forall_func
, void *);
76 db_symformat_t db_symformat_elf
= {
88 * Find the symbol table and strings; tell ddb about them.
90 * symsize: size of symbol table
91 * symtab: pointer to start of symbol table
92 * esymtab: pointer to end of string table, for checking - rounded up to
96 db_elf_sym_init(int symsize
, void *symtab
, void *esymtab
, const char *name
)
100 Elf_Sym
*symp
, *symtab_start
, *symtab_end
;
101 char *shstrtab
, *strtab_start
, *strtab_end
;
105 if (ALIGNED_POINTER(symtab
, long) == 0) {
106 db_printf("[ %s symbol table has bad start address %p ]\n",
111 symtab_start
= symtab_end
= NULL
;
112 strtab_start
= strtab_end
= NULL
;
115 * The format of the symbols loaded by the boot program is:
118 * first section header
121 * last section header
122 * first symbol or string table section
125 * last symbol or string table section
129 * Validate the Elf header.
131 elf
= (Elf_Ehdr
*)symtab
;
132 if (memcmp(elf
->e_ident
, ELFMAG
, SELFMAG
) != 0 ||
133 elf
->e_ident
[EI_CLASS
] != ELFCLASS
) {
134 errstr
= "bad magic";
138 if (elf
->e_machine
!= ELF_TARG_MACH
) {
139 errstr
= "bad e_machine";
144 * Find the section header string table (.shstrtab), and look up
145 * the symbol table (.symtab) and string table (.strtab) via their
146 * names in shstrtab, rather than by table type.
147 * This works in the presence of multiple string tables, such as
148 * stabs data found when booting bsd.gdb.
150 shp
= (Elf_Shdr
*)((char *)symtab
+ elf
->e_shoff
);
151 shstrtab
= (char *)symtab
+ shp
[elf
->e_shstrndx
].sh_offset
;
152 for (i
= 0; i
< elf
->e_shnum
; i
++) {
153 if (shp
[i
].sh_type
== SHT_SYMTAB
) {
156 if (shp
[i
].sh_offset
== 0)
158 symtab_start
= (Elf_Sym
*)((char *)symtab
+
160 symtab_end
= (Elf_Sym
*)((char *)symtab
+
161 shp
[i
].sh_offset
+ shp
[i
].sh_size
);
163 if (shp
[j
].sh_offset
== 0)
165 strtab_start
= (char *)symtab
+ shp
[j
].sh_offset
;
166 strtab_end
= (char *)symtab
+ shp
[j
].sh_offset
+
172 * This is the old way of doing things.
173 * XXX - verify that it's not needed.
175 if (strcmp(".strtab", shstrtab
+shp
[i
].sh_name
) == 0) {
176 strtab_start
= (char *)symtab
+ shp
[i
].sh_offset
;
177 strtab_end
= (char *)symtab
+ shp
[i
].sh_offset
+
179 } else if (strcmp(".symtab", shstrtab
+shp
[i
].sh_name
) == 0) {
180 symtab_start
= (Elf_Sym
*)((char *)symtab
+
182 symtab_end
= (Elf_Sym
*)((char *)symtab
+
183 shp
[i
].sh_offset
+ shp
[i
].sh_size
);
188 * Now, sanity check the symbols against the string table.
190 if (symtab_start
== NULL
|| strtab_start
== NULL
||
191 ALIGNED_POINTER(symtab_start
, long) == 0 ||
192 ALIGNED_POINTER(strtab_start
, long) == 0) {
193 errstr
= "symtab unaligned";
196 for (symp
= symtab_start
; symp
< symtab_end
; symp
++)
197 if (symp
->st_name
+ strtab_start
> strtab_end
) {
198 errstr
= "symtab corrupted";
203 * Link the symbol table into the debugger.
205 if (db_add_symbol_table((char *)symtab_start
,
206 (char *)symtab_end
, name
, (char *)symtab
) != -1) {
207 db_printf("[ using %lu bytes of %s ELF symbol table ]\n",
208 (u_long
)roundup(((char *)esymtab
- (char *)symtab
),
209 sizeof(u_long
)), name
);
216 db_printf("[ %s ELF symbol table not valid: %s ]\n", name
, errstr
);
221 * Internal helper function - return a pointer to the string table
222 * for the current symbol table.
225 db_elf_find_strtab(db_symtab_t
*stab
)
227 Elf_Ehdr
*elf
= STAB_TO_EHDR(stab
);
228 Elf_Shdr
*shp
= STAB_TO_SHDR(stab
, elf
);
232 shstrtab
= (char *)elf
+ shp
[elf
->e_shstrndx
].sh_offset
;
233 for (i
= 0; i
< elf
->e_shnum
; i
++) {
234 if (shp
[i
].sh_type
== SHT_SYMTAB
)
235 return ((char *)elf
+ shp
[shp
[i
].sh_link
].sh_offset
);
236 if (strcmp(".strtab", shstrtab
+shp
[i
].sh_name
) == 0)
237 return ((char *)elf
+ shp
[i
].sh_offset
);
244 * Lookup the symbol with the given name.
247 db_elf_lookup(db_symtab_t
*stab
, char *symstr
)
249 Elf_Sym
*symp
, *symtab_start
, *symtab_end
;
252 symtab_start
= STAB_TO_SYMSTART(stab
);
253 symtab_end
= STAB_TO_SYMEND(stab
);
255 strtab
= db_elf_find_strtab(stab
);
257 return ((db_sym_t
)0);
259 for (symp
= symtab_start
; symp
< symtab_end
; symp
++) {
260 if (symp
->st_name
!= 0 &&
261 db_eqname(strtab
+ symp
->st_name
, symstr
, 0))
262 return ((db_sym_t
)symp
);
265 return ((db_sym_t
)0);
269 * Search for the symbol with the given address (matching within the
270 * provided threshold).
273 db_elf_search_symbol(db_symtab_t
*symtab
, db_addr_t off
, db_strategy_t strategy
,
276 Elf_Sym
*rsymp
, *symp
, *symtab_start
, *symtab_end
;
277 db_expr_t diff
= *diffp
;
279 symtab_start
= STAB_TO_SYMSTART(symtab
);
280 symtab_end
= STAB_TO_SYMEND(symtab
);
284 for (symp
= symtab_start
; symp
< symtab_end
; symp
++) {
285 if (symp
->st_name
== 0)
288 /* This prevents me from seeing anythin in locore.s -- eeh */
289 if (ELF_SYM_TYPE(symp
->st_info
) != Elf_estt_object
&&
290 ELF_SYM_TYPE(symp
->st_info
) != Elf_estt_func
)
294 if (off
>= symp
->st_value
) {
295 if ((off
- symp
->st_value
) < diff
) {
296 diff
= off
- symp
->st_value
;
299 if (strategy
== DB_STGY_PROC
&&
300 ELFDEFNNAME(ST_TYPE
)(symp
->st_info
)
302 ELFDEFNNAME(ST_BIND
)(symp
->st_info
)
305 if (strategy
== DB_STGY_ANY
&&
306 ELFDEFNNAME(ST_BIND
)(symp
->st_info
)
310 } else if ((off
- symp
->st_value
) == diff
) {
313 else if (ELFDEFNNAME(ST_BIND
)(rsymp
->st_info
)
315 ELFDEFNNAME(ST_BIND
)(symp
->st_info
)
317 /* pick the external symbol */
329 return ((db_sym_t
)rsymp
);
333 * Return the name and value for a symbol.
336 db_elf_symbol_values(db_symtab_t
*symtab
, db_sym_t sym
, char **namep
,
339 Elf_Sym
*symp
= (Elf_Sym
*)sym
;
343 strtab
= db_elf_find_strtab(symtab
);
347 *namep
= strtab
+ symp
->st_name
;
351 *valuep
= symp
->st_value
;
355 * Return the file and line number of the current program counter
356 * if we can find the appropriate debugging symbol.
359 db_elf_line_at_pc(db_symtab_t
*symtab
, db_sym_t cursym
, char **filename
,
360 int *linenum
, db_expr_t off
)
364 * XXX We don't support this (yet).
370 * Returns the number of arguments to a function and their
371 * names if we can find the appropriate debugging symbol.
374 db_elf_sym_numargs(db_symtab_t
*symtab
, db_sym_t cursym
, int *nargp
,
379 * XXX We don't support this (yet).
385 db_elf_forall(db_symtab_t
*stab
, db_forall_func_t db_forall_func
, void *arg
)
388 static char suffix
[2];
389 Elf_Sym
*symp
, *symtab_start
, *symtab_end
;
391 symtab_start
= STAB_TO_SYMSTART(stab
);
392 symtab_end
= STAB_TO_SYMEND(stab
);
394 strtab
= db_elf_find_strtab(stab
);
398 for (symp
= symtab_start
; symp
< symtab_end
; symp
++)
399 if (symp
->st_name
!= 0) {
401 switch (ELFDEFNNAME(ST_TYPE
)(symp
->st_info
)) {
417 (*db_forall_func
)(stab
, (db_sym_t
)symp
,
418 strtab
+ symp
->st_name
, suffix
, 0, arg
);
422 #endif /* DB_ELF_SYMBOLS */