db_elf.c revision 1.15 1 /* $NetBSD: db_elf.c,v 1.15 2001/07/31 19:14:18 bjh21 Exp $ */
2
3 /*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
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.
10 *
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.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/proc.h>
44
45 #include <machine/db_machdep.h>
46
47 #include <ddb/db_sym.h>
48 #include <ddb/db_output.h>
49 #include <ddb/db_extern.h>
50
51 #ifdef DB_ELF_SYMBOLS
52
53 #ifndef DB_ELFSIZE
54 #error Must define DB_ELFSIZE!
55 #endif
56
57 #define ELFSIZE DB_ELFSIZE
58
59 #include <sys/exec_elf.h>
60
61 static char *db_elf_find_strtab __P((db_symtab_t *));
62
63 #define STAB_TO_SYMSTART(stab) ((Elf_Sym *)((stab)->start))
64 #define STAB_TO_SYMEND(stab) ((Elf_Sym *)((stab)->end))
65 #define STAB_TO_EHDR(stab) ((Elf_Ehdr *)((stab)->private))
66 #define STAB_TO_SHDR(stab, e) ((Elf_Shdr *)((stab)->private + (e)->e_shoff))
67
68 boolean_t db_elf_sym_init __P((int, void *, void *, const char *));
69 db_sym_t db_elf_lookup __P((db_symtab_t *, char *));
70 db_sym_t db_elf_search_symbol __P((db_symtab_t *, db_addr_t,
71 db_strategy_t, db_expr_t *));
72 void db_elf_symbol_values __P((db_symtab_t *, db_sym_t,
73 char **, db_expr_t *));
74 boolean_t db_elf_line_at_pc __P((db_symtab_t *, db_sym_t,
75 char **, int *, db_expr_t));
76 boolean_t db_elf_sym_numargs __P((db_symtab_t *, db_sym_t, int *,
77 char **));
78 void db_elf_forall __P((db_symtab_t *,
79 db_forall_func_t db_forall_func, void *));
80
81 const db_symformat_t db_symformat_elf = {
82 "ELF",
83 db_elf_sym_init,
84 db_elf_lookup,
85 db_elf_search_symbol,
86 db_elf_symbol_values,
87 db_elf_line_at_pc,
88 db_elf_sym_numargs,
89 db_elf_forall
90 };
91
92 /*
93 * Find the symbol table and strings; tell ddb about them.
94 */
95 boolean_t
96 db_elf_sym_init(symsize, symtab, esymtab, name)
97 int symsize; /* size of symbol table */
98 void *symtab; /* pointer to start of symbol table */
99 void *esymtab; /* pointer to end of string table,
100 for checking - rounded up to integer
101 boundary */
102 const char *name;
103 {
104 Elf_Ehdr *elf;
105 Elf_Shdr *shp;
106 Elf_Sym *symp, *symtab_start, *symtab_end;
107 char *strtab_start, *strtab_end;
108 int i, j;
109
110 if (ALIGNED_POINTER(symtab, long) == 0) {
111 printf("[ %s symbol table has bad start address %p ]\n",
112 name, symtab);
113 return (FALSE);
114 }
115
116 symtab_start = symtab_end = NULL;
117 strtab_start = strtab_end = NULL;
118
119 /*
120 * The format of the symbols loaded by the boot program is:
121 *
122 * Elf exec header
123 * first section header
124 * . . .
125 * . . .
126 * last section header
127 * first symbol or string table section
128 * . . .
129 * . . .
130 * last symbol or string table section
131 */
132
133 /*
134 * Validate the Elf header.
135 */
136 elf = (Elf_Ehdr *)symtab;
137 if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
138 elf->e_ident[EI_CLASS] != ELFCLASS)
139 goto badheader;
140
141 switch (elf->e_machine) {
142
143 ELFDEFNNAME(MACHDEP_ID_CASES)
144
145 default:
146 goto badheader;
147 }
148
149 /*
150 * Find the first (and, we hope, only) SHT_SYMTAB section in
151 * the file, and the SHT_STRTAB section that goes with it.
152 */
153 shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff);
154 for (i = 0; i < elf->e_shnum; i++) {
155 if (shp[i].sh_type == SHT_SYMTAB) {
156 /* Got the symbol table. */
157 symtab_start = (Elf_Sym *)((char *)symtab +
158 shp[i].sh_offset);
159 symtab_end = (Elf_Sym *)((char *)symtab +
160 shp[i].sh_offset + shp[i].sh_size);
161 /* Find the string table to go with it. */
162 j = shp[i].sh_link;
163 strtab_start = (char *)symtab + shp[j].sh_offset;
164 strtab_end = (char *)symtab + shp[j].sh_offset +
165 shp[j].sh_size;
166 /* There should only be one symbol table. */
167 break;
168 }
169 }
170
171 /*
172 * Now, sanity check the symbols against the string table.
173 */
174 if (symtab_start == NULL || strtab_start == NULL ||
175 ALIGNED_POINTER(symtab_start, long) == 0 ||
176 ALIGNED_POINTER(strtab_start, long) == 0)
177 goto badheader;
178 for (symp = symtab_start; symp < symtab_end; symp++)
179 if (symp->st_name + strtab_start > strtab_end)
180 goto badheader;
181
182 /*
183 * Link the symbol table into the debugger.
184 */
185 if (db_add_symbol_table((char *)symtab_start,
186 (char *)symtab_end, name, (char *)symtab) != -1) {
187 printf("[ using %lu bytes of %s ELF symbol table ]\n",
188 (u_long)roundup(((char *)esymtab - (char *)symtab),
189 sizeof(u_long)), name);
190 return (TRUE);
191 }
192
193 return (FALSE);
194
195 badheader:
196 printf("[ %s ELF symbol table not valid ]\n", name);
197 return (FALSE);
198 }
199
200 /*
201 * Internal helper function - return a pointer to the string table
202 * for the current symbol table.
203 */
204 static char *
205 db_elf_find_strtab(stab)
206 db_symtab_t *stab;
207 {
208 Elf_Ehdr *elf = STAB_TO_EHDR(stab);
209 Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
210 int i;
211
212 for (i = 0; i < elf->e_shnum; i++) {
213 if (shp[i].sh_type == SHT_SYMTAB)
214 return ((char*)elf + shp[shp[i].sh_link].sh_offset);
215 }
216
217 return (NULL);
218 }
219
220 /*
221 * Lookup the symbol with the given name.
222 */
223 db_sym_t
224 db_elf_lookup(stab, symstr)
225 db_symtab_t *stab;
226 char *symstr;
227 {
228 Elf_Sym *symp, *symtab_start, *symtab_end;
229 char *strtab;
230
231 symtab_start = STAB_TO_SYMSTART(stab);
232 symtab_end = STAB_TO_SYMEND(stab);
233
234 strtab = db_elf_find_strtab(stab);
235 if (strtab == NULL)
236 return ((db_sym_t)0);
237
238 for (symp = symtab_start; symp < symtab_end; symp++) {
239 if (symp->st_name != 0 &&
240 db_eqname(strtab + symp->st_name, symstr, 0))
241 return ((db_sym_t)symp);
242 }
243
244 return ((db_sym_t)0);
245 }
246
247 /*
248 * Search for the symbol with the given address (matching within the
249 * provided threshold).
250 */
251 db_sym_t
252 db_elf_search_symbol(symtab, off, strategy, diffp)
253 db_symtab_t *symtab;
254 db_addr_t off;
255 db_strategy_t strategy;
256 db_expr_t *diffp; /* in/out */
257 {
258 Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end;
259 db_expr_t diff = *diffp;
260
261 symtab_start = STAB_TO_SYMSTART(symtab);
262 symtab_end = STAB_TO_SYMEND(symtab);
263
264 rsymp = NULL;
265
266 for (symp = symtab_start; symp < symtab_end; symp++) {
267 if (symp->st_name == 0)
268 continue;
269 #if 0
270 /* This prevents me from seeing anythin in locore.s -- eeh */
271 if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object &&
272 ELF_SYM_TYPE(symp->st_info) != Elf_estt_func)
273 continue;
274 #endif
275
276 if (off >= symp->st_value) {
277 if ((off - symp->st_value) < diff) {
278 diff = off - symp->st_value;
279 rsymp = symp;
280 if (diff == 0) {
281 if (strategy == DB_STGY_PROC &&
282 ELFDEFNNAME(ST_TYPE)(symp->st_info)
283 == STT_FUNC &&
284 ELFDEFNNAME(ST_BIND)(symp->st_info)
285 != STB_LOCAL)
286 break;
287 if (strategy == DB_STGY_ANY &&
288 ELFDEFNNAME(ST_BIND)(symp->st_info)
289 != STB_LOCAL)
290 break;
291 }
292 } else if ((off - symp->st_value) == diff) {
293 if (rsymp == NULL)
294 rsymp = symp;
295 else if (ELFDEFNNAME(ST_BIND)(rsymp->st_info)
296 == STB_LOCAL &&
297 ELFDEFNNAME(ST_BIND)(symp->st_info)
298 != STB_LOCAL) {
299 /* pick the external symbol */
300 rsymp = symp;
301 }
302 }
303 }
304 }
305
306 if (rsymp == NULL)
307 *diffp = off;
308 else
309 *diffp = diff;
310
311 return ((db_sym_t)rsymp);
312 }
313
314 /*
315 * Return the name and value for a symbol.
316 */
317 void
318 db_elf_symbol_values(symtab, sym, namep, valuep)
319 db_symtab_t *symtab;
320 db_sym_t sym;
321 char **namep;
322 db_expr_t *valuep;
323 {
324 Elf_Sym *symp = (Elf_Sym *)sym;
325 char *strtab;
326
327 if (namep) {
328 strtab = db_elf_find_strtab(symtab);
329 if (strtab == NULL)
330 *namep = NULL;
331 else
332 *namep = strtab + symp->st_name;
333 }
334
335 if (valuep)
336 *valuep = symp->st_value;
337 }
338
339 /*
340 * Return the file and line number of the current program counter
341 * if we can find the appropriate debugging symbol.
342 */
343 boolean_t
344 db_elf_line_at_pc(symtab, cursym, filename, linenum, off)
345 db_symtab_t *symtab;
346 db_sym_t cursym;
347 char **filename;
348 int *linenum;
349 db_expr_t off;
350 {
351
352 /*
353 * XXX We don't support this (yet).
354 */
355 return (FALSE);
356 }
357
358 /*
359 * Returns the number of arguments to a function and their
360 * names if we can find the appropriate debugging symbol.
361 */
362 boolean_t
363 db_elf_sym_numargs(symtab, cursym, nargp, argnamep)
364 db_symtab_t *symtab;
365 db_sym_t cursym;
366 int *nargp;
367 char **argnamep;
368 {
369
370 /*
371 * XXX We don't support this (yet).
372 */
373 return (FALSE);
374 }
375
376 void
377 db_elf_forall(stab, db_forall_func, arg)
378 db_symtab_t *stab;
379 db_forall_func_t db_forall_func;
380 void *arg;
381 {
382 char *strtab;
383 static char suffix[2];
384 Elf_Sym *symp, *symtab_start, *symtab_end;
385
386 symtab_start = STAB_TO_SYMSTART(stab);
387 symtab_end = STAB_TO_SYMEND(stab);
388
389 strtab = db_elf_find_strtab(stab);
390 if (strtab == NULL)
391 return;
392
393 for (symp = symtab_start; symp < symtab_end; symp++)
394 if (symp->st_name != 0) {
395 suffix[1] = '\0';
396 switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) {
397 case STT_OBJECT:
398 suffix[0] = '+';
399 break;
400 case STT_FUNC:
401 suffix[0] = '*';
402 break;
403 case STT_SECTION:
404 suffix[0] = '&';
405 break;
406 case STT_FILE:
407 suffix[0] = '/';
408 break;
409 default:
410 suffix[0] = '\0';
411 }
412 (*db_forall_func)(stab, (db_sym_t)symp,
413 strtab + symp->st_name, suffix, 0, arg);
414 }
415 return;
416 }
417 #endif /* DB_ELF_SYMBOLS */
418