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