FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_elf.c
1 /* $NetBSD: db_elf.c,v 1.25 2008/04/28 20:23:46 martin 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 *
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.
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: db_elf.c,v 1.25 2008/04/28 20:23:46 martin Exp $");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/proc.h>
39
40 #include <machine/db_machdep.h>
41
42 #include <ddb/db_sym.h>
43 #include <ddb/db_output.h>
44 #include <ddb/db_extern.h>
45
46 #ifdef DB_ELF_SYMBOLS
47
48 #ifndef DB_ELFSIZE
49 #error Must define DB_ELFSIZE!
50 #endif
51
52 #define ELFSIZE DB_ELFSIZE
53
54 #include <sys/exec_elf.h>
55
56 static char *db_elf_find_strtab(db_symtab_t *);
57
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))
62
63 static bool db_elf_sym_init(int, void *, void *, const char *);
64 static db_sym_t db_elf_lookup(db_symtab_t *, char *);
65 static db_sym_t db_elf_search_symbol(db_symtab_t *, db_addr_t, db_strategy_t,
66 db_expr_t *);
67 static void db_elf_symbol_values(db_symtab_t *, db_sym_t, char **,
68 db_expr_t *);
69 static bool db_elf_line_at_pc(db_symtab_t *, db_sym_t, char **, int *,
70 db_expr_t);
71 static bool db_elf_sym_numargs(db_symtab_t *, db_sym_t, int *, char **);
72 static void db_elf_forall(db_symtab_t *, db_forall_func_t db_forall_func,
73 void *);
74
75 const db_symformat_t db_symformat_elf = {
76 "ELF",
77 db_elf_sym_init,
78 db_elf_lookup,
79 db_elf_search_symbol,
80 db_elf_symbol_values,
81 db_elf_line_at_pc,
82 db_elf_sym_numargs,
83 db_elf_forall
84 };
85
86 /*
87 * Find the symbol table and strings; tell ddb about them.
88 */
89 static bool
90 db_elf_sym_init(
91 int symsize, /* size of symbol table */
92 void *symtab, /* pointer to start of symbol table */
93 void *esymtab, /* pointer to end of string table,
94 for checking - rounded up to integer
95 boundary */
96 const char *name
97 )
98 {
99 Elf_Ehdr *elf;
100 Elf_Shdr *shp;
101 Elf_Sym *symp, *symtab_start, *symtab_end;
102 char *strtab_start, *strtab_end;
103 int i, j;
104
105 if (ALIGNED_POINTER(symtab, long) == 0) {
106 printf("[ %s symbol table has bad start address %p ]\n",
107 name, symtab);
108 return (false);
109 }
110
111 symtab_start = symtab_end = NULL;
112 strtab_start = strtab_end = NULL;
113
114 /*
115 * The format of the symbols loaded by the boot program is:
116 *
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
126 */
127
128 /*
129 * Validate the Elf header.
130 */
131 elf = (Elf_Ehdr *)symtab;
132 if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
133 elf->e_ident[EI_CLASS] != ELFCLASS)
134 goto badheader;
135
136 switch (elf->e_machine) {
137
138 ELFDEFNNAME(MACHDEP_ID_CASES)
139
140 default:
141 goto badheader;
142 }
143
144 /*
145 * Find the first (and, we hope, only) SHT_SYMTAB section in
146 * the file, and the SHT_STRTAB section that goes with it.
147 */
148 if (elf->e_shoff == 0)
149 goto badheader;
150 shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff);
151 for (i = 0; i < elf->e_shnum; i++) {
152 if (shp[i].sh_type == SHT_SYMTAB) {
153 if (shp[i].sh_offset == 0)
154 continue;
155 /* Got the symbol table. */
156 symtab_start = (Elf_Sym *)((char *)symtab +
157 shp[i].sh_offset);
158 symtab_end = (Elf_Sym *)((char *)symtab +
159 shp[i].sh_offset + shp[i].sh_size);
160 /* Find the string table to go with it. */
161 j = shp[i].sh_link;
162 if (shp[j].sh_offset == 0)
163 continue;
164 strtab_start = (char *)symtab + shp[j].sh_offset;
165 strtab_end = (char *)symtab + shp[j].sh_offset +
166 shp[j].sh_size;
167 /* There should only be one symbol table. */
168 break;
169 }
170 }
171
172 /*
173 * Now, sanity check the symbols against the string table.
174 */
175 if (symtab_start == NULL || strtab_start == NULL ||
176 ALIGNED_POINTER(symtab_start, long) == 0 ||
177 ALIGNED_POINTER(strtab_start, long) == 0)
178 goto badheader;
179 for (symp = symtab_start; symp < symtab_end; symp++)
180 if (symp->st_name + strtab_start > strtab_end)
181 goto badheader;
182
183 /*
184 * Link the symbol table into the debugger.
185 */
186 if (db_add_symbol_table((char *)symtab_start,
187 (char *)symtab_end, name, (char *)symtab) != -1) {
188 printf("[ using %lu bytes of %s ELF symbol table ]\n",
189 (u_long)roundup(((char *)esymtab - (char *)symtab),
190 sizeof(u_long)), name);
191 return (true);
192 }
193
194 return (false);
195
196 badheader:
197 printf("[ %s ELF symbol table not valid ]\n", name);
198 return (false);
199 }
200
201 /*
202 * Internal helper function - return a pointer to the string table
203 * for the current symbol table.
204 */
205 static char *
206 db_elf_find_strtab(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 /*
213 * We don't load ELF header for ELF modules.
214 * Find out if this is a loadable module. If so,
215 * string table comes right after symbol table.
216 */
217 if ((Elf_Sym *)elf == STAB_TO_SYMSTART(stab)) {
218 return ((char *)STAB_TO_SYMEND(stab));
219 }
220 for (i = 0; i < elf->e_shnum; i++) {
221 if (shp[i].sh_type == SHT_SYMTAB)
222 return ((char*)elf + shp[shp[i].sh_link].sh_offset);
223 }
224
225 return (NULL);
226 }
227
228 /*
229 * Lookup the symbol with the given name.
230 */
231 static db_sym_t
232 db_elf_lookup(db_symtab_t *stab, 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 static db_sym_t
258 db_elf_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strategy,
259 db_expr_t *diffp)
260 {
261 Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end;
262 db_addr_t diff = *diffp;
263
264 symtab_start = STAB_TO_SYMSTART(symtab);
265 symtab_end = STAB_TO_SYMEND(symtab);
266
267 rsymp = NULL;
268
269 for (symp = symtab_start; symp < symtab_end; symp++) {
270 if (symp->st_name == 0)
271 continue;
272 #if 0
273 /* This prevents me from seeing anythin in locore.s -- eeh */
274 if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object &&
275 ELF_SYM_TYPE(symp->st_info) != Elf_estt_func)
276 continue;
277 #endif
278
279 if (off >= symp->st_value) {
280 if (off - symp->st_value < diff) {
281 diff = off - symp->st_value;
282 rsymp = symp;
283 if (diff == 0) {
284 if (strategy == DB_STGY_PROC &&
285 ELFDEFNNAME(ST_TYPE)(symp->st_info)
286 == STT_FUNC &&
287 ELFDEFNNAME(ST_BIND)(symp->st_info)
288 != STB_LOCAL)
289 break;
290 if (strategy == DB_STGY_ANY &&
291 ELFDEFNNAME(ST_BIND)(symp->st_info)
292 != STB_LOCAL)
293 break;
294 }
295 } else if (off - symp->st_value == diff) {
296 if (rsymp == NULL)
297 rsymp = symp;
298 else if (ELFDEFNNAME(ST_BIND)(rsymp->st_info)
299 == STB_LOCAL &&
300 ELFDEFNNAME(ST_BIND)(symp->st_info)
301 != STB_LOCAL) {
302 /* pick the external symbol */
303 rsymp = symp;
304 }
305 }
306 }
307 }
308
309 if (rsymp == NULL)
310 *diffp = off;
311 else
312 *diffp = diff;
313
314 return ((db_sym_t)rsymp);
315 }
316
317 /*
318 * Return the name and value for a symbol.
319 */
320 static void
321 db_elf_symbol_values(db_symtab_t *symtab, db_sym_t sym, 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 static bool
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 static bool
363 db_elf_sym_numargs(db_symtab_t *symtab, db_sym_t cursym, int *nargp,
364 char **argnamep)
365 {
366
367 /*
368 * XXX We don't support this (yet).
369 */
370 return (false);
371 }
372
373 static void
374 db_elf_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg)
375 {
376 char *strtab;
377 static char suffix[2];
378 Elf_Sym *symp, *symtab_start, *symtab_end;
379
380 symtab_start = STAB_TO_SYMSTART(stab);
381 symtab_end = STAB_TO_SYMEND(stab);
382
383 strtab = db_elf_find_strtab(stab);
384 if (strtab == NULL)
385 return;
386
387 for (symp = symtab_start; symp < symtab_end; symp++)
388 if (symp->st_name != 0) {
389 suffix[1] = '\0';
390 switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) {
391 case STT_OBJECT:
392 suffix[0] = '+';
393 break;
394 case STT_FUNC:
395 suffix[0] = '*';
396 break;
397 case STT_SECTION:
398 suffix[0] = '&';
399 break;
400 case STT_FILE:
401 suffix[0] = '/';
402 break;
403 default:
404 suffix[0] = '\0';
405 }
406 (*db_forall_func)(stab, (db_sym_t)symp,
407 strtab + symp->st_name, suffix, 0, arg);
408 }
409 return;
410 }
411 #endif /* DB_ELF_SYMBOLS */
Cache object: f85bd686f46966ff08a3139fe69a07e7
|