LCOV - code coverage report
Current view: top level - libdw - dwarf_begin_elf.c (source / functions) Hit Total Coverage
Test: elfutils-0.181 Lines: 128 202 63.4 %
Date: 2020-09-08 14:07:57 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      281178 : check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
      75             : {
      76      281178 :   GElf_Shdr shdr_mem;
      77      281178 :   GElf_Shdr *shdr;
      78             : 
      79             :   /* Get the section header data.  */
      80      281178 :   shdr = gelf_getshdr (scn, &shdr_mem);
      81      281178 :   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      281178 :   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      268095 :   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      804282 :   const char *scnname = elf_strptr (result->elf, shstrndx,
     105      268094 :                                     shdr->sh_name);
     106      268094 :   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     4638670 :   for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
     121             :     {
     122     4409278 :       size_t dbglen = strlen (dwarf_scnnames[cnt]);
     123     4409278 :       size_t scnlen = strlen (scnname);
     124     4409278 :       if (strncmp (scnname, dwarf_scnnames[cnt], dbglen) == 0
     125       38743 :           && (dbglen == scnlen
     126         542 :               || (scnlen == dbglen + 4
     127         427 :                   && strstr (scnname, ".dwo") == scnname + dbglen)))
     128             :         break;
     129     4370659 :       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     4370577 :       else if (scnlen > 14 /* .gnu.debuglto_ prefix. */
     141      122448 :                && strncmp (scnname, ".gnu.debuglto_", 14) == 0
     142           0 :                && strcmp (&scnname[14], dwarf_scnnames[cnt]) == 0)
     143             :         break;
     144             :     }
     145             : 
     146      268093 :   if (cnt >= ndwarf_scnnames)
     147             :     /* Not a debug section; ignore it. */
     148             :     return result;
     149             : 
     150       38701 :   if (unlikely (result->sectiondata[cnt] != NULL))
     151             :     /* A section appears twice.  That's bad.  We ignore the section.  */
     152             :     return result;
     153             : 
     154             :   /* We cannot know whether or not a GNU compressed section has already
     155             :      been uncompressed or not, so ignore any errors.  */
     156       38701 :   if (gnu_compressed)
     157          82 :     elf_compress_gnu (scn, 0, 0);
     158             : 
     159       38701 :   if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
     160             :     {
     161         298 :       if (elf_compress (scn, 0, 0) < 0)
     162             :         {
     163             :           /* It would be nice if we could fail with a specific error.
     164             :              But we don't know if this was an essential section or not.
     165             :              So just continue for now. See also valid_p().  */
     166             :           return result;
     167             :         }
     168             :     }
     169             : 
     170             :   /* Get the section data.  */
     171       38701 :   Elf_Data *data = elf_getdata (scn, NULL);
     172       38701 :   if (data == NULL)
     173             :     goto err;
     174             : 
     175       38701 :   if (data->d_buf == NULL || data->d_size == 0)
     176             :     /* No data actually available, ignore it. */
     177             :     return result;
     178             : 
     179             :   /* We can now read the section data into results. */
     180       38695 :   result->sectiondata[cnt] = data;
     181             : 
     182       38695 :   return result;
     183             : }
     184             : 
     185             : 
     186             : /* Helper function to set debugdir field.  We want to cache the dir
     187             :    where we found this Dwarf ELF file to locate alt and dwo files.  */
     188             : char *
     189        6108 : __libdw_debugdir (int fd)
     190             : {
     191             :   /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25.  */
     192        6108 :   char devfdpath[25];
     193        6108 :   sprintf (devfdpath, "/proc/self/fd/%u", fd);
     194        6108 :   char *fdpath = realpath (devfdpath, NULL);
     195        6108 :   char *fddir;
     196        6108 :   if (fdpath != NULL && fdpath[0] == '/'
     197        5823 :       && (fddir = strrchr (fdpath, '/')) != NULL)
     198             :     {
     199        5823 :       *++fddir = '\0';
     200        5823 :       return fdpath;
     201             :     }
     202             :   return NULL;
     203             : }
     204             : 
     205             : 
     206             : /* Check whether all the necessary DWARF information is available.  */
     207             : static Dwarf *
     208        5703 : valid_p (Dwarf *result)
     209             : {
     210             :   /* We looked at all the sections.  Now determine whether all the
     211             :      sections with debugging information we need are there.
     212             : 
     213             :      Require at least one section that can be read "standalone".  */
     214        5703 :   if (likely (result != NULL)
     215        5702 :       && unlikely (result->sectiondata[IDX_debug_info] == NULL
     216             :                    && result->sectiondata[IDX_debug_line] == NULL
     217             :                    && result->sectiondata[IDX_debug_frame] == NULL))
     218             :     {
     219         121 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     220         121 :       __libdw_seterrno (DWARF_E_NO_DWARF);
     221         121 :       free (result);
     222         121 :       result = NULL;
     223             :     }
     224             : 
     225             :   /* For dwarf_location_attr () we need a "fake" CU to indicate
     226             :      where the "fake" attribute data comes from.  This is a block
     227             :      inside the .debug_loc or .debug_loclists section.  */
     228        5703 :   if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL)
     229             :     {
     230        5256 :       result->fake_loc_cu = (Dwarf_CU *) malloc (sizeof (Dwarf_CU));
     231        5256 :       if (unlikely (result->fake_loc_cu == NULL))
     232             :         {
     233           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     234           0 :           __libdw_seterrno (DWARF_E_NOMEM);
     235           0 :           free (result);
     236           0 :           result = NULL;
     237             :         }
     238             :       else
     239             :         {
     240        5256 :           result->fake_loc_cu->sec_idx = IDX_debug_loc;
     241        5256 :           result->fake_loc_cu->dbg = result;
     242        5256 :           result->fake_loc_cu->startp
     243        5256 :             = result->sectiondata[IDX_debug_loc]->d_buf;
     244        5256 :           result->fake_loc_cu->endp
     245        5256 :             = (result->sectiondata[IDX_debug_loc]->d_buf
     246        5256 :                + result->sectiondata[IDX_debug_loc]->d_size);
     247        5256 :           result->fake_loc_cu->locs = NULL;
     248        5256 :           result->fake_loc_cu->address_size = 0;
     249        5256 :           result->fake_loc_cu->version = 0;
     250        5256 :           result->fake_loc_cu->split = NULL;
     251             :         }
     252             :     }
     253             : 
     254        5703 :   if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL)
     255             :     {
     256          45 :       result->fake_loclists_cu = (Dwarf_CU *) malloc (sizeof (Dwarf_CU));
     257          45 :       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          45 :           result->fake_loclists_cu->sec_idx = IDX_debug_loclists;
     268          45 :           result->fake_loclists_cu->dbg = result;
     269          45 :           result->fake_loclists_cu->startp
     270          45 :             = result->sectiondata[IDX_debug_loclists]->d_buf;
     271          45 :           result->fake_loclists_cu->endp
     272          45 :             = (result->sectiondata[IDX_debug_loclists]->d_buf
     273          45 :                + result->sectiondata[IDX_debug_loclists]->d_size);
     274          45 :           result->fake_loclists_cu->locs = NULL;
     275          45 :           result->fake_loclists_cu->address_size = 0;
     276          45 :           result->fake_loclists_cu->version = 0;
     277          45 :           result->fake_loclists_cu->split = NULL;
     278             :         }
     279             :     }
     280             : 
     281             :   /* For DW_OP_constx/GNU_const_index and DW_OP_addrx/GNU_addr_index
     282             :      the dwarf_location_attr () will need a "fake" address CU to
     283             :      indicate where the attribute data comes from.  This is a just
     284             :      inside the .debug_addr section, if it exists.  */
     285        5703 :   if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL)
     286             :     {
     287          39 :       result->fake_addr_cu = (Dwarf_CU *) malloc (sizeof (Dwarf_CU));
     288          39 :       if (unlikely (result->fake_addr_cu == NULL))
     289             :         {
     290           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     291           0 :           __libdw_seterrno (DWARF_E_NOMEM);
     292           0 :           free (result->fake_loc_cu);
     293           0 :           free (result->fake_loclists_cu);
     294           0 :           free (result);
     295           0 :           result = NULL;
     296             :         }
     297             :       else
     298             :         {
     299          39 :           result->fake_addr_cu->sec_idx = IDX_debug_addr;
     300          39 :           result->fake_addr_cu->dbg = result;
     301          39 :           result->fake_addr_cu->startp
     302          39 :             = result->sectiondata[IDX_debug_addr]->d_buf;
     303          39 :           result->fake_addr_cu->endp
     304          39 :             = (result->sectiondata[IDX_debug_addr]->d_buf
     305          39 :                + result->sectiondata[IDX_debug_addr]->d_size);
     306          39 :           result->fake_addr_cu->locs = NULL;
     307          39 :           result->fake_addr_cu->address_size = 0;
     308          39 :           result->fake_addr_cu->version = 0;
     309          39 :           result->fake_addr_cu->split = NULL;
     310             :         }
     311             :     }
     312             : 
     313        5703 :   if (result != NULL)
     314        5581 :     result->debugdir = __libdw_debugdir (result->elf->fildes);
     315             : 
     316        5703 :   return result;
     317             : }
     318             : 
     319             : 
     320             : static Dwarf *
     321        5703 : global_read (Dwarf *result, Elf *elf, size_t shstrndx)
     322             : {
     323        5703 :   Elf_Scn *scn = NULL;
     324             : 
     325      286881 :   while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
     326      281178 :     result = check_section (result, shstrndx, scn, false);
     327             : 
     328        5703 :   return valid_p (result);
     329             : }
     330             : 
     331             : 
     332             : static Dwarf *
     333           0 : scngrp_read (Dwarf *result, Elf *elf, size_t shstrndx, Elf_Scn *scngrp)
     334             : {
     335           0 :   GElf_Shdr shdr_mem;
     336           0 :   GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem);
     337           0 :   if (shdr == NULL)
     338             :     {
     339           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     340           0 :       __libdw_seterrno (DWARF_E_INVALID_ELF);
     341           0 :       free (result);
     342           0 :       return NULL;
     343             :     }
     344             : 
     345           0 :   if ((shdr->sh_flags & SHF_COMPRESSED) != 0
     346           0 :       && elf_compress (scngrp, 0, 0) < 0)
     347             :     {
     348           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     349           0 :       __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
     350           0 :       free (result);
     351           0 :       return NULL;
     352             :     }
     353             : 
     354             :   /* SCNGRP is the section descriptor for a section group which might
     355             :      contain debug sections.  */
     356           0 :   Elf_Data *data = elf_getdata (scngrp, NULL);
     357           0 :   if (data == NULL)
     358             :     {
     359             :       /* We cannot read the section content.  Fail!  */
     360           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     361           0 :       free (result);
     362           0 :       return NULL;
     363             :     }
     364             : 
     365             :   /* The content of the section is a number of 32-bit words which
     366             :      represent section indices.  The first word is a flag word.  */
     367           0 :   Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
     368           0 :   size_t cnt;
     369           0 :   for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
     370             :     {
     371           0 :       Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
     372           0 :       if (scn == NULL)
     373             :         {
     374             :           /* A section group refers to a non-existing section.  Should
     375             :              never happen.  */
     376           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     377           0 :           __libdw_seterrno (DWARF_E_INVALID_ELF);
     378           0 :           free (result);
     379           0 :           return NULL;
     380             :         }
     381             : 
     382           0 :       result = check_section (result, shstrndx, scn, true);
     383           0 :       if (result == NULL)
     384             :         break;
     385             :     }
     386             : 
     387           0 :   return valid_p (result);
     388             : }
     389             : 
     390             : 
     391             : Dwarf *
     392        5703 : dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
     393             : {
     394        5703 :   GElf_Ehdr *ehdr;
     395        5703 :   GElf_Ehdr ehdr_mem;
     396             : 
     397             :   /* Get the ELF header of the file.  We need various pieces of
     398             :      information from it.  */
     399        5703 :   ehdr = gelf_getehdr (elf, &ehdr_mem);
     400        5703 :   if (ehdr == NULL)
     401             :     {
     402           0 :       if (elf_kind (elf) != ELF_K_ELF)
     403           0 :         __libdw_seterrno (DWARF_E_NOELF);
     404             :       else
     405           0 :         __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
     406             : 
     407           0 :       return NULL;
     408             :     }
     409             : 
     410             : 
     411             :   /* Default memory allocation size.  */
     412        5703 :   size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
     413        5703 :   assert (sizeof (struct Dwarf) < mem_default_size);
     414             : 
     415             :   /* Allocate the data structure.  */
     416        5703 :   Dwarf *result = (Dwarf *) calloc (1, sizeof (Dwarf));
     417        5703 :   if (unlikely (result == NULL)
     418        5703 :       || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0))
     419             :     {
     420           0 :       free (result);
     421           0 :       __libdw_seterrno (DWARF_E_NOMEM);
     422           0 :       return NULL;
     423             :     }
     424             : 
     425             :   /* Fill in some values.  */
     426        5703 :   if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
     427             :       || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
     428          78 :     result->other_byte_order = true;
     429             : 
     430        5703 :   result->elf = elf;
     431        5703 :   result->alt_fd = -1;
     432             : 
     433             :   /* Initialize the memory handling.  Initial blocks are allocated on first
     434             :      actual allocation.  */
     435        5703 :   result->mem_default_size = mem_default_size;
     436        5703 :   result->oom_handler = __libdw_oom;
     437        5703 :   if (pthread_rwlock_init(&result->mem_rwl, NULL) != 0)
     438             :     {
     439           0 :       free (result);
     440           0 :       __libdw_seterrno (DWARF_E_NOMEM); /* no memory.  */
     441           0 :       return NULL;
     442             :     }
     443        5703 :   result->mem_stacks = 0;
     444        5703 :   result->mem_tails = NULL;
     445             : 
     446        5703 :   if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
     447             :     {
     448             :       /* All sections are recognized by name, so pass the section header
     449             :          string index along to easily get the section names.  */
     450        5703 :       size_t shstrndx;
     451        5703 :       if (elf_getshdrstrndx (elf, &shstrndx) != 0)
     452             :         {
     453           0 :           Dwarf_Sig8_Hash_free (&result->sig8_hash);
     454           0 :           __libdw_seterrno (DWARF_E_INVALID_ELF);
     455           0 :           free (result);
     456           0 :           return NULL;
     457             :         }
     458             : 
     459             :       /* If the caller provides a section group we get the DWARF
     460             :          sections only from this setion group.  Otherwise we search
     461             :          for the first section with the required name.  Further
     462             :          sections with the name are ignored.  The DWARF specification
     463             :          does not really say this is allowed.  */
     464        5703 :       if (scngrp == NULL)
     465        5703 :         return global_read (result, elf, shstrndx);
     466             :       else
     467           0 :         return scngrp_read (result, elf, shstrndx, scngrp);
     468             :     }
     469           0 :   else if (cmd == DWARF_C_WRITE)
     470             :     {
     471           0 :       Dwarf_Sig8_Hash_free (&result->sig8_hash);
     472           0 :       __libdw_seterrno (DWARF_E_UNIMPL);
     473           0 :       free (result);
     474           0 :       return NULL;
     475             :     }
     476             : 
     477           0 :   Dwarf_Sig8_Hash_free (&result->sig8_hash);
     478           0 :   __libdw_seterrno (DWARF_E_INVALID_CMD);
     479           0 :   free (result);
     480           0 :   return NULL;
     481             : }
     482             : INTDEF(dwarf_begin_elf)

Generated by: LCOV version 1.13