sync
[bitrig.git] / sys / ddb / db_elf.c
blob2e4ed76a91a15380522015810c439cbee7fcd2ea
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 $ */
4 /*-
5 * Copyright (c) 1997 The NetBSD Foundation, Inc.
6 * All rights reserved.
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
14 * are met:
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>
37 #include <sys/proc.h>
38 #include <sys/exec.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>
46 #ifdef DB_ELF_SYMBOLS
48 #ifndef DB_ELFSIZE
49 #error Must define DB_ELFSIZE!
50 #endif
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 *,
72 char **);
73 void db_elf_forall(db_symtab_t *,
74 db_forall_func_t db_forall_func, void *);
76 db_symformat_t db_symformat_elf = {
77 "ELF",
78 db_elf_sym_init,
79 db_elf_lookup,
80 db_elf_search_symbol,
81 db_elf_symbol_values,
82 db_elf_line_at_pc,
83 db_elf_sym_numargs,
84 db_elf_forall
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
93 * integer boundry
95 boolean_t
96 db_elf_sym_init(int symsize, void *symtab, void *esymtab, const char *name)
98 Elf_Ehdr *elf;
99 Elf_Shdr *shp;
100 Elf_Sym *symp, *symtab_start, *symtab_end;
101 char *shstrtab, *strtab_start, *strtab_end;
102 int i;
103 char *errstr = "";
105 if (ALIGNED_POINTER(symtab, long) == 0) {
106 db_printf("[ %s symbol table has bad start address %p ]\n",
107 name, symtab);
108 return (FALSE);
111 symtab_start = symtab_end = NULL;
112 strtab_start = strtab_end = NULL;
115 * The format of the symbols loaded by the boot program is:
117 * Elf exec header
118 * first section header
119 * . . .
120 * . . .
121 * last section header
122 * first symbol or string table section
123 * . . .
124 * . . .
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";
135 goto badheader;
138 if (elf->e_machine != ELF_TARG_MACH) {
139 errstr = "bad e_machine";
140 goto badheader;
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) {
154 int j;
156 if (shp[i].sh_offset == 0)
157 continue;
158 symtab_start = (Elf_Sym *)((char *)symtab +
159 shp[i].sh_offset);
160 symtab_end = (Elf_Sym *)((char *)symtab +
161 shp[i].sh_offset + shp[i].sh_size);
162 j = shp[i].sh_link;
163 if (shp[j].sh_offset == 0)
164 continue;
165 strtab_start = (char *)symtab + shp[j].sh_offset;
166 strtab_end = (char *)symtab + shp[j].sh_offset +
167 shp[j].sh_size;
168 break;
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 +
178 shp[i].sh_size;
179 } else if (strcmp(".symtab", shstrtab+shp[i].sh_name) == 0) {
180 symtab_start = (Elf_Sym *)((char *)symtab +
181 shp[i].sh_offset);
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";
194 goto badheader;
196 for (symp = symtab_start; symp < symtab_end; symp++)
197 if (symp->st_name + strtab_start > strtab_end) {
198 errstr = "symtab corrupted";
199 goto badheader;
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);
210 return (TRUE);
213 return (FALSE);
215 badheader:
216 db_printf("[ %s ELF symbol table not valid: %s ]\n", name, errstr);
217 return (FALSE);
221 * Internal helper function - return a pointer to the string table
222 * for the current symbol table.
224 static char *
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);
229 char *shstrtab;
230 int i;
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);
240 return (NULL);
244 * Lookup the symbol with the given name.
246 db_sym_t
247 db_elf_lookup(db_symtab_t *stab, char *symstr)
249 Elf_Sym *symp, *symtab_start, *symtab_end;
250 char *strtab;
252 symtab_start = STAB_TO_SYMSTART(stab);
253 symtab_end = STAB_TO_SYMEND(stab);
255 strtab = db_elf_find_strtab(stab);
256 if (strtab == NULL)
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).
272 db_sym_t
273 db_elf_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strategy,
274 db_expr_t *diffp)
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);
282 rsymp = NULL;
284 for (symp = symtab_start; symp < symtab_end; symp++) {
285 if (symp->st_name == 0)
286 continue;
287 #if 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)
291 continue;
292 #endif
294 if (off >= symp->st_value) {
295 if ((off - symp->st_value) < diff) {
296 diff = off - symp->st_value;
297 rsymp = symp;
298 if (diff == 0) {
299 if (strategy == DB_STGY_PROC &&
300 ELFDEFNNAME(ST_TYPE)(symp->st_info)
301 == STT_FUNC &&
302 ELFDEFNNAME(ST_BIND)(symp->st_info)
303 != STB_LOCAL)
304 break;
305 if (strategy == DB_STGY_ANY &&
306 ELFDEFNNAME(ST_BIND)(symp->st_info)
307 != STB_LOCAL)
308 break;
310 } else if ((off - symp->st_value) == diff) {
311 if (rsymp == NULL)
312 rsymp = symp;
313 else if (ELFDEFNNAME(ST_BIND)(rsymp->st_info)
314 == STB_LOCAL &&
315 ELFDEFNNAME(ST_BIND)(symp->st_info)
316 != STB_LOCAL) {
317 /* pick the external symbol */
318 rsymp = symp;
324 if (rsymp == NULL)
325 *diffp = off;
326 else
327 *diffp = diff;
329 return ((db_sym_t)rsymp);
333 * Return the name and value for a symbol.
335 void
336 db_elf_symbol_values(db_symtab_t *symtab, db_sym_t sym, char **namep,
337 db_expr_t *valuep)
339 Elf_Sym *symp = (Elf_Sym *)sym;
340 char *strtab;
342 if (namep) {
343 strtab = db_elf_find_strtab(symtab);
344 if (strtab == NULL)
345 *namep = NULL;
346 else
347 *namep = strtab + symp->st_name;
350 if (valuep)
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.
358 boolean_t
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).
366 return (FALSE);
370 * Returns the number of arguments to a function and their
371 * names if we can find the appropriate debugging symbol.
373 boolean_t
374 db_elf_sym_numargs(db_symtab_t *symtab, db_sym_t cursym, int *nargp,
375 char **argnamep)
379 * XXX We don't support this (yet).
381 return (FALSE);
384 void
385 db_elf_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg)
387 char *strtab;
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);
395 if (strtab == NULL)
396 return;
398 for (symp = symtab_start; symp < symtab_end; symp++)
399 if (symp->st_name != 0) {
400 suffix[1] = '\0';
401 switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) {
402 case STT_OBJECT:
403 suffix[0] = '+';
404 break;
405 case STT_FUNC:
406 suffix[0] = '*';
407 break;
408 case STT_SECTION:
409 suffix[0] = '&';
410 break;
411 case STT_FILE:
412 suffix[0] = '/';
413 break;
414 default:
415 suffix[0] = '\0';
417 (*db_forall_func)(stab, (db_sym_t)symp,
418 strtab + symp->st_name, suffix, 0, arg);
420 return;
422 #endif /* DB_ELF_SYMBOLS */