LCOV - code coverage report
Current view: top level - libdw - dwarf_begin_elf.c (source / functions) Hit Total Coverage
Test: elfutils-0.172 Lines: 102 170 60.0 %
Date: 2018-06-11 22:52:14 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      208389 : check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
      75             : {
      76             :   GElf_Shdr shdr_mem;
      77             :   GElf_Shdr *shdr;
      78             : 
      79             :   /* Get the section header data.  */
      80      208389 :   shdr = gelf_getshdr (scn, &shdr_mem);
      81      208389 :   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      208389 :   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      196245 :   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      196245 :   const char *scnname = elf_strptr (result->elf, ehdr->e_shstrndx,
     105      196245 :                                     shdr->sh_name);
     106      196245 :   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     3081541 :   for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
     121             :     {
     122     3119912 :       size_t dbglen = strlen (dwarf_scnnames[cnt]);
     123     3119912 :       size_t scnlen = strlen (scnname);
     124     3119912 :       if (strncmp (scnname, dwarf_scnnames[cnt], dbglen) == 0
     125       38427 :           && (dbglen == scnlen
     126         512 :               || (scnlen == dbglen + 4
     127         403 :                   && strstr (scnname, ".dwo") == scnname + dbglen)))
     128             :         break;
     129     3081603 :       else if (scnname[0] == '.' && scnname[1] == 'z'
     130         478 :                && (strncmp (&scnname[2], &dwarf_scnnames[cnt][1],
     131             :                             dbglen - 1) == 0
     132          62 :                    && (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      196244 :   if (cnt >= ndwarf_scnnames)
     143             :     /* Not a debug section; ignore it. */
     144             :     return result;
     145             : 
     146       38371 :   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       38371 :   if (gnu_compressed)
     153          62 :     elf_compress_gnu (scn, 0, 0);
     154             : 
     155       38371 :   if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
     156             :     {
     157         270 :       if (elf_compress (scn, 0, 0) < 0)
     158             :         {
     159             :           /* If we failed to decompress the section and it's the
     160             :              debug_info section, then fail with specific error rather
     161             :              than the generic NO_DWARF. Without debug_info we can't do
     162             :              anything (see also valid_p()). */
     163           0 :           if (cnt == IDX_debug_info)
     164             :             {
     165           0 :               Dwarf_Sig8_Hash_free (&result->sig8_hash);
     166           0 :               __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
     167           0 :               free (result);
     168           0 :               return NULL;
     169             :             }
     170             :           return result;
     171             :         }
     172             :     }
     173             : 
     174             :   /* Get the section data.  */
     175       38371 :   Elf_Data *data = elf_getdata (scn, NULL);
     176       38371 :   if (data == NULL)
     177             :     goto err;
     178             : 
     179       38371 :   if (data->d_buf == NULL || data->d_size == 0)
     180             :     /* No data actually available, ignore it. */
     181             :     return result;
     182             : 
     183             :   /* We can now read the section data into results. */
     184       38365 :   result->sectiondata[cnt] = data;
     185             : 
     186       38365 :   return result;
     187             : }
     188             : 
     189             : 
     190             : /* Helper function to set debugdir field.  We want to cache the dir
     191             :    where we found this Dwarf ELF file to locate alt and dwo files.  */
     192             : char *
     193        5921 : __libdw_debugdir (int fd)
     194             : {
     195             :   /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25.  */
     196             :   char devfdpath[25];
     197        5921 :   sprintf (devfdpath, "/proc/self/fd/%u", fd);
     198        5921 :   char *fdpath = realpath (devfdpath, NULL);
     199             :   char *fddir;
     200        5921 :   if (fdpath != NULL && fdpath[0] == '/'
     201        5678 :       && (fddir = strrchr (fdpath, '/')) != NULL)
     202             :     {
     203        5678 :       *++fddir = '\0';
     204        5678 :       return fdpath;
     205             :     }
     206             :   return NULL;
     207             : }
     208             : 
     209             : 
     210             : /* Check whether all the necessary DWARF information is available.  */
     211             : static Dwarf *
     212        5611 : valid_p (Dwarf *result)
     213             : {
     214             :   /* We looked at all the sections.  Now determine whether all the
     215             :      sections with debugging information we need are there.
     216             : 
     217             :      XXX Which sections are absolutely necessary?  Add tests if
     218             :      necessary.  For now we require only .debug_info.  Hopefully this
     219             :      is correct.  */
     220        5611 :   if (likely (result != NULL)
     221        5610 :       && unlikely (result->sectiondata[IDX_debug_info] == NULL))
     222             :     {
     223          93 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     224          93 :       __libdw_seterrno (DWARF_E_NO_DWARF);
     225          93 :       free (result);
     226          93 :       result = NULL;
     227             :     }
     228             : 
     229             :   /* For dwarf_location_attr () we need a "fake" CU to indicate
     230             :      where the "fake" attribute data comes from.  This is a block
     231             :      inside the .debug_loc or .debug_loclists section.  */
     232        5518 :   if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL)
     233             :     {
     234        5256 :       result->fake_loc_cu = (Dwarf_CU *) calloc (1, sizeof (Dwarf_CU));
     235        5256 :       if (unlikely (result->fake_loc_cu == NULL))
     236             :         {
     237           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     238           0 :           __libdw_seterrno (DWARF_E_NOMEM);
     239           0 :           free (result);
     240           0 :           result = NULL;
     241             :         }
     242             :       else
     243             :         {
     244        5256 :           result->fake_loc_cu->sec_idx = IDX_debug_loc;
     245        5256 :           result->fake_loc_cu->dbg = result;
     246             :           result->fake_loc_cu->startp
     247        5256 :             = result->sectiondata[IDX_debug_loc]->d_buf;
     248             :           result->fake_loc_cu->endp
     249        5256 :             = (result->sectiondata[IDX_debug_loc]->d_buf
     250        5256 :                + result->sectiondata[IDX_debug_loc]->d_size);
     251             :         }
     252             :     }
     253             : 
     254        5611 :   if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL)
     255             :     {
     256          43 :       result->fake_loclists_cu = (Dwarf_CU *) calloc (1, sizeof (Dwarf_CU));
     257          43 :       if (unlikely (result->fake_loclists_cu == NULL))
     258             :         {
     259           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     260           0 :           __libdw_seterrno (DWARF_E_NOMEM);
     261           0 :           free (result->fake_loc_cu);
     262           0 :           free (result);
     263           0 :           result = NULL;
     264             :         }
     265             :       else
     266             :         {
     267          43 :           result->fake_loclists_cu->sec_idx = IDX_debug_loclists;
     268          43 :           result->fake_loclists_cu->dbg = result;
     269             :           result->fake_loclists_cu->startp
     270          43 :             = result->sectiondata[IDX_debug_loclists]->d_buf;
     271             :           result->fake_loclists_cu->endp
     272          43 :             = (result->sectiondata[IDX_debug_loclists]->d_buf
     273          43 :                + result->sectiondata[IDX_debug_loclists]->d_size);
     274             :         }
     275             :     }
     276             : 
     277             :   /* For DW_OP_constx/GNU_const_index and DW_OP_addrx/GNU_addr_index
     278             :      the dwarf_location_attr () will need a "fake" address CU to
     279             :      indicate where the attribute data comes from.  This is a just
     280             :      inside the .debug_addr section, if it exists.  */
     281        5611 :   if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL)
     282             :     {
     283          37 :       result->fake_addr_cu = (Dwarf_CU *) calloc (1, sizeof (Dwarf_CU));
     284          37 :       if (unlikely (result->fake_addr_cu == NULL))
     285             :         {
     286           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     287           0 :           __libdw_seterrno (DWARF_E_NOMEM);
     288           0 :           free (result->fake_loc_cu);
     289           0 :           free (result->fake_loclists_cu);
     290           0 :           free (result);
     291           0 :           result = NULL;
     292             :         }
     293             :       else
     294             :         {
     295          37 :           result->fake_addr_cu->sec_idx = IDX_debug_addr;
     296          37 :           result->fake_addr_cu->dbg = result;
     297             :           result->fake_addr_cu->startp
     298          37 :             = result->sectiondata[IDX_debug_addr]->d_buf;
     299             :           result->fake_addr_cu->endp
     300          37 :             = (result->sectiondata[IDX_debug_addr]->d_buf
     301          37 :                + result->sectiondata[IDX_debug_addr]->d_size);
     302             :         }
     303             :     }
     304             : 
     305        5611 :   if (result != NULL)
     306        5517 :     result->debugdir = __libdw_debugdir (result->elf->fildes);
     307             : 
     308        5611 :   return result;
     309             : }
     310             : 
     311             : 
     312             : static Dwarf *
     313        5611 : global_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr)
     314             : {
     315        5611 :   Elf_Scn *scn = NULL;
     316             : 
     317      219611 :   while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
     318      208389 :     result = check_section (result, ehdr, scn, false);
     319             : 
     320        5611 :   return valid_p (result);
     321             : }
     322             : 
     323             : 
     324             : static Dwarf *
     325           0 : scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Elf_Scn *scngrp)
     326             : {
     327             :   GElf_Shdr shdr_mem;
     328           0 :   GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem);
     329           0 :   if (shdr == NULL)
     330             :     {
     331           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     332           0 :       __libdw_seterrno (DWARF_E_INVALID_ELF);
     333           0 :       free (result);
     334           0 :       return NULL;
     335             :     }
     336             : 
     337           0 :   if ((shdr->sh_flags & SHF_COMPRESSED) != 0
     338           0 :       && elf_compress (scngrp, 0, 0) < 0)
     339             :     {
     340           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     341           0 :       __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
     342           0 :       free (result);
     343           0 :       return NULL;
     344             :     }
     345             : 
     346             :   /* SCNGRP is the section descriptor for a section group which might
     347             :      contain debug sections.  */
     348           0 :   Elf_Data *data = elf_getdata (scngrp, NULL);
     349           0 :   if (data == NULL)
     350             :     {
     351             :       /* We cannot read the section content.  Fail!  */
     352           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     353           0 :       free (result);
     354           0 :       return NULL;
     355             :     }
     356             : 
     357             :   /* The content of the section is a number of 32-bit words which
     358             :      represent section indices.  The first word is a flag word.  */
     359           0 :   Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
     360             :   size_t cnt;
     361           0 :   for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
     362             :     {
     363           0 :       Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
     364           0 :       if (scn == NULL)
     365             :         {
     366             :           /* A section group refers to a non-existing section.  Should
     367             :              never happen.  */
     368           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     369           0 :           __libdw_seterrno (DWARF_E_INVALID_ELF);
     370           0 :           free (result);
     371           0 :           return NULL;
     372             :         }
     373             : 
     374           0 :       result = check_section (result, ehdr, scn, true);
     375           0 :       if (result == NULL)
     376             :         break;
     377             :     }
     378             : 
     379           0 :   return valid_p (result);
     380             : }
     381             : 
     382             : 
     383             : Dwarf *
     384        5611 : dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
     385             : {
     386             :   GElf_Ehdr *ehdr;
     387             :   GElf_Ehdr ehdr_mem;
     388             : 
     389             :   /* Get the ELF header of the file.  We need various pieces of
     390             :      information from it.  */
     391        5611 :   ehdr = gelf_getehdr (elf, &ehdr_mem);
     392        5611 :   if (ehdr == NULL)
     393             :     {
     394           0 :       if (elf_kind (elf) != ELF_K_ELF)
     395           0 :         __libdw_seterrno (DWARF_E_NOELF);
     396             :       else
     397           0 :         __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
     398             : 
     399             :       return NULL;
     400             :     }
     401             : 
     402             : 
     403             :   /* Default memory allocation size.  */
     404        5611 :   size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
     405        5611 :   assert (sizeof (struct Dwarf) < mem_default_size);
     406             : 
     407             :   /* Allocate the data structure.  */
     408        5611 :   Dwarf *result = (Dwarf *) calloc (1, sizeof (Dwarf) + mem_default_size);
     409        5611 :   if (unlikely (result == NULL)
     410        5611 :       || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0))
     411             :     {
     412           0 :       free (result);
     413           0 :       __libdw_seterrno (DWARF_E_NOMEM);
     414           0 :       return NULL;
     415             :     }
     416             : 
     417             :   /* Fill in some values.  */
     418        5611 :   if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
     419             :       || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
     420          58 :     result->other_byte_order = true;
     421             : 
     422        5611 :   result->elf = elf;
     423        5611 :   result->alt_fd = -1;
     424             : 
     425             :   /* Initialize the memory handling.  */
     426        5611 :   result->mem_default_size = mem_default_size;
     427        5611 :   result->oom_handler = __libdw_oom;
     428        5611 :   result->mem_tail = (struct libdw_memblock *) (result + 1);
     429        5611 :   result->mem_tail->size = (result->mem_default_size
     430        5611 :                             - offsetof (struct libdw_memblock, mem));
     431        5611 :   result->mem_tail->remaining = result->mem_tail->size;
     432        5611 :   result->mem_tail->prev = NULL;
     433             : 
     434        5611 :   if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
     435             :     {
     436             :       /* If the caller provides a section group we get the DWARF
     437             :          sections only from this setion group.  Otherwise we search
     438             :          for the first section with the required name.  Further
     439             :          sections with the name are ignored.  The DWARF specification
     440             :          does not really say this is allowed.  */
     441        5611 :       if (scngrp == NULL)
     442        5611 :         return global_read (result, elf, ehdr);
     443             :       else
     444           0 :         return scngrp_read (result, elf, ehdr, scngrp);
     445             :     }
     446           0 :   else if (cmd == DWARF_C_WRITE)
     447             :     {
     448           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     449           0 :       __libdw_seterrno (DWARF_E_UNIMPL);
     450           0 :       free (result);
     451           0 :       return NULL;
     452             :     }
     453             : 
     454           0 :   Dwarf_Sig8_Hash_free (&result->sig8_hash);
     455           0 :   __libdw_seterrno (DWARF_E_INVALID_CMD);
     456           0 :   free (result);
     457           0 :   return NULL;
     458             : }
     459             : INTDEF(dwarf_begin_elf)

Generated by: LCOV version 1.13