Annotation of sys/ddb/db_elf.c, Revision 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