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: releng/5.0/sys/ddb/db_elf.c 103362 2002-09-15 22:28:39Z bde $ */
    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 #include "opt_ddb.h"
   42 
   43 #ifdef DDB_NOKLDSYM
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 
   48 #ifdef __i386__
   49 #include <machine/bootinfo.h>
   50 #endif
   51 
   52 #include <ddb/ddb.h>
   53 #include <ddb/db_sym.h>
   54 
   55 #include <machine/elf.h>
   56 
   57 #ifndef _ALIGNED_POINTER
   58 #define _ALIGNED_POINTER(ptr, type)     1
   59 #endif
   60 
   61 static char *db_elf_find_strtab(db_symtab_t *);
   62 
   63 #define STAB_TO_SYMSTART(stab)  ((Elf_Sym *)((stab)->start))
   64 #define STAB_TO_SYMEND(stab)    ((Elf_Sym *)((stab)->end))
   65 #define STAB_TO_EHDR(stab)      ((Elf_Ehdr *)((stab)->private))
   66 #define STAB_TO_SHDR(stab, e)   ((Elf_Shdr *)((stab)->private + (e)->e_shoff))
   67 
   68 void X_db_sym_init(void *symtab, void *esymtab, char *name);
   69 
   70 /*
   71  * Find the symbol table and strings; tell ddb about them.
   72  */
   73 void
   74 X_db_sym_init(symtab, esymtab, name)
   75         void *symtab;           /* pointer to start of symbol table */
   76         void *esymtab;          /* pointer to end of string table,
   77                                    for checking - rounded up to integer
   78                                    boundary */
   79         char *name;
   80 {
   81         Elf_Ehdr *elf;
   82         Elf_Shdr *shp;
   83         Elf_Sym *symp, *symtab_start, *symtab_end;
   84         char *strtab_start, *strtab_end;
   85         int i;
   86 
   87         if (_ALIGNED_POINTER(symtab, long) == 0) {
   88                 printf("DDB: bad symbol table start address %p\n", symtab);
   89                 return;
   90         }
   91 
   92         symtab_start = symtab_end = NULL;
   93         strtab_start = strtab_end = NULL;
   94 
   95         /*
   96          * The format of the symbols loaded by the boot program is:
   97          *
   98          *      Elf exec header
   99          *      first section header
  100          *      . . .
  101          *      . . .
  102          *      last section header
  103          *      first symbol or string table section
  104          *      . . .
  105          *      . . .
  106          *      last symbol or string table section
  107          */
  108 
  109         /*
  110          * Validate the Elf header.
  111          */
  112         elf = (Elf_Ehdr *)symtab;
  113         if (elf->e_ident[EI_MAG0] != ELFMAG0
  114             || elf->e_ident[EI_MAG1] != ELFMAG1
  115             || elf->e_ident[EI_MAG2] != ELFMAG2
  116             || elf->e_ident[EI_MAG3] != ELFMAG3)
  117                 goto badheader;
  118 
  119         if (!ELF_MACHINE_OK(elf->e_machine))
  120                 goto badheader;
  121 
  122         /*
  123          * We need to avoid the section header string table (small string
  124          * table which names the sections).  We do this by assuming that
  125          * the following two conditions will be true:
  126          *
  127          *      (1) .shstrtab will be smaller than one page.
  128          *      (2) .strtab will be larger than one page.
  129          *
  130          * When we encounter what we think is the .shstrtab, we change
  131          * its section type Elf_sht_null so that it will be ignored
  132          * later.
  133          */
  134         shp = (Elf_Shdr *)((char*)symtab + elf->e_shoff);
  135         for (i = 0; i < elf->e_shnum; i++) {
  136                 if (shp[i].sh_addr || i == elf->e_shstrndx)
  137                         continue;
  138                 switch (shp[i].sh_type) {
  139                 case SHT_STRTAB:
  140                         if (shp[i].sh_size < PAGE_SIZE) {
  141                                 shp[i].sh_type = SHT_NULL;
  142                                 continue;
  143                         }
  144                         if (strtab_start != NULL)
  145                                 goto multiple_strtab;
  146                         strtab_start = (char *)symtab + shp[i].sh_offset;
  147                         strtab_end = (char *)symtab + shp[i].sh_offset +
  148                             shp[i].sh_size;
  149                         break;
  150 
  151                 case SHT_SYMTAB:
  152                         if (symtab_start != NULL)
  153                                 goto multiple_symtab;
  154                         symtab_start = (Elf_Sym *)((char*)symtab + shp[i].sh_offset);
  155                         symtab_end = (Elf_Sym *)((char*)symtab + shp[i].sh_offset +
  156                             shp[i].sh_size);
  157                         break;
  158 
  159                 default:
  160                         /* Ignore all other sections. */
  161                         break;
  162                 }
  163         }
  164 
  165         /*
  166          * Now, sanity check the symbols against the string table.
  167          */
  168         if (symtab_start == NULL || strtab_start == NULL ||
  169             _ALIGNED_POINTER(symtab_start, long) == 0 ||
  170             _ALIGNED_POINTER(strtab_start, long) == 0)
  171                 goto badheader;
  172         for (symp = symtab_start; symp < symtab_end; symp++)
  173                 if (symp->st_name + strtab_start > strtab_end)
  174                         goto badheader;
  175 
  176         /*
  177          * Link the symbol table into the debugger.
  178          */
  179         db_add_symbol_table((char *)symtab_start,
  180                             (char *)symtab_end, name, (char *)symtab);
  181         printf("[ preserving %lu bytes of %s symbol table ]\n",
  182                (u_long)roundup(((char*)esymtab - (char*)symtab), sizeof(u_long)), name);
  183         return;
  184 
  185  badheader:
  186         printf("[ %s symbol table not valid ]\n", name);
  187         return;
  188 
  189  multiple_strtab:
  190         printf("[ %s has multiple string tables ]\n", name);
  191         return;
  192 
  193  multiple_symtab:
  194         printf("[ %s has multiple symbol tables ]\n", name);
  195         return;
  196 }
  197 
  198 /*
  199  * Internal helper function - return a pointer to the string table
  200  * for the current symbol table.
  201  */
  202 static char *
  203 db_elf_find_strtab(stab)
  204         db_symtab_t *stab;
  205 {
  206         Elf_Ehdr *elf = STAB_TO_EHDR(stab);
  207         Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
  208         int i;
  209 
  210         for (i = 0; i < elf->e_shnum; i++) {
  211                 if (shp[i].sh_type == SHT_STRTAB
  212                     && !shp[i].sh_addr && i != elf->e_shstrndx)
  213                         return (stab->private + shp[i].sh_offset);
  214         }
  215 
  216         return (NULL);
  217 }
  218 
  219 /*
  220  * Lookup the symbol with the given name.
  221  */
  222 c_db_sym_t
  223 X_db_lookup(stab, symstr)
  224         db_symtab_t *stab;
  225         const char *symstr;
  226 {
  227         Elf_Sym *symp, *symtab_start, *symtab_end;
  228         char *strtab;
  229 
  230         symtab_start = STAB_TO_SYMSTART(stab);
  231         symtab_end = STAB_TO_SYMEND(stab);
  232 
  233         strtab = db_elf_find_strtab(stab);
  234         if (strtab == NULL)
  235                 return ((db_sym_t)0);
  236 
  237         for (symp = symtab_start; symp < symtab_end; symp++) {
  238                 if (symp->st_name != 0 &&
  239                     db_eqname(strtab + symp->st_name, symstr, 0))
  240                         return ((db_sym_t)symp);
  241         }
  242 
  243         return ((db_sym_t)0);
  244 }
  245 
  246 /*
  247  * Search for the symbol with the given address (matching within the
  248  * provided threshold).
  249  */
  250 c_db_sym_t
  251 X_db_search_symbol(symtab, off, strategy, diffp)
  252         db_symtab_t *symtab;
  253         db_addr_t off;
  254         db_strategy_t strategy;
  255         db_expr_t *diffp;               /* in/out */
  256 {
  257         Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end;
  258         db_expr_t diff = *diffp;
  259 
  260         symtab_start = STAB_TO_SYMSTART(symtab);
  261         symtab_end = STAB_TO_SYMEND(symtab);
  262 
  263         rsymp = NULL;
  264 
  265         for (symp = symtab_start; symp < symtab_end; symp++) {
  266                 if (symp->st_name == 0)
  267                         continue;
  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         c_db_sym_t sym;
  313         const char **namep;
  314         db_expr_t *valuep;
  315 {
  316         const Elf_Sym *symp = (const 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         c_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         c_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 
  372 #ifdef __i386__
  373 void *ksym_start, *ksym_end;
  374 #else
  375 extern void *ksym_start, *ksym_end;
  376 #endif
  377 
  378 void
  379 kdb_init(void)
  380 {
  381         static Elf_Ehdr elf;
  382         static Elf_Shdr sh[2];
  383 
  384 #ifdef __i386__
  385         ksym_start = (void *)bootinfo.bi_symtab;
  386         ksym_end = (void *)bootinfo.bi_esymtab;
  387 #endif
  388         if (ksym_end <= ksym_start)
  389                 return;
  390 
  391         /*
  392          * The FreeBSD boot program doesn't actually load any headers, so
  393          * fake just enough for the routines in this file to work.
  394          */
  395         elf.e_ident[EI_MAG0] = ELFMAG0;
  396         elf.e_ident[EI_MAG1] = ELFMAG1;
  397         elf.e_ident[EI_MAG2] = ELFMAG2;
  398         elf.e_ident[EI_MAG3] = ELFMAG3;
  399         elf.e_machine = EM_486;
  400         elf.e_shoff = (uintptr_t)(void *)&sh[0] - (uintptr_t)(void *)&elf;
  401         sh[0].sh_type = SHT_SYMTAB;
  402         sh[0].sh_offset = (uintptr_t)ksym_start + sizeof(long) -
  403             (uintptr_t)(void *)&elf;
  404         sh[0].sh_size = *(int *)ksym_start;
  405         sh[1].sh_type = SHT_STRTAB;
  406         sh[1].sh_offset = sh[0].sh_offset + sh[0].sh_size + sizeof(long);
  407         sh[1].sh_size = (uintptr_t)ksym_end - (uintptr_t)ksym_start -
  408             sizeof(long) - sh[0].sh_size - sizeof(long);
  409         elf.e_shstrndx = -1;
  410         elf.e_shnum = 2;
  411 
  412         X_db_sym_init(&elf, ksym_end, "kernel");
  413 }
  414 
  415 #endif /* DDB_NOKLDSYM */

Cache object: 77efc0d50b5625ccacd4b97bbad8b4b3


[ 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.