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 /*      $NetBSD: db_elf.c,v 1.4 1998/05/03 18:49:54 thorpej Exp $       */
    2 /*-
    3  * Copyright (c) 1997 The NetBSD Foundation, Inc.
    4  * All rights reserved.
    5  *
    6  * This code is derived from software contributed to The NetBSD Foundation
    7  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
    8  * NASA Ames Research Center.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD: releng/5.2/sys/ddb/db_elf.c 120543 2003-09-28 06:02:33Z bde $");
   41 
   42 #include "opt_ddb.h"
   43 
   44 #ifdef DDB_NOKLDSYM
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 
   49 #ifdef __i386__
   50 #include <machine/bootinfo.h>
   51 #endif
   52 
   53 #include <ddb/ddb.h>
   54 #include <ddb/db_sym.h>
   55 
   56 #include <machine/elf.h>
   57 
   58 #ifndef _ALIGNED_POINTER
   59 #define _ALIGNED_POINTER(ptr, type)     1
   60 #endif
   61 
   62 static char *db_elf_find_strtab(db_symtab_t *);
   63 
   64 #define STAB_TO_SYMSTART(stab)  ((Elf_Sym *)((stab)->start))
   65 #define STAB_TO_SYMEND(stab)    ((Elf_Sym *)((stab)->end))
   66 #define STAB_TO_EHDR(stab)      ((Elf_Ehdr *)((stab)->private))
   67 #define STAB_TO_SHDR(stab, e)   ((Elf_Shdr *)((stab)->private + (e)->e_shoff))
   68 
   69 void X_db_sym_init(void *symtab, void *esymtab, char *name);
   70 
   71 /*
   72  * Find the symbol table and strings; tell ddb about them.
   73  */
   74 void
   75 X_db_sym_init(symtab, esymtab, name)
   76         void *symtab;           /* pointer to start of symbol table */
   77         void *esymtab;          /* pointer to end of string table,
   78                                    for checking - rounded up to integer
   79                                    boundary */
   80         char *name;
   81 {
   82         Elf_Ehdr *elf;
   83         Elf_Shdr *shp;
   84         Elf_Sym *symp, *symtab_start, *symtab_end;
   85         char *strtab_start, *strtab_end;
   86         int i;
   87 
   88         if (_ALIGNED_POINTER(symtab, long) == 0) {
   89                 printf("DDB: bad symbol table start address %p\n", symtab);
   90                 return;
   91         }
   92 
   93         symtab_start = symtab_end = NULL;
   94         strtab_start = strtab_end = NULL;
   95 
   96         /*
   97          * The format of the symbols loaded by the boot program is:
   98          *
   99          *      Elf exec header
  100          *      first section header
  101          *      . . .
  102          *      . . .
  103          *      last section header
  104          *      first symbol or string table section
  105          *      . . .
  106          *      . . .
  107          *      last symbol or string table section
  108          */
  109 
  110         /*
  111          * Validate the Elf header.
  112          */
  113         elf = (Elf_Ehdr *)symtab;
  114         if (elf->e_ident[EI_MAG0] != ELFMAG0
  115             || elf->e_ident[EI_MAG1] != ELFMAG1
  116             || elf->e_ident[EI_MAG2] != ELFMAG2
  117             || elf->e_ident[EI_MAG3] != ELFMAG3)
  118                 goto badheader;
  119 
  120         if (!ELF_MACHINE_OK(elf->e_machine))
  121                 goto badheader;
  122 
  123         /*
  124          * We need to avoid the section header string table (small string
  125          * table which names the sections).  We do this by assuming that
  126          * the following two conditions will be true:
  127          *
  128          *      (1) .shstrtab will be smaller than one page.
  129          *      (2) .strtab will be larger than one page.
  130          *
  131          * When we encounter what we think is the .shstrtab, we change
  132          * its section type Elf_sht_null so that it will be ignored
  133          * later.
  134          */
  135         shp = (Elf_Shdr *)((char*)symtab + elf->e_shoff);
  136         for (i = 0; i < elf->e_shnum; i++) {
  137                 if (shp[i].sh_addr || i == elf->e_shstrndx)
  138                         continue;
  139                 switch (shp[i].sh_type) {
  140                 case SHT_STRTAB:
  141                         if (shp[i].sh_size < PAGE_SIZE) {
  142                                 shp[i].sh_type = SHT_NULL;
  143                                 continue;
  144                         }
  145                         if (strtab_start != NULL)
  146                                 goto multiple_strtab;
  147                         strtab_start = (char *)symtab + shp[i].sh_offset;
  148                         strtab_end = (char *)symtab + shp[i].sh_offset +
  149                             shp[i].sh_size;
  150                         break;
  151 
  152                 case SHT_SYMTAB:
  153                         if (symtab_start != NULL)
  154                                 goto multiple_symtab;
  155                         symtab_start = (Elf_Sym *)((char*)symtab + shp[i].sh_offset);
  156                         symtab_end = (Elf_Sym *)((char*)symtab + shp[i].sh_offset +
  157                             shp[i].sh_size);
  158                         break;
  159 
  160                 default:
  161                         /* Ignore all other sections. */
  162                         break;
  163                 }
  164         }
  165 
  166         /*
  167          * Now, sanity check the symbols against the string table.
  168          */
  169         if (symtab_start == NULL || strtab_start == NULL ||
  170             _ALIGNED_POINTER(symtab_start, long) == 0 ||
  171             _ALIGNED_POINTER(strtab_start, long) == 0)
  172                 goto badheader;
  173         for (symp = symtab_start; symp < symtab_end; symp++)
  174                 if (symp->st_name + strtab_start > strtab_end)
  175                         goto badheader;
  176 
  177         /*
  178          * Link the symbol table into the debugger.
  179          */
  180         db_add_symbol_table((char *)symtab_start,
  181                             (char *)symtab_end, name, (char *)symtab);
  182         printf("[ preserving %lu bytes of %s symbol table ]\n",
  183                (u_long)roundup(((char*)esymtab - (char*)symtab), sizeof(u_long)), name);
  184         return;
  185 
  186  badheader:
  187         printf("[ %s symbol table not valid ]\n", name);
  188         return;
  189 
  190  multiple_strtab:
  191         printf("[ %s has multiple string tables ]\n", name);
  192         return;
  193 
  194  multiple_symtab:
  195         printf("[ %s has multiple symbol tables ]\n", name);
  196         return;
  197 }
  198 
  199 /*
  200  * Internal helper function - return a pointer to the string table
  201  * for the current symbol table.
  202  */
  203 static char *
  204 db_elf_find_strtab(stab)
  205         db_symtab_t *stab;
  206 {
  207         Elf_Ehdr *elf = STAB_TO_EHDR(stab);
  208         Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
  209         int i;
  210 
  211         for (i = 0; i < elf->e_shnum; i++) {
  212                 if (shp[i].sh_type == SHT_STRTAB
  213                     && !shp[i].sh_addr && i != elf->e_shstrndx)
  214                         return (stab->private + shp[i].sh_offset);
  215         }
  216 
  217         return (NULL);
  218 }
  219 
  220 /*
  221  * Lookup the symbol with the given name.
  222  */
  223 c_db_sym_t
  224 X_db_lookup(stab, symstr)
  225         db_symtab_t *stab;
  226         const char *symstr;
  227 {
  228         Elf_Sym *symp, *symtab_start, *symtab_end;
  229         char *strtab;
  230 
  231         symtab_start = STAB_TO_SYMSTART(stab);
  232         symtab_end = STAB_TO_SYMEND(stab);
  233 
  234         strtab = db_elf_find_strtab(stab);
  235         if (strtab == NULL)
  236                 return ((db_sym_t)0);
  237 
  238         for (symp = symtab_start; symp < symtab_end; symp++) {
  239                 if (symp->st_name != 0 &&
  240                     db_eqname(strtab + symp->st_name, symstr, 0))
  241                         return ((db_sym_t)symp);
  242         }
  243 
  244         return ((db_sym_t)0);
  245 }
  246 
  247 /*
  248  * Search for the symbol with the given address (matching within the
  249  * provided threshold).
  250  */
  251 c_db_sym_t
  252 X_db_search_symbol(symtab, off, strategy, diffp)
  253         db_symtab_t *symtab;
  254         db_addr_t off;
  255         db_strategy_t strategy;
  256         db_expr_t *diffp;               /* in/out */
  257 {
  258         Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end;
  259         db_expr_t diff = *diffp;
  260 
  261         symtab_start = STAB_TO_SYMSTART(symtab);
  262         symtab_end = STAB_TO_SYMEND(symtab);
  263 
  264         rsymp = NULL;
  265 
  266         for (symp = symtab_start; symp < symtab_end; symp++) {
  267                 if (symp->st_name == 0)
  268                         continue;
  269                 if (ELF_ST_TYPE(symp->st_info) != STT_OBJECT &&
  270                     ELF_ST_TYPE(symp->st_info) != STT_FUNC &&
  271                     ELF_ST_TYPE(symp->st_info) != STT_NOTYPE)
  272                         continue;
  273 
  274                 if (off >= symp->st_value) {
  275                         if ((off - symp->st_value) < diff) {
  276                                 diff = off - symp->st_value;
  277                                 rsymp = symp;
  278                                 if (diff == 0) {
  279                                         if (strategy == DB_STGY_PROC &&
  280                                             ELF_ST_TYPE(symp->st_info) ==
  281                                               STT_FUNC &&
  282                                             ELF_ST_BIND(symp->st_info) !=
  283                                               STB_LOCAL)
  284                                                 break;
  285                                         if (strategy == DB_STGY_ANY &&
  286                                             ELF_ST_BIND(symp->st_info) !=
  287                                               STB_LOCAL)
  288                                                 break;
  289                                 }
  290                         } else if ((off - symp->st_value) == diff) {
  291                                 if (rsymp == NULL)
  292                                         rsymp = symp;
  293                                 else if (ELF_ST_BIND(rsymp->st_info) ==
  294                                       STB_LOCAL &&
  295                                     ELF_ST_BIND(symp->st_info) !=
  296                                       STB_LOCAL) {
  297                                         /* pick the external symbol */
  298                                         rsymp = symp;
  299                                 }
  300                         }
  301                 }
  302         }
  303 
  304         if (rsymp == NULL)
  305                 *diffp = off;
  306         else
  307                 *diffp = diff;
  308 
  309         return ((db_sym_t)rsymp);
  310 }
  311 
  312 /*
  313  * Return the name and value for a symbol.
  314  */
  315 void
  316 X_db_symbol_values(symtab, sym, namep, valuep)
  317         db_symtab_t *symtab;
  318         c_db_sym_t sym;
  319         const char **namep;
  320         db_expr_t *valuep;
  321 {
  322         const Elf_Sym *symp = (const Elf_Sym *)sym;
  323         char *strtab;
  324 
  325         if (namep) {
  326                 strtab = db_elf_find_strtab(symtab);
  327                 if (strtab == NULL)
  328                         *namep = NULL;
  329                 else
  330                         *namep = strtab + symp->st_name;
  331         }
  332 
  333         if (valuep)
  334                 *valuep = symp->st_value;
  335 }
  336 
  337 /*
  338  * Return the file and line number of the current program counter
  339  * if we can find the appropriate debugging symbol.
  340  */
  341 boolean_t
  342 X_db_line_at_pc(symtab, cursym, filename, linenum, off)
  343         db_symtab_t *symtab;
  344         c_db_sym_t cursym;
  345         char **filename;
  346         int *linenum;
  347         db_expr_t off;
  348 {
  349 
  350         /*
  351          * XXX We don't support this (yet).
  352          */
  353         return (FALSE);
  354 }
  355 
  356 /*
  357  * Returns the number of arguments to a function and their
  358  * names if we can find the appropriate debugging symbol.
  359  */
  360 boolean_t
  361 X_db_sym_numargs(symtab, cursym, nargp, argnamep)
  362         db_symtab_t *symtab;
  363         c_db_sym_t cursym;
  364         int *nargp;
  365         char **argnamep;
  366 {
  367 
  368         /*
  369          * XXX We don't support this (yet).
  370          */
  371         return (FALSE);
  372 }
  373 
  374 /*
  375  * Initialization routine for Elf files.
  376  */
  377 
  378 #ifdef __i386__
  379 void *ksym_start, *ksym_end;
  380 #else
  381 extern void *ksym_start, *ksym_end;
  382 #endif
  383 
  384 void
  385 kdb_init(void)
  386 {
  387         static Elf_Ehdr elf;
  388         static Elf_Shdr sh[2];
  389 
  390 #ifdef __i386__
  391         ksym_start = (void *)bootinfo.bi_symtab;
  392         ksym_end = (void *)bootinfo.bi_esymtab;
  393 #endif
  394         if (ksym_end <= ksym_start)
  395                 return;
  396 
  397         /*
  398          * The FreeBSD boot program doesn't actually load any headers, so
  399          * fake just enough for the routines in this file to work.
  400          */
  401         elf.e_ident[EI_MAG0] = ELFMAG0;
  402         elf.e_ident[EI_MAG1] = ELFMAG1;
  403         elf.e_ident[EI_MAG2] = ELFMAG2;
  404         elf.e_ident[EI_MAG3] = ELFMAG3;
  405         elf.e_machine = EM_486;
  406         elf.e_shoff = (uintptr_t)(void *)&sh[0] - (uintptr_t)(void *)&elf;
  407         sh[0].sh_type = SHT_SYMTAB;
  408         sh[0].sh_offset = (uintptr_t)ksym_start + sizeof(long) -
  409             (uintptr_t)(void *)&elf;
  410         sh[0].sh_size = *(int *)ksym_start;
  411         sh[1].sh_type = SHT_STRTAB;
  412         sh[1].sh_offset = sh[0].sh_offset + sh[0].sh_size + sizeof(long);
  413         sh[1].sh_size = (uintptr_t)ksym_end - (uintptr_t)ksym_start -
  414             sizeof(long) - sh[0].sh_size - sizeof(long);
  415         elf.e_shstrndx = -1;
  416         elf.e_shnum = 2;
  417 
  418         X_db_sym_init(&elf, ksym_end, "kernel");
  419 }
  420 
  421 #endif /* DDB_NOKLDSYM */

Cache object: 2882cd1bce92e89b425b0b3dadd4d4dd


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