Don't use .Xo/.Xc. Fix date format.
[netbsd-mini2440.git] / sys / ddb / db_elf.c
blobc5fc9b2ba9a8467b716aea764dd92ebe6f0e5821
1 /* $NetBSD: db_elf.c,v 1.26 2009/03/07 22:02:17 ad Exp $ */
3 /*-
4 * Copyright (c) 1997, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
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
13 * are met:
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>
38 #include <sys/proc.h>
40 #include <ddb/ddb.h>
42 #include <machine/pmap.h>
43 #include <machine/vmparam.h>
45 #ifdef DB_ELF_SYMBOLS
47 #ifndef DB_ELFSIZE
48 #error Must define DB_ELFSIZE!
49 #endif
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,
65 db_expr_t *);
66 static void db_elf_symbol_values(db_symtab_t *, db_sym_t, const char **,
67 db_expr_t *);
68 static bool db_elf_line_at_pc(db_symtab_t *, db_sym_t, char **, int *,
69 db_expr_t);
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,
72 void *);
74 const db_symformat_t db_symformat_elf = {
75 "ELF",
76 db_elf_sym_init,
77 db_elf_lookup,
78 db_elf_search_symbol,
79 db_elf_symbol_values,
80 db_elf_line_at_pc,
81 db_elf_sym_numargs,
82 db_elf_forall
85 static db_symtab_t db_symtabs;
88 * Add symbol table, with given name, to symbol tables.
90 static int
91 db_add_symbol_table(char *start, char *end, const char *name, char *ref)
94 db_symtabs.start = start;
95 db_symtabs.end = end;
96 db_symtabs.name = name;
97 db_symtabs.private = ref;
99 return(0);
103 * Find the symbol table and strings; tell ddb about them.
105 static bool
106 db_elf_sym_init(
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
111 boundary */
112 const char *name
115 Elf_Ehdr *elf;
116 Elf_Shdr *shp;
117 Elf_Sym *symp, *symtab_start, *symtab_end;
118 char *strtab_start, *strtab_end;
119 int i, j;
121 if (ALIGNED_POINTER(symtab, long) == 0) {
122 printf("[ %s symbol table has bad start address %p ]\n",
123 name, symtab);
124 return (false);
127 symtab_start = symtab_end = NULL;
128 strtab_start = strtab_end = NULL;
131 * The format of the symbols loaded by the boot program is:
133 * Elf exec header
134 * first section header
135 * . . .
136 * . . .
137 * last section header
138 * first symbol or string table section
139 * . . .
140 * . . .
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)
150 goto badheader;
152 switch (elf->e_machine) {
154 ELFDEFNNAME(MACHDEP_ID_CASES)
156 default:
157 goto badheader;
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)
165 goto badheader;
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)
170 continue;
171 /* Got the symbol table. */
172 symtab_start = (Elf_Sym *)((char *)symtab +
173 shp[i].sh_offset);
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. */
177 j = shp[i].sh_link;
178 if (shp[j].sh_offset == 0)
179 continue;
180 strtab_start = (char *)symtab + shp[j].sh_offset;
181 strtab_end = (char *)symtab + shp[j].sh_offset +
182 shp[j].sh_size;
183 /* There should only be one symbol table. */
184 break;
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)
194 goto badheader;
195 for (symp = symtab_start; symp < symtab_end; symp++)
196 if (symp->st_name + strtab_start > strtab_end)
197 goto badheader;
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) {
204 return (true);
207 return (false);
209 badheader:
210 printf("[ %s ELF symbol table not valid ]\n", name);
211 return (false);
215 * Internal helper function - return a pointer to the string table
216 * for the current symbol table.
218 static char *
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);
223 int i;
225 stab = &db_symtabs;
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);
240 return (NULL);
244 * Lookup the symbol with the given name.
246 static db_sym_t
247 db_elf_lookup(db_symtab_t *stab, const char *symstr)
249 Elf_Sym *symp, *symtab_start, *symtab_end;
250 char *strtab;
252 stab = &db_symtabs;
254 symtab_start = STAB_TO_SYMSTART(stab);
255 symtab_end = STAB_TO_SYMEND(stab);
257 strtab = db_elf_find_strtab(stab);
258 if (strtab == NULL)
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).
274 static db_sym_t
275 db_elf_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strategy,
276 db_expr_t *diffp)
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);
286 rsymp = NULL;
288 for (symp = symtab_start; symp < symtab_end; symp++) {
289 if (symp->st_name == 0)
290 continue;
292 #if 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)
296 continue;
297 #endif
299 if (off >= symp->st_value) {
300 if (off - symp->st_value < diff) {
301 diff = off - symp->st_value;
302 rsymp = symp;
303 if (diff == 0) {
304 if (strategy == DB_STGY_PROC &&
305 ELFDEFNNAME(ST_TYPE)(symp->st_info)
306 == STT_FUNC &&
307 ELFDEFNNAME(ST_BIND)(symp->st_info)
308 != STB_LOCAL)
309 break;
310 if (strategy == DB_STGY_ANY &&
311 ELFDEFNNAME(ST_BIND)(symp->st_info)
312 != STB_LOCAL)
313 break;
315 } else if (off - symp->st_value == diff) {
316 if (rsymp == NULL)
317 rsymp = symp;
318 else if (ELFDEFNNAME(ST_BIND)(rsymp->st_info)
319 == STB_LOCAL &&
320 ELFDEFNNAME(ST_BIND)(symp->st_info)
321 != STB_LOCAL) {
322 /* pick the external symbol */
323 rsymp = symp;
329 if (rsymp == NULL)
330 *diffp = off;
331 else
332 *diffp = diff;
334 return ((db_sym_t)rsymp);
338 * Return the name and value for a symbol.
340 static void
341 db_elf_symbol_values(db_symtab_t *symtab, db_sym_t sym, const char **namep,
342 db_expr_t *valuep)
344 Elf_Sym *symp = (Elf_Sym *)sym;
345 char *strtab;
347 symtab = &db_symtabs;
349 if (namep) {
350 strtab = db_elf_find_strtab(symtab);
351 if (strtab == NULL)
352 *namep = NULL;
353 else
354 *namep = strtab + symp->st_name;
357 if (valuep)
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.
365 static bool
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).
372 return (false);
376 * Returns the number of arguments to a function and their
377 * names if we can find the appropriate debugging symbol.
379 static bool
380 db_elf_sym_numargs(db_symtab_t *symtab, db_sym_t cursym, int *nargp,
381 char **argnamep)
385 * XXX We don't support this (yet).
387 return (false);
390 static void
391 db_elf_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg)
393 char *strtab;
394 static char suffix[2];
395 Elf_Sym *symp, *symtab_start, *symtab_end;
397 stab = &db_symtabs;
399 symtab_start = STAB_TO_SYMSTART(stab);
400 symtab_end = STAB_TO_SYMEND(stab);
402 strtab = db_elf_find_strtab(stab);
403 if (strtab == NULL)
404 return;
406 for (symp = symtab_start; symp < symtab_end; symp++)
407 if (symp->st_name != 0) {
408 suffix[1] = '\0';
409 switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) {
410 case STT_OBJECT:
411 suffix[0] = '+';
412 break;
413 case STT_FUNC:
414 suffix[0] = '*';
415 break;
416 case STT_SECTION:
417 suffix[0] = '&';
418 break;
419 case STT_FILE:
420 suffix[0] = '/';
421 break;
422 default:
423 suffix[0] = '\0';
425 (*db_forall_func)(stab, (db_sym_t)symp,
426 strtab + symp->st_name, suffix, 0, arg);
428 return;
430 #endif /* DB_ELF_SYMBOLS */