LCOV - code coverage report
Current view: top level - ddb - db_elf.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 179 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: db_elf.c,v 1.28 2017/09/08 05:36:52 deraadt 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             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      22             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      23             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      24             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      25             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      26             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      27             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      28             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      29             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      30             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      31             :  * POSSIBILITY OF SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #include <sys/param.h>
      35             : #include <sys/stdint.h>
      36             : #include <sys/systm.h>
      37             : #include <sys/exec.h>
      38             : 
      39             : #include <machine/db_machdep.h>
      40             : 
      41             : #include <ddb/db_elf.h>
      42             : #include <ddb/db_sym.h>
      43             : #include <ddb/db_output.h>
      44             : 
      45             : #include <sys/exec_elf.h>
      46             : 
      47             : db_symtab_t db_symtab;
      48             : 
      49             : Elf_Sym         *db_elf_sym_lookup(char *);
      50             : 
      51             : /*
      52             :  * Find the symbol table and strings; tell ddb about them.
      53             :  *
      54             :  * symsize:     size of symbol table
      55             :  * symtab:      pointer to start of symbol table
      56             :  * esymtab:     pointer to end of string table, for checking - rounded up to
      57             :  *                  integer boundry
      58             :  */
      59             : int
      60           0 : db_elf_sym_init(int symsize, void *symtab, void *esymtab, const char *name)
      61             : {
      62             :         Elf_Ehdr *elf;
      63             :         Elf_Shdr *shp;
      64             :         Elf_Sym *symp, *symtab_start, *symtab_end;
      65             :         char *shstrtab, *strtab_start, *strtab_end;
      66             :         int i;
      67             :         char *errstr = "";
      68             : 
      69             :         if (ALIGNED_POINTER(symtab, long) == 0) {
      70             :                 db_printf("[ %s symbol table has bad start address %p ]\n",
      71             :                     name, symtab);
      72             :                 return (0);
      73             :         }
      74             : 
      75             :         symtab_start = symtab_end = NULL;
      76             :         strtab_start = strtab_end = NULL;
      77             : 
      78             :         /*
      79             :          * The format of the symbols loaded by the boot program is:
      80             :          *
      81             :          *      Elf exec header
      82             :          *      first section header
      83             :          *      . . .
      84             :          *      . . .
      85             :          *      last section header
      86             :          *      first symbol, string, or line table section
      87             :          *      . . .
      88             :          *      . . .
      89             :          *      last symbol, string, or line table section
      90             :          */
      91             : 
      92             :         /*
      93             :          * Validate the Elf header.
      94             :          */
      95           0 :         elf = (Elf_Ehdr *)symtab;
      96           0 :         if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
      97           0 :             elf->e_ident[EI_CLASS] != ELFCLASS) {
      98             :                 errstr = "bad magic";
      99           0 :                 goto badheader;
     100             :         }
     101             : 
     102           0 :         if (elf->e_machine != ELF_TARG_MACH) {
     103             :                 errstr = "bad e_machine";
     104           0 :                 goto badheader;
     105             :         }
     106             : 
     107             :         /*
     108             :          * Find the section header string table (.shstrtab), and look up
     109             :          * the symbol table (.symtab) and string table (.strtab) via their
     110             :          * names in shstrtab, rather than by table type.
     111             :          * This works in the presence of multiple string tables, such as
     112             :          * stabs data found when booting bsd.gdb.
     113             :          */
     114           0 :         shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff);
     115           0 :         shstrtab = (char *)symtab + shp[elf->e_shstrndx].sh_offset;
     116           0 :         for (i = 0; i < elf->e_shnum; i++) {
     117           0 :                 if (shp[i].sh_type == SHT_SYMTAB) {
     118             :                         int j;
     119             : 
     120           0 :                         if (shp[i].sh_offset == 0)
     121           0 :                                 continue;
     122           0 :                         symtab_start = (Elf_Sym *)((char *)symtab +
     123             :                             shp[i].sh_offset);
     124           0 :                         symtab_end = (Elf_Sym *)((char *)symtab +
     125           0 :                             shp[i].sh_offset + shp[i].sh_size);
     126           0 :                         j = shp[i].sh_link;
     127           0 :                         if (shp[j].sh_offset == 0)
     128           0 :                                 continue;
     129           0 :                         strtab_start = (char *)symtab + shp[j].sh_offset;
     130           0 :                         strtab_end = (char *)symtab + shp[j].sh_offset +
     131           0 :                             shp[j].sh_size;
     132           0 :                         break;
     133             :                 }
     134             : 
     135             :                 /*
     136             :                  * This is the old way of doing things.
     137             :                  * XXX - verify that it's not needed.
     138             :                  */
     139           0 :                 if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0) {
     140           0 :                         strtab_start = (char *)symtab + shp[i].sh_offset;
     141           0 :                         strtab_end = (char *)symtab + shp[i].sh_offset +
     142           0 :                             shp[i].sh_size;
     143           0 :                 } else if (strcmp(".symtab", shstrtab+shp[i].sh_name) == 0) {
     144           0 :                         symtab_start = (Elf_Sym *)((char *)symtab +
     145           0 :                             shp[i].sh_offset);
     146           0 :                         symtab_end = (Elf_Sym *)((char *)symtab +
     147           0 :                             shp[i].sh_offset + shp[i].sh_size);
     148           0 :                 }
     149             :         }
     150             : 
     151             :         /*
     152             :          * Now, sanity check the symbols against the string table.
     153             :          */
     154           0 :         if (symtab_start == NULL || strtab_start == NULL ||
     155             :             ALIGNED_POINTER(symtab_start, long) == 0 ||
     156             :             ALIGNED_POINTER(strtab_start, long) == 0) {
     157             :                 errstr = "symtab unaligned";
     158           0 :                 goto badheader;
     159             :         }
     160           0 :         for (symp = symtab_start; symp < symtab_end; symp++)
     161           0 :                 if (symp->st_name + strtab_start > strtab_end) {
     162             :                         errstr = "symtab corrupted";
     163           0 :                         goto badheader;
     164             :                 }
     165             : 
     166             :         /*
     167             :          * Link the symbol table into the debugger.
     168             :          */
     169           0 :         db_symtab.start = (char *)symtab_start;
     170           0 :         db_symtab.end = (char *)symtab_end;
     171           0 :         db_symtab.name = name;
     172           0 :         db_symtab.private = (char *)symtab;
     173             : 
     174           0 :         db_printf("[ using %lu bytes of %s ELF symbol table ]\n",
     175           0 :             (u_long)roundup(((char *)esymtab - (char *)symtab), sizeof(u_long)),
     176             :             name);
     177             : 
     178           0 :         return (1);
     179             : 
     180             :  badheader:
     181           0 :         db_printf("[ %s ELF symbol table not valid: %s ]\n", name, errstr);
     182           0 :         return (0);
     183           0 : }
     184             : 
     185             : /*
     186             :  * Internal helper function - return a pointer to the string table
     187             :  * for the current symbol table.
     188             :  */
     189             : char *
     190           0 : db_elf_find_strtab(db_symtab_t *stab)
     191             : {
     192           0 :         Elf_Ehdr *elf = STAB_TO_EHDR(stab);
     193           0 :         Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
     194             :         char *shstrtab;
     195             :         int i;
     196             : 
     197           0 :         shstrtab = (char *)elf + shp[elf->e_shstrndx].sh_offset;
     198           0 :         for (i = 0; i < elf->e_shnum; i++) {
     199           0 :                 if (shp[i].sh_type == SHT_SYMTAB)
     200           0 :                         return ((char *)elf + shp[shp[i].sh_link].sh_offset);
     201           0 :                 if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0)
     202           0 :                         return ((char *)elf + shp[i].sh_offset);
     203             :         }
     204             : 
     205           0 :         return (NULL);
     206           0 : }
     207             : 
     208             : /*
     209             :  * Internal helper function - return a pointer to the section
     210             :  * named ``sname''.
     211             :  */
     212             : const char *
     213           0 : db_elf_find_section(db_symtab_t *stab, size_t *size, const char *sname)
     214             : {
     215           0 :         Elf_Ehdr *elf = STAB_TO_EHDR(stab);
     216           0 :         Elf_Shdr *shp = STAB_TO_SHDR(stab, elf);
     217             :         char *shstrtab;
     218             :         int i;
     219             : 
     220           0 :         shstrtab = (char *)elf + shp[elf->e_shstrndx].sh_offset;
     221           0 :         for (i = 0; i < elf->e_shnum; i++) {
     222           0 :                 if ((shp[i].sh_flags & SHF_ALLOC) != 0 &&
     223           0 :                     strcmp(sname, shstrtab+shp[i].sh_name) == 0) {
     224           0 :                         *size = shp[i].sh_size;
     225           0 :                         return ((char *)elf + shp[i].sh_offset);
     226             :                 }
     227             :         }
     228             : 
     229           0 :         return (NULL);
     230           0 : }
     231             : 
     232             : /*
     233             :  * Lookup the symbol with the given name.
     234             :  */
     235             : Elf_Sym *
     236           0 : db_elf_sym_lookup(char *symstr)
     237             : {
     238             :         db_symtab_t *stab = &db_symtab;
     239             :         Elf_Sym *symp, *symtab_start, *symtab_end;
     240             :         char *strtab;
     241             : 
     242           0 :         if (stab->private == NULL)
     243           0 :                 return (NULL);
     244             : 
     245           0 :         symtab_start = STAB_TO_SYMSTART(stab);
     246           0 :         symtab_end = STAB_TO_SYMEND(stab);
     247             : 
     248           0 :         strtab = db_elf_find_strtab(stab);
     249           0 :         if (strtab == NULL)
     250           0 :                 return (NULL);
     251             : 
     252           0 :         for (symp = symtab_start; symp < symtab_end; symp++) {
     253           0 :                 if (symp->st_name != 0 &&
     254           0 :                     db_eqname(strtab + symp->st_name, symstr, 0))
     255           0 :                         return (symp);
     256             :         }
     257             : 
     258           0 :         return (NULL);
     259           0 : }
     260             : 
     261             : /*
     262             :  * Search for the symbol with the given address (matching within the
     263             :  * provided threshold).
     264             :  */
     265             : Elf_Sym *
     266           0 : db_elf_sym_search(db_addr_t off, db_strategy_t strategy,
     267             :     db_expr_t *diffp)
     268             : {
     269             :         db_symtab_t *stab = &db_symtab;
     270             :         Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end;
     271           0 :         db_expr_t diff = *diffp;
     272             : 
     273           0 :         if (stab->private == NULL)
     274           0 :                 return (NULL);
     275             : 
     276           0 :         symtab_start = STAB_TO_SYMSTART(stab);
     277           0 :         symtab_end = STAB_TO_SYMEND(stab);
     278             : 
     279             :         rsymp = NULL;
     280             : 
     281           0 :         for (symp = symtab_start; symp < symtab_end; symp++) {
     282           0 :                 if (symp->st_name == 0)
     283             :                         continue;
     284             : #if 0
     285             :                 /* This prevents me from seeing anythin in locore.s -- eeh */
     286             :                 if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object &&
     287             :                     ELF_SYM_TYPE(symp->st_info) != Elf_estt_func)
     288             :                         continue;
     289             : #endif
     290             : 
     291           0 :                 if (off >= symp->st_value) {
     292           0 :                         if ((off - symp->st_value) < diff) {
     293             :                                 diff = off - symp->st_value;
     294             :                                 rsymp = symp;
     295           0 :                                 if (diff == 0) {
     296           0 :                                         if (strategy == DB_STGY_PROC &&
     297           0 :                                             ELF_ST_TYPE(symp->st_info)
     298           0 :                                               == STT_FUNC &&
     299           0 :                                             ELF_ST_BIND(symp->st_info)
     300           0 :                                               != STB_LOCAL)
     301             :                                                 break;
     302           0 :                                         if (strategy == DB_STGY_ANY &&
     303           0 :                                             ELF_ST_BIND(symp->st_info)
     304           0 :                                               != STB_LOCAL)
     305             :                                                 break;
     306             :                                 }
     307           0 :                         } else if ((off - symp->st_value) == diff) {
     308           0 :                                 if (rsymp == NULL)
     309           0 :                                         rsymp = symp;
     310           0 :                                 else if (ELF_ST_BIND(rsymp->st_info)
     311           0 :                                       == STB_LOCAL &&
     312           0 :                                     ELF_ST_BIND(symp->st_info)
     313           0 :                                       != STB_LOCAL) {
     314             :                                         /* pick the external symbol */
     315             :                                         rsymp = symp;
     316           0 :                                 }
     317             :                         }
     318             :                 }
     319             :         }
     320             : 
     321           0 :         if (rsymp == NULL)
     322           0 :                 *diffp = off;
     323             :         else
     324           0 :                 *diffp = diff;
     325             : 
     326           0 :         return (rsymp);
     327           0 : }
     328             : 
     329             : /*
     330             :  * Return the name and value for a symbol.
     331             :  */
     332             : void
     333           0 : db_symbol_values(Elf_Sym *sym, char **namep, db_expr_t *valuep)
     334             : {
     335             :         db_symtab_t *stab = &db_symtab;
     336             :         Elf_Sym *symp = (Elf_Sym *)sym;
     337             :         char *strtab;
     338             : 
     339           0 :         if (sym == NULL) {
     340           0 :                 *namep = NULL;
     341           0 :                 return;
     342             :         }
     343             : 
     344           0 :         if (stab->private == NULL)
     345           0 :                 return;
     346             : 
     347           0 :         if (namep) {
     348           0 :                 strtab = db_elf_find_strtab(stab);
     349           0 :                 if (strtab == NULL)
     350           0 :                         *namep = NULL;
     351             :                 else
     352           0 :                         *namep = strtab + symp->st_name;
     353             :         }
     354             : 
     355           0 :         if (valuep)
     356           0 :                 *valuep = symp->st_value;
     357           0 : }
     358             : 
     359             : /*
     360             :  * Return the file and line number of the current program counter
     361             :  * if we can find the appropriate debugging symbol.
     362             :  */
     363             : int
     364           0 : db_elf_line_at_pc(Elf_Sym *cursym, char **filename,
     365             :     int *linenum, db_expr_t off)
     366             : {
     367             :         db_symtab_t *stab = &db_symtab;
     368             :         static char path[PATH_MAX];
     369           0 :         const char *linetab, *dirname, *basename;
     370           0 :         size_t linetab_size;
     371             : 
     372           0 :         if (stab->private == NULL)
     373           0 :                 return (0);
     374             : 
     375           0 :         linetab = db_elf_find_section(stab, &linetab_size, ".debug_line");
     376           0 :         if (linetab == NULL)
     377           0 :                 return (0);
     378             : 
     379           0 :         if (!db_dwarf_line_at_pc(linetab, linetab_size, off,
     380             :             &dirname, &basename, linenum))
     381           0 :                 return (0);
     382             : 
     383           0 :         if (dirname == NULL)
     384           0 :                 strlcpy(path, basename, sizeof(path));
     385             :         else
     386           0 :                 snprintf(path, sizeof(path), "%s/%s", dirname, basename);
     387           0 :         *filename = path;
     388           0 :         return (1);
     389           0 : }
     390             : 
     391             : void
     392           0 : db_elf_sym_forall(db_forall_func_t db_forall_func, void *arg)
     393             : {
     394             :         db_symtab_t *stab = &db_symtab;
     395             :         char *strtab;
     396             :         static char suffix[2];
     397             :         Elf_Sym *symp, *symtab_start, *symtab_end;
     398             : 
     399           0 :         if (stab->private == NULL)
     400           0 :                 return;
     401             : 
     402           0 :         symtab_start = STAB_TO_SYMSTART(stab);
     403           0 :         symtab_end = STAB_TO_SYMEND(stab);
     404             : 
     405           0 :         strtab = db_elf_find_strtab(stab);
     406           0 :         if (strtab == NULL)
     407           0 :                 return;
     408             : 
     409           0 :         for (symp = symtab_start; symp < symtab_end; symp++)
     410           0 :                 if (symp->st_name != 0) {
     411           0 :                         suffix[1] = '\0';
     412           0 :                         switch (ELF_ST_TYPE(symp->st_info)) {
     413             :                         case STT_OBJECT:
     414           0 :                                 suffix[0] = '+';
     415           0 :                                 break;
     416             :                         case STT_FUNC:
     417           0 :                                 suffix[0] = '*';
     418           0 :                                 break;
     419             :                         case STT_SECTION:
     420           0 :                                 suffix[0] = '&';
     421           0 :                                 break;
     422             :                         case STT_FILE:
     423           0 :                                 suffix[0] = '/';
     424           0 :                                 break;
     425             :                         default:
     426           0 :                                 suffix[0] = '\0';
     427           0 :                         }
     428           0 :                         (*db_forall_func)(symp,
     429           0 :                             strtab + symp->st_name, suffix, 0, arg);
     430           0 :                 }
     431           0 : }
     432             : 
     433             : Elf_Sym *
     434           0 : db_symbol_by_name(char *name, db_expr_t *valuep)
     435             : {
     436             :         Elf_Sym         *sym;
     437             : 
     438           0 :         sym = db_elf_sym_lookup(name);
     439           0 :         if (sym == NULL)
     440           0 :             return (NULL);
     441           0 :         db_symbol_values(sym, &name, valuep);
     442           0 :         return (sym);
     443           0 : }

Generated by: LCOV version 1.13