LCOV - code coverage report
Current view: top level - libdw - dwarf_getabbrev.c (source / functions) Hit Total Coverage
Test: elfutils-0.178 Lines: 54 63 85.7 %
Date: 2019-11-26 23:55:16 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Get abbreviation at given offset.
       2             :    Copyright (C) 2003, 2004, 2005, 2006, 2014, 2017 Red Hat, Inc.
       3             :    This file is part of elfutils.
       4             :    Written by Ulrich Drepper <drepper@redhat.com>, 2003.
       5             : 
       6             :    This file is free software; you can redistribute it and/or modify
       7             :    it under the terms of either
       8             : 
       9             :      * the GNU Lesser General Public License as published by the Free
      10             :        Software Foundation; either version 3 of the License, or (at
      11             :        your option) any later version
      12             : 
      13             :    or
      14             : 
      15             :      * the GNU General Public License as published by the Free
      16             :        Software Foundation; either version 2 of the License, or (at
      17             :        your option) any later version
      18             : 
      19             :    or both in parallel, as here.
      20             : 
      21             :    elfutils is distributed in the hope that it will be useful, but
      22             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      23             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      24             :    General Public License for more details.
      25             : 
      26             :    You should have received copies of the GNU General Public License and
      27             :    the GNU Lesser General Public License along with this program.  If
      28             :    not, see <http://www.gnu.org/licenses/>.  */
      29             : 
      30             : #ifdef HAVE_CONFIG_H
      31             : # include <config.h>
      32             : #endif
      33             : 
      34             : #include <dwarf.h>
      35             : #include "libdwP.h"
      36             : 
      37             : 
      38             : Dwarf_Abbrev *
      39             : internal_function
      40      830195 : __libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu, Dwarf_Off offset,
      41             :                    size_t *lengthp, Dwarf_Abbrev *result)
      42             : {
      43             :   /* Don't fail if there is not .debug_abbrev section.  */
      44      830195 :   if (dbg->sectiondata[IDX_debug_abbrev] == NULL)
      45             :     return NULL;
      46             : 
      47      830195 :   if (offset >= dbg->sectiondata[IDX_debug_abbrev]->d_size)
      48             :     {
      49           0 :       __libdw_seterrno (DWARF_E_INVALID_OFFSET);
      50           0 :       return NULL;
      51             :     }
      52             : 
      53     1660390 :   const unsigned char *abbrevp
      54      830195 :     = (unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf + offset;
      55             : 
      56      830195 :   if (*abbrevp == '\0')
      57             :     /* We are past the last entry.  */
      58             :     return DWARF_END_ABBREV;
      59             : 
      60             :   /* 7.5.3 Abbreviations Tables
      61             : 
      62             :      [...] Each declaration begins with an unsigned LEB128 number
      63             :      representing the abbreviation code itself.  [...]  The
      64             :      abbreviation code is followed by another unsigned LEB128
      65             :      number that encodes the entry's tag.  [...]
      66             : 
      67             :      [...] Following the tag encoding is a 1-byte value that
      68             :      determines whether a debugging information entry using this
      69             :      abbreviation has child entries or not. [...]
      70             : 
      71             :      [...] Finally, the child encoding is followed by a series of
      72             :      attribute specifications. Each attribute specification
      73             :      consists of two parts. The first part is an unsigned LEB128
      74             :      number representing the attribute's name. The second part is
      75             :      an unsigned LEB128 number representing the attribute's form.  */
      76      828520 :   const unsigned char *end = (dbg->sectiondata[IDX_debug_abbrev]->d_buf
      77             :                               + dbg->sectiondata[IDX_debug_abbrev]->d_size);
      78      828520 :   const unsigned char *start_abbrevp = abbrevp;
      79      828520 :   unsigned int code;
      80      828520 :   get_uleb128 (code, abbrevp, end);
      81             : 
      82             :   /* Check whether this code is already in the hash table.  */
      83      828520 :   bool foundit = false;
      84      828520 :   Dwarf_Abbrev *abb = NULL;
      85      828520 :   if (cu == NULL
      86      746973 :       || (abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code)) == NULL)
      87             :     {
      88      828514 :       if (result == NULL)
      89      746967 :         abb = libdw_typed_alloc (dbg, Dwarf_Abbrev);
      90             :       else
      91             :         abb = result;
      92             :     }
      93             :   else
      94             :     {
      95           6 :       foundit = true;
      96             : 
      97           6 :       if (unlikely (abb->offset != offset))
      98             :         {
      99             :           /* A duplicate abbrev code at a different offset,
     100             :              that should never happen.  */
     101           0 :         invalid:
     102           0 :           if (! foundit)
     103           0 :             libdw_typed_unalloc (dbg, Dwarf_Abbrev);
     104           0 :           __libdw_seterrno (DWARF_E_INVALID_DWARF);
     105           0 :           return NULL;
     106             :         }
     107             : 
     108             :       /* If the caller doesn't need the length we are done.  */
     109           6 :       if (lengthp == NULL)
     110             :         goto out;
     111             :     }
     112             : 
     113             :   /* If there is already a value in the hash table we are going to
     114             :      overwrite its content.  This must not be a problem, since the
     115             :      content better be the same.  */
     116      828520 :   abb->code = code;
     117      828520 :   if (abbrevp >= end)
     118             :     goto invalid;
     119      828520 :   get_uleb128 (abb->tag, abbrevp, end);
     120      828520 :   if (abbrevp + 1 >= end)
     121             :     goto invalid;
     122      828520 :   abb->has_children = *abbrevp++ == DW_CHILDREN_yes;
     123      828520 :   abb->attrp = (unsigned char *) abbrevp;
     124      828520 :   abb->offset = offset;
     125             : 
     126             :   /* Skip over all the attributes and check rest of the abbrev is valid.  */
     127     4623786 :   unsigned int attrname;
     128     4623786 :   unsigned int attrform;
     129     4623786 :   do
     130             :     {
     131     4623786 :       if (abbrevp >= end)
     132             :         goto invalid;
     133     4623786 :       get_uleb128 (attrname, abbrevp, end);
     134     4623786 :       if (abbrevp >= end)
     135             :         goto invalid;
     136     4623786 :       get_uleb128 (attrform, abbrevp, end);
     137     4623786 :       if (attrform == DW_FORM_implicit_const)
     138             :         {
     139         221 :           int64_t formval __attribute__((__unused__));
     140         221 :           if (abbrevp >= end)
     141             :             goto invalid;
     142         221 :           get_sleb128 (formval, abbrevp, end);
     143             :         }
     144             :     }
     145     4623786 :   while (attrname != 0 || attrform != 0);
     146             : 
     147             :   /* Return the length to the caller if she asked for it.  */
     148      828520 :   if (lengthp != NULL)
     149      828520 :     *lengthp = abbrevp - start_abbrevp;
     150             : 
     151             :   /* Add the entry to the hash table.  */
     152      828520 :   if (cu != NULL && ! foundit)
     153      746967 :     if (Dwarf_Abbrev_Hash_insert (&cu->abbrev_hash, abb->code, abb) == -1)
     154             :       {
     155             :         /* The entry was already in the table, remove the one we just
     156             :            created and get the one already inserted.  */
     157           0 :         libdw_typed_unalloc (dbg, Dwarf_Abbrev);
     158           0 :         abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code);
     159             :       }
     160             : 
     161      828520 :  out:
     162             :   return abb;
     163             : }
     164             : 
     165             : 
     166             : Dwarf_Abbrev *
     167        1207 : dwarf_getabbrev (Dwarf_Die *die, Dwarf_Off offset, size_t *lengthp)
     168             : {
     169        1207 :   if (die == NULL || die->cu == NULL)
     170             :     return NULL;
     171             : 
     172          75 :   Dwarf_CU *cu = die->cu;
     173          75 :   Dwarf *dbg = cu->dbg;
     174          75 :   Dwarf_Off abbrev_offset = cu->orig_abbrev_offset;
     175          75 :   Elf_Data *data = dbg->sectiondata[IDX_debug_abbrev];
     176          75 :   if (data == NULL)
     177             :     return NULL;
     178             : 
     179          75 :   if (offset >= data->d_size - abbrev_offset)
     180             :     {
     181           6 :       __libdw_seterrno (DWARF_E_INVALID_OFFSET);
     182           6 :       return NULL;
     183             :     }
     184             : 
     185          69 :   return __libdw_getabbrev (dbg, cu, abbrev_offset + offset, lengthp, NULL);
     186             : }

Generated by: LCOV version 1.13