root/ddb/db_elf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. db_elf_sym_init
  2. db_elf_find_strtab
  3. db_elf_lookup
  4. db_elf_search_symbol
  5. db_elf_symbol_values
  6. db_elf_line_at_pc
  7. db_elf_sym_numargs
  8. db_elf_forall

    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 */

/* [<][>][^][v][top][bottom][index][help] */