LCOV - code coverage report
Current view: top level - libdw - dwarf_formudata.c (source / functions) Hit Total Coverage
Test: elfutils-0.172 Lines: 90 120 75.0 %
Date: 2018-06-11 22:52:14 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Return unsigned constant represented by attribute.
       2             :    Copyright (C) 2003-2012, 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             : internal_function const unsigned char *
      38      491739 : __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
      39             :                  int err_nodata, const unsigned char **endpp,
      40             :                  Dwarf_Off *offsetp)
      41             : {
      42      491739 :   if (attr == NULL)
      43             :     return NULL;
      44             : 
      45      491739 :   const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index];
      46      491739 :   Dwarf_CU *skel = NULL; /* See below, needed for GNU DebugFission.  */
      47      491739 :   if (unlikely (d == NULL
      48             :                 && sec_index == IDX_debug_ranges
      49             :                 && attr->cu->version < 5
      50             :                 && attr->cu->unit_type == DW_UT_split_compile))
      51             :     {
      52          10 :       skel = __libdw_find_split_unit (attr->cu);
      53          10 :       if (skel != NULL)
      54          10 :         d = skel->dbg->sectiondata[IDX_debug_ranges];
      55             :     }
      56             : 
      57      491739 :   if (unlikely (d == NULL))
      58             :     {
      59           9 :       __libdw_seterrno (err_nodata);
      60           9 :       return NULL;
      61             :     }
      62             : 
      63             :   Dwarf_Word offset;
      64      491730 :   if (attr->form == DW_FORM_sec_offset)
      65             :     {
      66             :       /* GNU DebugFission is slightly odd.  It uses DW_FORM_sec_offset
      67             :          in split units, but they are really (unrelocated) offsets
      68             :          from the skeleton DW_AT_GNU_ranges_base (which is only used
      69             :          for the split unit, not the skeleton ranges itself, see also
      70             :          DW_AT_rnglists_base, which is used in DWARF5 for both, but
      71             :          points to the offsets index).  So it isn't really a formptr,
      72             :          but an offset + base calculation.  */
      73      407514 :       if (unlikely (skel != NULL))
      74             :         {
      75          10 :           Elf_Data *data = attr->cu->dbg->sectiondata[cu_sec_idx (attr->cu)];
      76          10 :           const unsigned char *datap = attr->valp;
      77          10 :           size_t size = attr->cu->offset_size;
      78          10 :           if (unlikely (data == NULL
      79             :                         || datap < (const unsigned char *) data->d_buf
      80             :                         || data->d_size < size
      81             :                         || ((size_t) (datap
      82             :                                       - (const unsigned char *) data->d_buf)
      83             :                             > data->d_size - size)))
      84             :             goto invalid;
      85             : 
      86          10 :           if (size == 4)
      87          10 :             offset = read_4ubyte_unaligned (attr->cu->dbg, datap);
      88             :           else
      89           0 :             offset = read_8ubyte_unaligned (attr->cu->dbg, datap);
      90             : 
      91          10 :           offset += __libdw_cu_ranges_base (skel);
      92             :         }
      93             :       else
      94             :         {
      95      815008 :           if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
      96      407504 :                                    cu_sec_idx (attr->cu), attr->valp,
      97      407504 :                                    attr->cu->offset_size, &offset,
      98             :                                    sec_index, 0))
      99             :             return NULL;
     100             :         }
     101             :     }
     102       84216 :   else if (attr->cu->version > 3)
     103             :     goto invalid;
     104             :   else
     105         542 :     switch (attr->form)
     106             :       {
     107         542 :       case DW_FORM_data4:
     108             :       case DW_FORM_data8:
     109        1084 :         if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
     110         542 :                                  cu_sec_idx (attr->cu),
     111         542 :                                  attr->valp,
     112             :                                  attr->form == DW_FORM_data4 ? 4 : 8,
     113             :                                  &offset, sec_index, 0))
     114             :           return NULL;
     115             :         break;
     116             : 
     117           0 :       default:
     118           0 :         if (INTUSE(dwarf_formudata) (attr, &offset))
     119             :           return NULL;
     120             :       };
     121             : 
     122      408056 :   unsigned char *readp = d->d_buf + offset;
     123      408056 :   unsigned char *endp = d->d_buf + d->d_size;
     124      408056 :   if (unlikely (readp >= endp))
     125             :     {
     126       83674 :     invalid:
     127       83674 :       __libdw_seterrno (DWARF_E_INVALID_DWARF);
     128       83674 :       return NULL;
     129             :     }
     130             : 
     131      408056 :   if (endpp != NULL)
     132           0 :     *endpp = endp;
     133      408056 :   if (offsetp != NULL)
     134      408056 :     *offsetp = offset;
     135             :   return readp;
     136             : }
     137             : 
     138             : int
     139     1663143 : dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval)
     140             : {
     141     1663143 :   if (attr == NULL)
     142             :     return -1;
     143             : 
     144     1660685 :   const unsigned char *datap = attr->valp;
     145     1660685 :   const unsigned char *endp = attr->cu->endp;
     146             : 
     147     1660685 :   switch (attr->form)
     148             :     {
     149     1240580 :     case DW_FORM_data1:
     150     1240580 :       if (datap + 1 > endp)
     151             :         {
     152           0 :         invalid:
     153           0 :           __libdw_seterrno (DWARF_E_INVALID_DWARF);
     154           0 :           return -1;
     155             :         }
     156     1240580 :       *return_uval = *attr->valp;
     157     1240580 :       break;
     158             : 
     159      221716 :     case DW_FORM_data2:
     160      221716 :       if (datap + 2 > endp)
     161             :         goto invalid;
     162      221716 :       *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
     163      221716 :       break;
     164             : 
     165      178203 :     case DW_FORM_data4:
     166             :     case DW_FORM_data8:
     167             :     case DW_FORM_sec_offset:
     168             :       /* Before DWARF4 data4 and data8 are pure constants unless the
     169             :          attribute also allows offsets (*ptr classes), since DWARF4
     170             :          they are always just constants (start_scope is special though,
     171             :          since it only could express a rangelist since DWARF4).  */
     172      178203 :       if (attr->form == DW_FORM_sec_offset
     173       40893 :           || (attr->cu->version < 4 && attr->code != DW_AT_start_scope))
     174             :         {
     175      137746 :           switch (attr->code)
     176             :             {
     177       40865 :             case DW_AT_data_member_location:
     178             :             case DW_AT_frame_base:
     179             :             case DW_AT_location:
     180             :             case DW_AT_return_addr:
     181             :             case DW_AT_segment:
     182             :             case DW_AT_static_link:
     183             :             case DW_AT_string_length:
     184             :             case DW_AT_use_location:
     185             :             case DW_AT_vtable_elem_location:
     186             :             case DW_AT_GNU_locviews:
     187             :             case DW_AT_loclists_base:
     188       40865 :               if (attr->cu->version < 5)
     189             :                 {
     190             :                   /* loclistptr */
     191       40826 :                   if (__libdw_formptr (attr, IDX_debug_loc,
     192             :                                        DWARF_E_NO_DEBUG_LOC, NULL,
     193             :                                        return_uval) == NULL)
     194             :                     return -1;
     195             :                 }
     196             :               else
     197             :                 {
     198             :                   /* loclist, loclistsptr */
     199          39 :                   if (__libdw_formptr (attr, IDX_debug_loclists,
     200             :                                        DWARF_E_NO_DEBUG_LOCLISTS, NULL,
     201             :                                        return_uval) == NULL)
     202             :                     return -1;
     203             :                 }
     204             :               break;
     205             : 
     206         267 :             case DW_AT_macro_info:
     207             :               /* macptr into .debug_macinfo */
     208         267 :               if (__libdw_formptr (attr, IDX_debug_macinfo,
     209             :                                    DWARF_E_NO_ENTRY, NULL,
     210             :                                    return_uval) == NULL)
     211             :                 return -1;
     212             :               break;
     213             : 
     214         283 :             case DW_AT_GNU_macros:
     215             :             case DW_AT_macros:
     216             :               /* macptr into .debug_macro */
     217         283 :               if (__libdw_formptr (attr, IDX_debug_macro,
     218             :                                    DWARF_E_NO_ENTRY, NULL,
     219             :                                    return_uval) == NULL)
     220             :                 return -1;
     221             :               break;
     222             : 
     223       10676 :             case DW_AT_ranges:
     224             :             case DW_AT_start_scope:
     225             :             case DW_AT_GNU_ranges_base:
     226             :             case DW_AT_rnglists_base:
     227       10676 :               if (attr->cu->version < 5)
     228             :                 {
     229             :                   /* rangelistptr */
     230       10661 :                   if (__libdw_formptr (attr, IDX_debug_ranges,
     231             :                                        DWARF_E_NO_DEBUG_RANGES, NULL,
     232             :                                        return_uval) == NULL)
     233             :                     return -1;
     234             :                 }
     235             :               else
     236             :                 {
     237             :                   /* rnglistsptr */
     238          15 :                   if (__libdw_formptr (attr, IDX_debug_rnglists,
     239             :                                        DWARF_E_NO_DEBUG_RNGLISTS, NULL,
     240             :                                        return_uval) == NULL)
     241             :                     return -1;
     242             :                 }
     243             :               break;
     244             : 
     245       85566 :             case DW_AT_stmt_list:
     246             :               /* lineptr */
     247       85566 :               if (__libdw_formptr (attr, IDX_debug_line,
     248             :                                    DWARF_E_NO_DEBUG_LINE, NULL,
     249             :                                    return_uval) == NULL)
     250             :                 return -1;
     251             :               break;
     252             : 
     253          65 :             case DW_AT_addr_base:
     254             :             case DW_AT_GNU_addr_base:
     255             :               /* addrptr */
     256          65 :               if (__libdw_formptr (attr, IDX_debug_addr,
     257             :                                    DWARF_E_NO_DEBUG_ADDR, NULL,
     258             :                                    return_uval) == NULL)
     259             :                 return -1;
     260             :               break;
     261             : 
     262           0 :             case DW_AT_str_offsets_base:
     263             :               /* stroffsetsptr */
     264           0 :               if (__libdw_formptr (attr, IDX_debug_str_offsets,
     265             :                                    DWARF_E_NO_STR_OFFSETS, NULL,
     266             :                                    return_uval) == NULL)
     267             :                 return -1;
     268             :               break;
     269             : 
     270          24 :             default:
     271             :               /* sec_offset can only be used by one of the above attrs.  */
     272          24 :               if (attr->form == DW_FORM_sec_offset)
     273             :                 {
     274           0 :                   __libdw_seterrno (DWARF_E_INVALID_DWARF);
     275           0 :                   return -1;
     276             :                 }
     277             : 
     278             :               /* Not one of the special attributes, just a constant.  */
     279          24 :               if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
     280             :                                         attr->valp,
     281             :                                         attr->form == DW_FORM_data4 ? 4 : 8,
     282             :                                         return_uval))
     283             :                 return -1;
     284             :               break;
     285             :             }
     286             :         }
     287             :       else
     288             :         {
     289             :           /* We are dealing with a constant data4 or data8.  */
     290       40457 :           if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
     291             :                                     attr->valp,
     292             :                                     attr->form == DW_FORM_data4 ? 4 : 8,
     293             :                                     return_uval))
     294             :             return -1;
     295             :         }
     296             :       break;
     297             : 
     298       20011 :     case DW_FORM_sdata:
     299       20011 :       if (datap + 1 > endp)
     300             :         goto invalid;
     301       20011 :       get_sleb128 (*return_uval, datap, endp);
     302       20011 :       break;
     303             : 
     304          78 :     case DW_FORM_udata:
     305             :     case DW_FORM_rnglistx:
     306             :     case DW_FORM_loclistx:
     307          78 :       if (datap + 1 > endp)
     308             :         goto invalid;
     309          78 :       get_uleb128 (*return_uval, datap, endp);
     310          78 :       break;
     311             : 
     312          89 :     case DW_FORM_implicit_const:
     313             :       // The data comes from the abbrev, which has been bounds checked.
     314          89 :       get_sleb128_unchecked (*return_uval, datap);
     315          89 :       break;
     316             : 
     317             :     /* These are indexes into the .debug_addr section, normally resolved
     318             :        with dwarf_formaddr.  Here treat as constants.  */
     319           8 :     case DW_FORM_GNU_addr_index:
     320             :     case DW_FORM_addrx:
     321           8 :       if (datap >= endp)
     322             :         goto invalid;
     323           8 :       get_uleb128 (*return_uval, datap, endp);
     324           8 :       break;
     325             : 
     326           0 :     case DW_FORM_addrx1:
     327           0 :       if (datap >= endp - 1)
     328             :         goto invalid;
     329           0 :       *return_uval = *datap;
     330           0 :       break;
     331             : 
     332           0 :     case DW_FORM_addrx2:
     333           0 :       if (datap >= endp - 2)
     334             :         goto invalid;
     335           0 :       *return_uval = read_2ubyte_unaligned (attr->cu->dbg, datap);
     336           0 :       break;
     337             : 
     338           0 :     case DW_FORM_addrx3:
     339           0 :       if (datap >= endp - 3)
     340             :         goto invalid;
     341           0 :       *return_uval = read_3ubyte_unaligned (attr->cu->dbg, datap);
     342           0 :       break;
     343             : 
     344           0 :     case DW_FORM_addrx4:
     345           0 :       if (datap >= endp - 4)
     346             :         goto invalid;
     347           0 :       *return_uval = read_4ubyte_unaligned (attr->cu->dbg, datap);
     348           0 :       break;
     349             : 
     350           0 :     default:
     351           0 :       __libdw_seterrno (DWARF_E_NO_CONSTANT);
     352           0 :       return -1;
     353             :     }
     354             : 
     355             :   return 0;
     356             : }
     357             : INTDEF(dwarf_formudata)

Generated by: LCOV version 1.13