db_elf.c revision 1.14.2.1 1 /* $NetBSD: db_elf.c,v 1.14.2.1 2001/08/24 00:09:01 nathanw 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 if (elf->e_shoff == 0)
154 goto badheader;
155 shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff);
156 for (i = 0; i < elf->e_shnum; i++) {
157 if (shp[i].sh_type == SHT_SYMTAB) {
158 if (shp[i].sh_offset == 0)
159 continue;
160 /* Got the symbol table. */
161 symtab_start = (Elf_Sym *)((char *)symtab +
162 shp[i].sh_offset);
163 symtab_end = (Elf_Sym *)((char *)symtab +
164 shp[i].sh_offset + shp[i].sh_size);
165 /* Find the string table to go with it. */
166 j = shp[i].sh_link;
167 if (shp[j].sh_offset == 0)
168 continue;
169 strtab_start = (char *)symtab + shp[j].sh_offset;
170 strtab_end = (char *)symtab + shp[j].sh_offset +
171 shp[j].sh_size;
172 /* There should only be one symbol table. */
173 break;
174 }
175 }
176
177 /*
178 * Now, sanity check the symbols against the string table.
179 */
180 if (symtab_start == NULL || strtab_start == NULL ||
181 ALIGNED_POINTER(symtab_start, long) == 0 ||
182 ALIGNED_POINTER(strtab_start, long) == 0)
183 goto badheader;
184 for (symp = symtab_start; symp < symtab_end; symp++)
185 if (symp->st_name + strtab_start > strtab_end)
186 goto badheader;
187
188 /*
189 * Link the symbol table into the debugger.
190 */
191 if (db_add_symbol_table((char *)symtab_start,
192 (char *)symtab_end, name, (char *)symtab) != -1) {
193 printf("[ using %lu bytes of %s ELF symbol table ]\n",
194 (u_long)roundup(((char *)esymtab - (char *)symtab),
195 sizeof(u_long)), name);
196 return (TRUE);
197 }
198
199 return (FALSE);
200
201 badheader:
202 printf("[ %s ELF symbol table not valid ]\n", name);
203 return (FALSE);
204 }
205
206 /*
207 * Internal helper function - return a pointer to the string table
208 * for the current symbol table.
209 */
210 static char *
211 db_elf_find_strtab(stab)
212 db_symtab_t *stab;
213 {
214 Elf_Ehdr *elf = STAB_TO_EHDR(stab);
215 Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
216 int i;
217
218 for (i = 0; i < elf->e_shnum; i++) {
219 if (shp[i].sh_type == SHT_SYMTAB)
220 return ((char*)elf + shp[shp[i].sh_link].sh_offset);
221 }
222
223 return (NULL);
224 }
225
226 /*
227 * Lookup the symbol with the given name.
228 */
229 db_sym_t
230 db_elf_lookup(stab, symstr)
231 db_symtab_t *stab;
232 char *symstr;
233 {
234 Elf_Sym *symp, *symtab_start, *symtab_end;
235 char *strtab;
236
237 symtab_start = STAB_TO_SYMSTART(stab);
238 symtab_end = STAB_TO_SYMEND(stab);
239
240 strtab = db_elf_find_strtab(stab);
241 if (strtab == NULL)
242 return ((db_sym_t)0);
243
244 for (symp = symtab_start; symp < symtab_end; symp++) {
245 if (symp->st_name != 0 &&
246 db_eqname(strtab + symp->st_name, symstr, 0))
247 return ((db_sym_t)symp);
248 }
249
250 return ((db_sym_t)0);
251 }
252
253 /*
254 * Search for the symbol with the given address (matching within the
255 * provided threshold).
256 */
257 db_sym_t
258 db_elf_search_symbol(symtab, off, strategy, diffp)
259 db_symtab_t *symtab;
260 db_addr_t off;
261 db_strategy_t strategy;
262 db_expr_t *diffp; /* in/out */
263 {
264 Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end;
265 db_expr_t diff = *diffp;
266
267 symtab_start = STAB_TO_SYMSTART(symtab);
268 symtab_end = STAB_TO_SYMEND(symtab);
269
270 rsymp = NULL;
271
272 for (symp = symtab_start; symp < symtab_end; symp++) {
273 if (symp->st_name == 0)
274 continue;
275 #if 0
276 /* This prevents me from seeing anythin in locore.s -- eeh */
277 if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object &&
278 ELF_SYM_TYPE(symp->st_info) != Elf_estt_func)
279 continue;
280 #endif
281
282 if (off >= symp->st_value) {
283 if ((off - symp->st_value) < diff) {
284 diff = off - symp->st_value;
285 rsymp = symp;
286 if (diff == 0) {
287 if (strategy == DB_STGY_PROC &&
288 ELFDEFNNAME(ST_TYPE)(symp->st_info)
289 == STT_FUNC &&
290 ELFDEFNNAME(ST_BIND)(symp->st_info)
291 != STB_LOCAL)
292 break;
293 if (strategy == DB_STGY_ANY &&
294 ELFDEFNNAME(ST_BIND)(symp->st_info)
295 != STB_LOCAL)
296 break;
297 }
298 } else if ((off - symp->st_value) == diff) {
299 if (rsymp == NULL)
300 rsymp = symp;
301 else if (ELFDEFNNAME(ST_BIND)(rsymp->st_info)
302 == STB_LOCAL &&
303 ELFDEFNNAME(ST_BIND)(symp->st_info)
304 != STB_LOCAL) {
305 /* pick the external symbol */
306 rsymp = symp;
307 }
308 }
309 }
310 }
311
312 if (rsymp == NULL)
313 *diffp = off;
314 else
315 *diffp = diff;
316
317 return ((db_sym_t)rsymp);
318 }
319
320 /*
321 * Return the name and value for a symbol.
322 */
323 void
324 db_elf_symbol_values(symtab, sym, namep, valuep)
325 db_symtab_t *symtab;
326 db_sym_t sym;
327 char **namep;
328 db_expr_t *valuep;
329 {
330 Elf_Sym *symp = (Elf_Sym *)sym;
331 char *strtab;
332
333 if (namep) {
334 strtab = db_elf_find_strtab(symtab);
335 if (strtab == NULL)
336 *namep = NULL;
337 else
338 *namep = strtab + symp->st_name;
339 }
340
341 if (valuep)
342 *valuep = symp->st_value;
343 }
344
345 /*
346 * Return the file and line number of the current program counter
347 * if we can find the appropriate debugging symbol.
348 */
349 boolean_t
350 db_elf_line_at_pc(symtab, cursym, filename, linenum, off)
351 db_symtab_t *symtab;
352 db_sym_t cursym;
353 char **filename;
354 int *linenum;
355 db_expr_t off;
356 {
357
358 /*
359 * XXX We don't support this (yet).
360 */
361 return (FALSE);
362 }
363
364 /*
365 * Returns the number of arguments to a function and their
366 * names if we can find the appropriate debugging symbol.
367 */
368 boolean_t
369 db_elf_sym_numargs(symtab, cursym, nargp, argnamep)
370 db_symtab_t *symtab;
371 db_sym_t cursym;
372 int *nargp;
373 char **argnamep;
374 {
375
376 /*
377 * XXX We don't support this (yet).
378 */
379 return (FALSE);
380 }
381
382 void
383 db_elf_forall(stab, db_forall_func, arg)
384 db_symtab_t *stab;
385 db_forall_func_t db_forall_func;
386 void *arg;
387 {
388 char *strtab;
389 static char suffix[2];
390 Elf_Sym *symp, *symtab_start, *symtab_end;
391
392 symtab_start = STAB_TO_SYMSTART(stab);
393 symtab_end = STAB_TO_SYMEND(stab);
394
395 strtab = db_elf_find_strtab(stab);
396 if (strtab == NULL)
397 return;
398
399 for (symp = symtab_start; symp < symtab_end; symp++)
400 if (symp->st_name != 0) {
401 suffix[1] = '\0';
402 switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) {
403 case STT_OBJECT:
404 suffix[0] = '+';
405 break;
406 case STT_FUNC:
407 suffix[0] = '*';
408 break;
409 case STT_SECTION:
410 suffix[0] = '&';
411 break;
412 case STT_FILE:
413 suffix[0] = '/';
414 break;
415 default:
416 suffix[0] = '\0';
417 }
418 (*db_forall_func)(stab, (db_sym_t)symp,
419 strtab + symp->st_name, suffix, 0, arg);
420 }
421 return;
422 }
423 #endif /* DB_ELF_SYMBOLS */
424