LCOV - code coverage report
Current view: top level - libdw - dwarf_begin_elf.c (source / functions) Hit Total Coverage
Test: elfutils-0.175 Lines: 103 170 60.6 %
Date: 2018-11-16 13:02:39 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Create descriptor from ELF descriptor for processing file.
       2             :    Copyright (C) 2002-2011, 2014, 2015, 2017, 2018 Red Hat, Inc.
       3             :    This file is part of elfutils.
       4             : 
       5             :    This file is free software; you can redistribute it and/or modify
       6             :    it under the terms of either
       7             : 
       8             :      * the GNU Lesser General Public License as published by the Free
       9             :        Software Foundation; either version 3 of the License, or (at
      10             :        your option) any later version
      11             : 
      12             :    or
      13             : 
      14             :      * the GNU General Public License as published by the Free
      15             :        Software Foundation; either version 2 of the License, or (at
      16             :        your option) any later version
      17             : 
      18             :    or both in parallel, as here.
      19             : 
      20             :    elfutils is distributed in the hope that it will be useful, but
      21             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      22             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      23             :    General Public License for more details.
      24             : 
      25             :    You should have received copies of the GNU General Public License and
      26             :    the GNU Lesser General Public License along with this program.  If
      27             :    not, see <http://www.gnu.org/licenses/>.  */
      28             : 
      29             : #ifdef HAVE_CONFIG_H
      30             : # include <config.h>
      31             : #endif
      32             : 
      33             : #include <assert.h>
      34             : #include <stdbool.h>
      35             : #include <stddef.h>
      36             : #include <stdlib.h>
      37             : #include <stdio.h>
      38             : #include <string.h>
      39             : #include <unistd.h>
      40             : #include <sys/types.h>
      41             : #include <sys/stat.h>
      42             : #include <fcntl.h>
      43             : #include <endian.h>
      44             : 
      45             : #include "libelfP.h"
      46             : #include "libdwP.h"
      47             : 
      48             : 
      49             : /* Section names.  (Note .debug_str_offsets is the largest 19 chars.)  */
      50             : static const char dwarf_scnnames[IDX_last][19] =
      51             : {
      52             :   [IDX_debug_info] = ".debug_info",
      53             :   [IDX_debug_types] = ".debug_types",
      54             :   [IDX_debug_abbrev] = ".debug_abbrev",
      55             :   [IDX_debug_addr] = ".debug_addr",
      56             :   [IDX_debug_aranges] = ".debug_aranges",
      57             :   [IDX_debug_line] = ".debug_line",
      58             :   [IDX_debug_line_str] = ".debug_line_str",
      59             :   [IDX_debug_frame] = ".debug_frame",
      60             :   [IDX_debug_loc] = ".debug_loc",
      61             :   [IDX_debug_loclists] = ".debug_loclists",
      62             :   [IDX_debug_pubnames] = ".debug_pubnames",
      63             :   [IDX_debug_str] = ".debug_str",
      64             :   [IDX_debug_str_offsets] = ".debug_str_offsets",
      65             :   [IDX_debug_macinfo] = ".debug_macinfo",
      66             :   [IDX_debug_macro] = ".debug_macro",
      67             :   [IDX_debug_ranges] = ".debug_ranges",
      68             :   [IDX_debug_rnglists] = ".debug_rnglists",
      69             :   [IDX_gnu_debugaltlink] = ".gnu_debugaltlink"
      70             : };
      71             : #define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
      72             : 
      73             : static Dwarf *
      74      274889 : check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
      75             : {
      76             :   GElf_Shdr shdr_mem;
      77             :   GElf_Shdr *shdr;
      78             : 
      79             :   /* Get the section header data.  */
      80      274889 :   shdr = gelf_getshdr (scn, &shdr_mem);
      81      274889 :   if (shdr == NULL)
      82             :     /* We may read /proc/PID/mem with only program headers mapped and section
      83             :        headers out of the mapped pages.  */
      84             :     goto err;
      85             : 
      86             :   /* Ignore any SHT_NOBITS sections.  Debugging sections should not
      87             :      have been stripped, but in case of a corrupt file we won't try
      88             :      to look at the missing data.  */
      89      274889 :   if (unlikely (shdr->sh_type == SHT_NOBITS))
      90             :     return result;
      91             : 
      92             :   /* Make sure the section is part of a section group only iff we
      93             :      really need it.  If we are looking for the global (= non-section
      94             :      group debug info) we have to ignore all the info in section
      95             :      groups.  If we are looking into a section group we cannot look at
      96             :      a section which isn't part of the section group.  */
      97      262509 :   if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0)
      98             :     /* Ignore the section.  */
      99             :     return result;
     100             : 
     101             : 
     102             :   /* We recognize the DWARF section by their names.  This is not very
     103             :      safe and stable but the best we can do.  */
     104      262509 :   const char *scnname = elf_strptr (result->elf, shstrndx,
     105      262509 :                                     shdr->sh_name);
     106      262509 :   if (scnname == NULL)
     107             :     {
     108             :       /* The section name must be valid.  Otherwise is the ELF file
     109             :          invalid.  */
     110           1 :     err:
     111           1 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     112           1 :       __libdw_seterrno (DWARF_E_INVALID_ELF);
     113           1 :       free (result);
     114           1 :       return NULL;
     115             :     }
     116             : 
     117             :   /* Recognize the various sections.  Most names start with .debug_.  */
     118             :   size_t cnt;
     119             :   bool gnu_compressed = false;
     120     4271969 :   for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
     121             :     {
     122     4310524 :       size_t dbglen = strlen (dwarf_scnnames[cnt]);
     123     4310524 :       size_t scnlen = strlen (scnname);
     124     4310524 :       if (strncmp (scnname, dwarf_scnnames[cnt], dbglen) == 0
     125       38597 :           && (dbglen == scnlen
     126         542 :               || (scnlen == dbglen + 4
     127         427 :                   && strstr (scnname, ".dwo") == scnname + dbglen)))
     128             :         break;
     129     4272051 :       else if (scnname[0] == '.' && scnname[1] == 'z'
     130         594 :                && (strncmp (&scnname[2], &dwarf_scnnames[cnt][1],
     131             :                             dbglen - 1) == 0
     132          82 :                    && (scnlen == dbglen + 1
     133           0 :                        || (scnlen == dbglen + 5
     134           0 :                            && strstr (scnname,
     135           0 :                                       ".dwo") == scnname + dbglen + 1))))
     136             :         {
     137             :           gnu_compressed = true;
     138             :           break;
     139             :         }
     140             :     }
     141             : 
     142      262508 :   if (cnt >= ndwarf_scnnames)
     143             :     /* Not a debug section; ignore it. */
     144             :     return result;
     145             : 
     146       38555 :   if (unlikely (result->sectiondata[cnt] != NULL))
     147             :     /* A section appears twice.  That's bad.  We ignore the section.  */
     148             :     return result;
     149             : 
     150             :   /* We cannot know whether or not a GNU compressed section has already
     151             :      been uncompressed or not, so ignore any errors.  */
     152       38555 :   if (gnu_compressed)
     153          82 :     elf_compress_gnu (scn, 0, 0);
     154             : 
     155       38555 :   if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
     156             :     {
     157         298 :       if (elf_compress (scn, 0, 0) < 0)
     158             :         {
     159             :           /* It would be nice if we could fail with a specific error.
     160             :              But we don't know if this was an essential section or not.
     161             :              So just continue for now. See also valid_p().  */
     162             :           return result;
     163             :         }
     164             :     }
     165             : 
     166             :   /* Get the section data.  */
     167       38555 :   Elf_Data *data = elf_getdata (scn, NULL);
     168       38555 :   if (data == NULL)
     169             :     goto err;
     170             : 
     171       38555 :   if (data->d_buf == NULL || data->d_size == 0)
     172             :     /* No data actually available, ignore it. */
     173             :     return result;
     174             : 
     175             :   /* We can now read the section data into results. */
     176       38549 :   result->sectiondata[cnt] = data;
     177             : 
     178       38549 :   return result;
     179             : }
     180             : 
     181             : 
     182             : /* Helper function to set debugdir field.  We want to cache the dir
     183             :    where we found this Dwarf ELF file to locate alt and dwo files.  */
     184             : char *
     185        6025 : __libdw_debugdir (int fd)
     186             : {
     187             :   /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25.  */
     188             :   char devfdpath[25];
     189        6025 :   sprintf (devfdpath, "/proc/self/fd/%u", fd);
     190        6025 :   char *fdpath = realpath (devfdpath, NULL);
     191             :   char *fddir;
     192        6025 :   if (fdpath != NULL && fdpath[0] == '/'
     193        5767 :       && (fddir = strrchr (fdpath, '/')) != NULL)
     194             :     {
     195        5767 :       *++fddir = '\0';
     196        5767 :       return fdpath;
     197             :     }
     198             :   return NULL;
     199             : }
     200             : 
     201             : 
     202             : /* Check whether all the necessary DWARF information is available.  */
     203             : static Dwarf *
     204        5652 : valid_p (Dwarf *result)
     205             : {
     206             :   /* We looked at all the sections.  Now determine whether all the
     207             :      sections with debugging information we need are there.
     208             : 
     209             :      Require at least one section that can be read "standalone".  */
     210        5652 :   if (likely (result != NULL)
     211        5651 :       && unlikely (result->sectiondata[IDX_debug_info] == NULL
     212             :                    && result->sectiondata[IDX_debug_line] == NULL
     213             :                    && result->sectiondata[IDX_debug_frame] == NULL))
     214             :     {
     215          99 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     216          99 :       __libdw_seterrno (DWARF_E_NO_DWARF);
     217          99 :       free (result);
     218          99 :       result = NULL;
     219             :     }
     220             : 
     221             :   /* For dwarf_location_attr () we need a "fake" CU to indicate
     222             :      where the "fake" attribute data comes from.  This is a block
     223             :      inside the .debug_loc or .debug_loclists section.  */
     224        5553 :   if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL)
     225             :     {
     226        5270 :       result->fake_loc_cu = (Dwarf_CU *) calloc (1, sizeof (Dwarf_CU));
     227        5270 :       if (unlikely (result->fake_loc_cu == NULL))
     228             :         {
     229           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     230           0 :           __libdw_seterrno (DWARF_E_NOMEM);
     231           0 :           free (result);
     232           0 :           result = NULL;
     233             :         }
     234             :       else
     235             :         {
     236        5270 :           result->fake_loc_cu->sec_idx = IDX_debug_loc;
     237        5270 :           result->fake_loc_cu->dbg = result;
     238             :           result->fake_loc_cu->startp
     239        5270 :             = result->sectiondata[IDX_debug_loc]->d_buf;
     240             :           result->fake_loc_cu->endp
     241        5270 :             = (result->sectiondata[IDX_debug_loc]->d_buf
     242        5270 :                + result->sectiondata[IDX_debug_loc]->d_size);
     243             :         }
     244             :     }
     245             : 
     246        5652 :   if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL)
     247             :     {
     248          45 :       result->fake_loclists_cu = (Dwarf_CU *) calloc (1, sizeof (Dwarf_CU));
     249          45 :       if (unlikely (result->fake_loclists_cu == NULL))
     250             :         {
     251           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     252           0 :           __libdw_seterrno (DWARF_E_NOMEM);
     253           0 :           free (result->fake_loc_cu);
     254           0 :           free (result);
     255           0 :           result = NULL;
     256             :         }
     257             :       else
     258             :         {
     259          45 :           result->fake_loclists_cu->sec_idx = IDX_debug_loclists;
     260          45 :           result->fake_loclists_cu->dbg = result;
     261             :           result->fake_loclists_cu->startp
     262          45 :             = result->sectiondata[IDX_debug_loclists]->d_buf;
     263             :           result->fake_loclists_cu->endp
     264          45 :             = (result->sectiondata[IDX_debug_loclists]->d_buf
     265          45 :                + result->sectiondata[IDX_debug_loclists]->d_size);
     266             :         }
     267             :     }
     268             : 
     269             :   /* For DW_OP_constx/GNU_const_index and DW_OP_addrx/GNU_addr_index
     270             :      the dwarf_location_attr () will need a "fake" address CU to
     271             :      indicate where the attribute data comes from.  This is a just
     272             :      inside the .debug_addr section, if it exists.  */
     273        5652 :   if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL)
     274             :     {
     275          39 :       result->fake_addr_cu = (Dwarf_CU *) calloc (1, sizeof (Dwarf_CU));
     276          39 :       if (unlikely (result->fake_addr_cu == NULL))
     277             :         {
     278           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     279           0 :           __libdw_seterrno (DWARF_E_NOMEM);
     280           0 :           free (result->fake_loc_cu);
     281           0 :           free (result->fake_loclists_cu);
     282           0 :           free (result);
     283           0 :           result = NULL;
     284             :         }
     285             :       else
     286             :         {
     287          39 :           result->fake_addr_cu->sec_idx = IDX_debug_addr;
     288          39 :           result->fake_addr_cu->dbg = result;
     289             :           result->fake_addr_cu->startp
     290          39 :             = result->sectiondata[IDX_debug_addr]->d_buf;
     291             :           result->fake_addr_cu->endp
     292          39 :             = (result->sectiondata[IDX_debug_addr]->d_buf
     293          39 :                + result->sectiondata[IDX_debug_addr]->d_size);
     294             :         }
     295             :     }
     296             : 
     297        5652 :   if (result != NULL)
     298        5552 :     result->debugdir = __libdw_debugdir (result->elf->fildes);
     299             : 
     300        5652 :   return result;
     301             : }
     302             : 
     303             : 
     304             : static Dwarf *
     305        5652 : global_read (Dwarf *result, Elf *elf, size_t shstrndx)
     306             : {
     307        5652 :   Elf_Scn *scn = NULL;
     308             : 
     309      286193 :   while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
     310      274889 :     result = check_section (result, shstrndx, scn, false);
     311             : 
     312        5652 :   return valid_p (result);
     313             : }
     314             : 
     315             : 
     316             : static Dwarf *
     317           0 : scngrp_read (Dwarf *result, Elf *elf, size_t shstrndx, Elf_Scn *scngrp)
     318             : {
     319             :   GElf_Shdr shdr_mem;
     320           0 :   GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem);
     321           0 :   if (shdr == NULL)
     322             :     {
     323           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     324           0 :       __libdw_seterrno (DWARF_E_INVALID_ELF);
     325           0 :       free (result);
     326           0 :       return NULL;
     327             :     }
     328             : 
     329           0 :   if ((shdr->sh_flags & SHF_COMPRESSED) != 0
     330           0 :       && elf_compress (scngrp, 0, 0) < 0)
     331             :     {
     332           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     333           0 :       __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
     334           0 :       free (result);
     335           0 :       return NULL;
     336             :     }
     337             : 
     338             :   /* SCNGRP is the section descriptor for a section group which might
     339             :      contain debug sections.  */
     340           0 :   Elf_Data *data = elf_getdata (scngrp, NULL);
     341           0 :   if (data == NULL)
     342             :     {
     343             :       /* We cannot read the section content.  Fail!  */
     344           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     345           0 :       free (result);
     346           0 :       return NULL;
     347             :     }
     348             : 
     349             :   /* The content of the section is a number of 32-bit words which
     350             :      represent section indices.  The first word is a flag word.  */
     351           0 :   Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
     352             :   size_t cnt;
     353           0 :   for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
     354             :     {
     355           0 :       Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
     356           0 :       if (scn == NULL)
     357             :         {
     358             :           /* A section group refers to a non-existing section.  Should
     359             :              never happen.  */
     360           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     361           0 :           __libdw_seterrno (DWARF_E_INVALID_ELF);
     362           0 :           free (result);
     363           0 :           return NULL;
     364             :         }
     365             : 
     366           0 :       result = check_section (result, shstrndx, scn, true);
     367           0 :       if (result == NULL)
     368             :         break;
     369             :     }
     370             : 
     371           0 :   return valid_p (result);
     372             : }
     373             : 
     374             : 
     375             : Dwarf *
     376        5652 : dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
     377             : {
     378             :   GElf_Ehdr *ehdr;
     379             :   GElf_Ehdr ehdr_mem;
     380             : 
     381             :   /* Get the ELF header of the file.  We need various pieces of
     382             :      information from it.  */
     383        5652 :   ehdr = gelf_getehdr (elf, &ehdr_mem);
     384        5652 :   if (ehdr == NULL)
     385             :     {
     386           0 :       if (elf_kind (elf) != ELF_K_ELF)
     387           0 :         __libdw_seterrno (DWARF_E_NOELF);
     388             :       else
     389           0 :         __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
     390             : 
     391             :       return NULL;
     392             :     }
     393             : 
     394             : 
     395             :   /* Default memory allocation size.  */
     396        5652 :   size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
     397        5652 :   assert (sizeof (struct Dwarf) < mem_default_size);
     398             : 
     399             :   /* Allocate the data structure.  */
     400        5652 :   Dwarf *result = (Dwarf *) calloc (1, sizeof (Dwarf) + mem_default_size);
     401        5652 :   if (unlikely (result == NULL)
     402        5652 :       || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0))
     403             :     {
     404           0 :       free (result);
     405           0 :       __libdw_seterrno (DWARF_E_NOMEM);
     406           0 :       return NULL;
     407             :     }
     408             : 
     409             :   /* Fill in some values.  */
     410        5652 :   if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
     411             :       || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
     412          78 :     result->other_byte_order = true;
     413             : 
     414        5652 :   result->elf = elf;
     415        5652 :   result->alt_fd = -1;
     416             : 
     417             :   /* Initialize the memory handling.  */
     418        5652 :   result->mem_default_size = mem_default_size;
     419        5652 :   result->oom_handler = __libdw_oom;
     420        5652 :   result->mem_tail = (struct libdw_memblock *) (result + 1);
     421        5652 :   result->mem_tail->size = (result->mem_default_size
     422        5652 :                             - offsetof (struct libdw_memblock, mem));
     423        5652 :   result->mem_tail->remaining = result->mem_tail->size;
     424        5652 :   result->mem_tail->prev = NULL;
     425             : 
     426        5652 :   if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
     427             :     {
     428             :       /* All sections are recognized by name, so pass the section header
     429             :          string index along to easily get the section names.  */
     430             :       size_t shstrndx;
     431        5652 :       if (elf_getshdrstrndx (elf, &shstrndx) != 0)
     432             :         {
     433           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     434           0 :           __libdw_seterrno (DWARF_E_INVALID_ELF);
     435           0 :           free (result);
     436           0 :           return NULL;
     437             :         }
     438             : 
     439             :       /* If the caller provides a section group we get the DWARF
     440             :          sections only from this setion group.  Otherwise we search
     441             :          for the first section with the required name.  Further
     442             :          sections with the name are ignored.  The DWARF specification
     443             :          does not really say this is allowed.  */
     444        5652 :       if (scngrp == NULL)
     445        5652 :         return global_read (result, elf, shstrndx);
     446             :       else
     447           0 :         return scngrp_read (result, elf, shstrndx, scngrp);
     448             :     }
     449           0 :   else if (cmd == DWARF_C_WRITE)
     450             :     {
     451           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     452           0 :       __libdw_seterrno (DWARF_E_UNIMPL);
     453           0 :       free (result);
     454           0 :       return NULL;
     455             :     }
     456             : 
     457           0 :   Dwarf_Sig8_Hash_free (&result->sig8_hash);
     458           0 :   __libdw_seterrno (DWARF_E_INVALID_CMD);
     459           0 :   free (result);
     460           0 :   return NULL;
     461             : }
     462             : INTDEF(dwarf_begin_elf)

Generated by: LCOV version 1.13