The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_elf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $FreeBSD$ */
    2 /*      $NetBSD: db_elf.c,v 1.4 1998/05/03 18:49:54 thorpej 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 #if defined(__ELF__) && defined(__alpha__)
   42 
   43 #include "opt_ddb.h"
   44 
   45 #include <sys/types.h>
   46 #include <sys/param.h>
   47 #include <sys/systm.h>  
   48 #include <sys/proc.h>
   49 
   50 #include <machine/db_machdep.h>
   51 
   52 #include <ddb/db_sym.h>
   53 #include <ddb/db_output.h>
   54 
   55 #include <machine/elf.h>
   56 
   57 static char *db_elf_find_strtab __P((db_symtab_t *));
   58 
   59 #define STAB_TO_SYMSTART(stab)  ((Elf_Sym *)((stab)->start))
   60 #define STAB_TO_SYMEND(stab)    ((Elf_Sym *)((stab)->end))
   61 #define STAB_TO_EHDR(stab)      ((Elf_Ehdr *)((stab)->private))
   62 #define STAB_TO_SHDR(stab, e)   ((Elf_Shdr *)((stab)->private + (e)->e_shoff))
   63 
   64 void X_db_sym_init(void *symtab, void *esymtab, char *name);
   65 
   66 /*
   67  * Find the symbol table and strings; tell ddb about them.
   68  */
   69 void
   70 X_db_sym_init(symtab, esymtab, name)
   71         void *symtab;           /* pointer to start of symbol table */
   72         void *esymtab;          /* pointer to end of string table,
   73                                    for checking - rounded up to integer
   74                                    boundary */
   75         char *name;
   76 {
   77         Elf_Ehdr *elf;
   78         Elf_Shdr *shp;
   79         Elf_Sym *symp, *symtab_start, *symtab_end;
   80         char *strtab_start, *strtab_end;
   81         int i;
   82 
   83         if (ALIGNED_POINTER(symtab, long) == 0) {
   84                 printf("DDB: bad symbol table start address %p\n", symtab);
   85                 return;
   86         }
   87 
   88         symtab_start = symtab_end = NULL;
   89         strtab_start = strtab_end = NULL;
   90 
   91         /*
   92          * The format of the symbols loaded by the boot program is:
   93          *
   94          *      Elf exec header
   95          *      first section header
   96          *      . . .
   97          *      . . .
   98          *      last section header
   99          *      first symbol or string table section
  100          *      . . .
  101          *      . . .
  102          *      last symbol or string table section
  103          */
  104 
  105         /*
  106          * Validate the Elf header.
  107          */
  108         elf = (Elf_Ehdr *)symtab;
  109         if (elf->e_ident[EI_MAG0] != ELFMAG0
  110             || elf->e_ident[EI_MAG1] != ELFMAG1
  111             || elf->e_ident[EI_MAG2] != ELFMAG2
  112             || elf->e_ident[EI_MAG3] != ELFMAG3)
  113                 goto badheader;
  114 
  115         if (!ELF_MACHINE_OK(elf->e_machine))
  116                 goto badheader;
  117 
  118         /*
  119          * We need to avoid the section header string table (small string
  120          * table which names the sections).  We do this by assuming that
  121          * the following two conditions will be true:
  122          *
  123          *      (1) .shstrtab will be smaller than one page.
  124          *      (2) .strtab will be larger than one page.
  125          *
  126          * When we encounter what we think is the .shstrtab, we change
  127          * its section type Elf_sht_null so that it will be ignored
  128          * later.
  129          */
  130         shp = (Elf_Shdr *)((char*)symtab + elf->e_shoff);
  131         for (i = 0; i < elf->e_shnum; i++) {
  132                 if (shp[i].sh_addr || i == elf->e_shstrndx)
  133                         continue;
  134                 switch (shp[i].sh_type) {
  135                 case SHT_STRTAB:
  136                         if (shp[i].sh_size < PAGE_SIZE) {
  137                                 shp[i].sh_type = SHT_NULL;
  138                                 continue;
  139                         }
  140                         if (strtab_start != NULL)
  141                                 goto multiple_strtab;
  142                         strtab_start = (char *)symtab + shp[i].sh_offset;
  143                         strtab_end = (char *)symtab + shp[i].sh_offset +
  144                             shp[i].sh_size;
  145                         break;
  146                 
  147                 case SHT_SYMTAB:
  148                         if (symtab_start != NULL)
  149                                 goto multiple_symtab;
  150                         symtab_start = (Elf_Sym *)((char*)symtab + shp[i].sh_offset);
  151                         symtab_end = (Elf_Sym *)((char*)symtab + shp[i].sh_offset +
  152                             shp[i].sh_size);
  153                         break;
  154 
  155                 default:
  156                         /* Ignore all other sections. */
  157                         break;
  158                 }
  159         }
  160 
  161         /*
  162          * Now, sanity check the symbols against the string table.
  163          */
  164         if (symtab_start == NULL || strtab_start == NULL ||
  165             ALIGNED_POINTER(symtab_start, long) == 0 ||
  166             ALIGNED_POINTER(strtab_start, long) == 0)
  167                 goto badheader;
  168         for (symp = symtab_start; symp < symtab_end; symp++)
  169                 if (symp->st_name + strtab_start > strtab_end)
  170                         goto badheader;
  171 
  172         /*
  173          * Link the symbol table into the debugger.
  174          */
  175         db_add_symbol_table((char *)symtab_start,
  176                             (char *)symtab_end, name, (char *)symtab);
  177         printf("[ preserving %lu bytes of %s symbol table ]\n",
  178                (u_long)roundup(((char*)esymtab - (char*)symtab), sizeof(u_long)), name);
  179         return;
  180 
  181  badheader:
  182         printf("[ %s symbol table not valid ]\n", name);
  183         return;
  184 
  185  multiple_strtab:
  186         printf("[ %s has multiple string tables ]\n", name);
  187         return;
  188 
  189  multiple_symtab:
  190         printf("[ %s has multiple symbol tables ]\n", name);
  191         return;
  192 }
  193 
  194 /*
  195  * Internal helper function - return a pointer to the string table
  196  * for the current symbol table.
  197  */
  198 static char *
  199 db_elf_find_strtab(stab)
  200         db_symtab_t *stab;
  201 {
  202         Elf_Ehdr *elf = STAB_TO_EHDR(stab);
  203         Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
  204         int i;
  205 
  206         for (i = 0; i < elf->e_shnum; i++) {
  207                 if (shp[i].sh_type == SHT_STRTAB
  208                     && !shp[i].sh_addr && i != elf->e_shstrndx)
  209                         return (stab->private + shp[i].sh_offset);
  210         }
  211 
  212         return (NULL);
  213 }
  214 
  215 /*
  216  * Lookup the symbol with the given name.
  217  */
  218 db_sym_t
  219 X_db_lookup(stab, symstr)
  220         db_symtab_t *stab;
  221         char *symstr;
  222 {
  223         Elf_Sym *symp, *symtab_start, *symtab_end;
  224         char *strtab;
  225 
  226         symtab_start = STAB_TO_SYMSTART(stab);
  227         symtab_end = STAB_TO_SYMEND(stab);
  228 
  229         strtab = db_elf_find_strtab(stab);
  230         if (strtab == NULL)
  231                 return ((db_sym_t)0);
  232 
  233         for (symp = symtab_start; symp < symtab_end; symp++) {
  234                 if (symp->st_name != 0 &&
  235                     db_eqname(strtab + symp->st_name, symstr, 0))
  236                         return ((db_sym_t)symp);
  237         }
  238 
  239         return ((db_sym_t)0);
  240 }
  241 
  242 /*
  243  * Search for the symbol with the given address (matching within the
  244  * provided threshold).
  245  */
  246 db_sym_t
  247 X_db_search_symbol(symtab, off, strategy, diffp)
  248         db_symtab_t *symtab;
  249         db_addr_t off;
  250         db_strategy_t strategy;
  251         db_expr_t *diffp;               /* in/out */
  252 {
  253         Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end;
  254         db_expr_t diff = *diffp;
  255 
  256         symtab_start = STAB_TO_SYMSTART(symtab);
  257         symtab_end = STAB_TO_SYMEND(symtab);
  258 
  259         rsymp = NULL;
  260 
  261         for (symp = symtab_start; symp < symtab_end; symp++) {
  262                 if (symp->st_name == 0)
  263                         continue;
  264                 if (ELF_ST_TYPE(symp->st_info) != STT_OBJECT &&
  265                     ELF_ST_TYPE(symp->st_info) != STT_FUNC)
  266                         continue;
  267 
  268                 if (off >= symp->st_value) {
  269                         if ((off - symp->st_value) < diff) {
  270                                 diff = off - symp->st_value;
  271                                 rsymp = symp;
  272                                 if (diff == 0) {
  273                                         if (strategy == DB_STGY_PROC &&
  274                                             ELF_ST_TYPE(symp->st_info) ==
  275                                               STT_FUNC &&
  276                                             ELF_ST_BIND(symp->st_info) !=
  277                                               STB_LOCAL)
  278                                                 break;
  279                                         if (strategy == DB_STGY_ANY &&
  280                                             ELF_ST_BIND(symp->st_info) !=
  281                                               STB_LOCAL)
  282                                                 break;
  283                                 }
  284                         } else if ((off - symp->st_value) == diff) {
  285                                 if (rsymp == NULL)
  286                                         rsymp = symp;
  287                                 else if (ELF_ST_BIND(rsymp->st_info) ==
  288                                       STB_LOCAL &&
  289                                     ELF_ST_BIND(symp->st_info) !=
  290                                       STB_LOCAL) {
  291                                         /* pick the external symbol */
  292                                         rsymp = symp;
  293                                 }
  294                         }
  295                 }
  296         }
  297 
  298         if (rsymp == NULL)
  299                 *diffp = off;
  300         else
  301                 *diffp = diff;
  302 
  303         return ((db_sym_t)rsymp);
  304 }
  305 
  306 /*
  307  * Return the name and value for a symbol.
  308  */
  309 void
  310 X_db_symbol_values(symtab, sym, namep, valuep)
  311         db_symtab_t *symtab;
  312         db_sym_t sym;
  313         char **namep;
  314         db_expr_t *valuep;
  315 {
  316         Elf_Sym *symp = (Elf_Sym *)sym;
  317         char *strtab;
  318 
  319         if (namep) {
  320                 strtab = db_elf_find_strtab(symtab);
  321                 if (strtab == NULL)
  322                         *namep = NULL;
  323                 else
  324                         *namep = strtab + symp->st_name;
  325         }
  326 
  327         if (valuep)
  328                 *valuep = symp->st_value;
  329 }
  330 
  331 /*
  332  * Return the file and line number of the current program counter
  333  * if we can find the appropriate debugging symbol.
  334  */
  335 boolean_t
  336 X_db_line_at_pc(symtab, cursym, filename, linenum, off)
  337         db_symtab_t *symtab;
  338         db_sym_t cursym;
  339         char **filename;
  340         int *linenum;
  341         db_expr_t off;
  342 {
  343 
  344         /*
  345          * XXX We don't support this (yet).
  346          */
  347         return (FALSE);
  348 }
  349 
  350 /*
  351  * Returns the number of arguments to a function and their
  352  * names if we can find the appropriate debugging symbol.
  353  */
  354 boolean_t
  355 X_db_sym_numargs(symtab, cursym, nargp, argnamep)
  356         db_symtab_t *symtab;
  357         db_sym_t cursym;
  358         int *nargp;
  359         char **argnamep;
  360 {
  361 
  362         /*
  363          * XXX We don't support this (yet).
  364          */
  365         return (FALSE);
  366 }
  367 
  368 /*
  369  * Initialization routine for Elf files.
  370  */
  371 extern void *ksym_start, *ksym_end;
  372 
  373 void
  374 kdb_init(void)
  375 {
  376 
  377         if (ksym_end > ksym_start)
  378                 X_db_sym_init(ksym_start, ksym_end, "kernel");
  379 }
  380 
  381 #endif

Cache object: 8a843537e3414f28060cb0e29967f414


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.