LCOV - code coverage report
Current view: top level - libdw - dwarf_formudata.c (source / functions) Hit Total Coverage
Test: elfutils-0.192 Lines: 94 132 71.2 %
Date: 2024-11-22 01:36:28 Functions: 2 2 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 76 134 56.7 %

           Branch data     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                 :    1110314 : __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
      39                 :            :                  int err_nodata, const unsigned char **endpp,
      40                 :            :                  Dwarf_Off *offsetp)
      41                 :            : {
      42         [ -  + ]:    1110314 :   if (attr == NULL)
      43                 :            :     return NULL;
      44                 :            : 
      45                 :    1110314 :   const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index];
      46                 :    1110314 :   Dwarf_CU *skel = NULL; /* See below, needed for GNU DebugFission.  */
      47   [ +  +  -  +  :    1110314 :   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                 :         50 :       skel = __libdw_find_split_unit (attr->cu);
      53         [ -  + ]:         50 :       if (skel != NULL)
      54                 :         50 :         d = skel->dbg->sectiondata[IDX_debug_ranges];
      55                 :            :     }
      56                 :            : 
      57         [ +  + ]:    1110314 :   if (unlikely (d == NULL))
      58                 :            :     {
      59                 :         34 :       __libdw_seterrno (err_nodata);
      60                 :         34 :       return NULL;
      61                 :            :     }
      62                 :            : 
      63                 :    1110280 :   Dwarf_Word offset;
      64         [ +  + ]:    1110280 :   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         [ +  + ]:     918586 :       if (unlikely (skel != NULL))
      74                 :            :         {
      75         [ +  - ]:         50 :           Elf_Data *data = attr->cu->dbg->sectiondata[cu_sec_idx (attr->cu)];
      76                 :         50 :           const unsigned char *datap = attr->valp;
      77                 :         50 :           size_t size = attr->cu->offset_size;
      78   [ +  -  +  -  :         50 :           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                 :          0 :             goto invalid;
      85                 :            : 
      86         [ +  - ]:         50 :           if (size == 4)
      87         [ -  + ]:         50 :             offset = read_4ubyte_unaligned (attr->cu->dbg, datap);
      88                 :            :           else
      89         [ #  # ]:          0 :             offset = read_8ubyte_unaligned (attr->cu->dbg, datap);
      90                 :            : 
      91                 :         50 :           offset += __libdw_cu_ranges_base (skel);
      92                 :            :         }
      93                 :            :       else
      94                 :            :         {
      95         [ -  + ]:     918536 :           if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
      96                 :     918536 :                                    cu_sec_idx (attr->cu), attr->valp,
      97                 :     918536 :                                    attr->cu->offset_size, &offset,
      98                 :            :                                    sec_index, 0))
      99                 :            :             return NULL;
     100                 :            :         }
     101                 :            :     }
     102         [ +  + ]:     191694 :   else if (attr->cu->version > 3)
     103                 :     190618 :     goto invalid;
     104                 :            :   else
     105         [ +  - ]:       1076 :     switch (attr->form)
     106                 :            :       {
     107                 :       1076 :       case DW_FORM_data4:
     108                 :            :       case DW_FORM_data8:
     109   [ -  +  -  + ]:       1076 :         if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
     110                 :       1076 :                                  cu_sec_idx (attr->cu),
     111                 :       1076 :                                  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                 :     919662 :       };
     121                 :            : 
     122                 :     919662 :   unsigned char *readp = d->d_buf + offset;
     123                 :     919662 :   unsigned char *endp = d->d_buf + d->d_size;
     124         [ -  + ]:     919662 :   if (unlikely (readp >= endp))
     125                 :            :     {
     126                 :          0 :     invalid:
     127                 :     190618 :       __libdw_seterrno (DWARF_E_INVALID_DWARF);
     128                 :     190618 :       return NULL;
     129                 :            :     }
     130                 :            : 
     131         [ -  + ]:     919662 :   if (endpp != NULL)
     132                 :          0 :     *endpp = endp;
     133         [ +  - ]:     919662 :   if (offsetp != NULL)
     134                 :     919662 :     *offsetp = offset;
     135                 :            :   return readp;
     136                 :            : }
     137                 :            : 
     138                 :            : int
     139                 :    5904124 : dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval)
     140                 :            : {
     141         [ +  + ]:    5904124 :   if (attr == NULL)
     142                 :            :     return -1;
     143                 :            : 
     144                 :    5896536 :   const unsigned char *datap = attr->valp;
     145                 :    5896536 :   const unsigned char *endp = attr->cu->endp;
     146                 :            : 
     147   [ +  +  +  +  :    5896536 :   switch (attr->form)
          +  +  +  -  -  
                -  -  - ]
     148                 :            :     {
     149                 :    3721946 :     case DW_FORM_data1:
     150         [ -  + ]:    3721946 :       if (datap + 1 > endp)
     151                 :            :         {
     152                 :          0 :         invalid:
     153                 :          0 :           __libdw_seterrno (DWARF_E_INVALID_DWARF);
     154                 :          0 :           return -1;
     155                 :            :         }
     156                 :    3721946 :       *return_uval = *attr->valp;
     157                 :    3721946 :       break;
     158                 :            : 
     159                 :     568376 :     case DW_FORM_data2:
     160         [ -  + ]:     568376 :       if (datap + 2 > endp)
     161                 :          0 :         goto invalid;
     162         [ +  + ]:     568376 :       *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
     163                 :     568376 :       break;
     164                 :            : 
     165                 :     356154 :     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         [ +  + ]:     356154 :       if (attr->form == DW_FORM_sec_offset
     173   [ +  +  +  - ]:      95530 :           || (attr->cu->version < 4 && attr->code != DW_AT_start_scope))
     174                 :            :         {
     175   [ +  +  +  +  :     261392 :           switch (attr->code)
             +  +  +  + ]
     176                 :            :             {
     177                 :     217342 :             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         [ +  + ]:     217342 :               if (attr->cu->version < 5)
     189                 :            :                 {
     190                 :            :                   /* loclistptr */
     191         [ -  + ]:        324 :                   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         [ -  + ]:     217018 :                   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                 :       3336 :             case DW_AT_macro_info:
     207                 :            :               /* macptr into .debug_macinfo */
     208         [ -  + ]:       3336 :               if (__libdw_formptr (attr, IDX_debug_macinfo,
     209                 :            :                                    DWARF_E_NO_ENTRY, NULL,
     210                 :            :                                    return_uval) == NULL)
     211                 :            :                 return -1;
     212                 :            :               break;
     213                 :            : 
     214                 :       3368 :             case DW_AT_GNU_macros:
     215                 :            :             case DW_AT_macros:
     216                 :            :               /* macptr into .debug_macro */
     217         [ -  + ]:       3368 :               if (__libdw_formptr (attr, IDX_debug_macro,
     218                 :            :                                    DWARF_E_NO_ENTRY, NULL,
     219                 :            :                                    return_uval) == NULL)
     220                 :            :                 return -1;
     221                 :            :               break;
     222                 :            : 
     223                 :      33256 :             case DW_AT_ranges:
     224                 :            :             case DW_AT_start_scope:
     225                 :            :             case DW_AT_GNU_ranges_base:
     226                 :            :             case DW_AT_rnglists_base:
     227         [ +  + ]:      33256 :               if (attr->cu->version < 5)
     228                 :            :                 {
     229                 :            :                   /* rangelistptr */
     230         [ -  + ]:        124 :                   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         [ -  + ]:      33132 :                   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                 :       3828 :             case DW_AT_stmt_list:
     246                 :            :               /* lineptr */
     247         [ -  + ]:       3828 :               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                 :        224 :             case DW_AT_addr_base:
     254                 :            :             case DW_AT_GNU_addr_base:
     255                 :            :               /* addrptr */
     256         [ -  + ]:        224 :               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                 :         26 :             case DW_AT_str_offsets_base:
     263                 :            :               /* stroffsetsptr */
     264         [ -  + ]:         26 :               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                 :         12 :             default:
     271                 :            :               /* sec_offset can only be used by one of the above attrs.  */
     272         [ -  + ]:         12 :               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   [ -  +  -  + ]:         12 :               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   [ +  +  -  + ]:     189388 :           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                 :      40054 :     case DW_FORM_sdata:
     299         [ -  + ]:      40054 :       if (datap + 1 > endp)
     300                 :          0 :         goto invalid;
     301                 :      40054 :       get_sleb128 (*return_uval, datap, endp);
     302                 :      40054 :       break;
     303                 :            : 
     304                 :     800080 :     case DW_FORM_udata:
     305                 :            :     case DW_FORM_rnglistx:
     306                 :            :     case DW_FORM_loclistx:
     307         [ -  + ]:     800080 :       if (datap + 1 > endp)
     308                 :          0 :         goto invalid;
     309                 :     800080 :       get_uleb128 (*return_uval, datap, endp);
     310                 :     800080 :       break;
     311                 :            : 
     312                 :     409886 :     case DW_FORM_implicit_const:
     313                 :            :       // The data comes from the abbrev, which has been bounds checked.
     314                 :     409886 :       get_sleb128_unchecked (*return_uval, datap);
     315                 :     409886 :       break;
     316                 :            : 
     317                 :            :     /* These are indexes into the .debug_addr section, normally resolved
     318                 :            :        with dwarf_formaddr.  Here treat as constants.  */
     319                 :         40 :     case DW_FORM_GNU_addr_index:
     320                 :            :     case DW_FORM_addrx:
     321         [ -  + ]:         40 :       if (datap >= endp)
     322                 :          0 :         goto invalid;
     323                 :         40 :       get_uleb128 (*return_uval, datap, endp);
     324                 :         40 :       break;
     325                 :            : 
     326                 :          0 :     case DW_FORM_addrx1:
     327         [ #  # ]:          0 :       if (datap >= endp - 1)
     328                 :          0 :         goto invalid;
     329                 :          0 :       *return_uval = *datap;
     330                 :          0 :       break;
     331                 :            : 
     332                 :          0 :     case DW_FORM_addrx2:
     333         [ #  # ]:          0 :       if (datap >= endp - 2)
     334                 :          0 :         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                 :          0 :         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                 :          0 :         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.16