LCOV - code coverage report
Current view: top level - libdw - dwarf_aggregate_size.c (source / functions) Hit Total Coverage
Test: elfutils-0.189 Lines: 62 95 65.3 %
Date: 2023-08-29 13:46:25 Functions: 4 4 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 33 77 42.9 %

           Branch data     Line data    Source code
       1                 :            : /* Compute size of an aggregate type from DWARF.
       2                 :            :    Copyright (C) 2010, 2014, 2016 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 <dwarf.h>
      34                 :            : #include "libdwP.h"
      35                 :            : 
      36                 :            : 
      37                 :            : static Dwarf_Die *
      38                 :        454 : get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
      39                 :            : {
      40                 :        454 :   Dwarf_Die *type = INTUSE(dwarf_formref_die)
      41                 :            :     (INTUSE(dwarf_attr_integrate) (die, DW_AT_type, attr_mem), type_mem);
      42                 :            : 
      43   [ +  +  -  + ]:        454 :   if (type == NULL || INTUSE(dwarf_peel_type) (type, type) != 0)
      44                 :        197 :     return NULL;
      45                 :            : 
      46                 :            :   return type;
      47                 :            : }
      48                 :            : 
      49                 :            : static int aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
      50                 :            :                            Dwarf_Die *type_mem, int depth);
      51                 :            : 
      52                 :            : static int
      53                 :        226 : array_size (Dwarf_Die *die, Dwarf_Word *size,
      54                 :            :             Dwarf_Attribute *attr_mem, int depth)
      55                 :            : {
      56                 :        226 :   Dwarf_Word eltsize;
      57                 :        226 :   Dwarf_Die type_mem, aggregate_type_mem;
      58         [ -  + ]:        226 :   if (aggregate_size (get_type (die, attr_mem, &type_mem), &eltsize,
      59                 :            :                       &aggregate_type_mem, depth) != 0)
      60                 :            :       return -1;
      61                 :            : 
      62                 :            :   /* An array can have DW_TAG_subrange_type or DW_TAG_enumeration_type
      63                 :            :      children instead that give the size of each dimension.  */
      64                 :            : 
      65                 :        226 :   Dwarf_Die child;
      66         [ -  + ]:        226 :   if (INTUSE(dwarf_child) (die, &child) != 0)
      67                 :            :     return -1;
      68                 :            : 
      69                 :            :   bool any = false;
      70                 :            :   Dwarf_Word count_total = 1;
      71                 :        228 :   do
      72                 :            :     {
      73                 :        228 :       Dwarf_Word count;
      74      [ +  -  - ]:        228 :       switch (INTUSE(dwarf_tag) (&child))
      75                 :          0 :         {
      76                 :        228 :         case DW_TAG_subrange_type:
      77                 :            :           /* This has either DW_AT_count or DW_AT_upper_bound.  */
      78         [ -  + ]:        228 :           if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_count,
      79                 :            :                                             attr_mem) != NULL)
      80                 :            :             {
      81         [ #  # ]:          0 :               if (INTUSE(dwarf_formudata) (attr_mem, &count) != 0)
      82                 :          0 :                 return -1;
      83                 :            :             }
      84                 :            :           else
      85                 :            :             {
      86                 :        228 :               bool is_signed = true;
      87         [ +  + ]:        228 :               if (INTUSE(dwarf_attr) (get_type (&child, attr_mem, &type_mem),
      88                 :            :                                       DW_AT_encoding, attr_mem) != NULL)
      89                 :            :                 {
      90                 :         31 :                   Dwarf_Word encoding;
      91         [ -  + ]:         31 :                   if (INTUSE(dwarf_formudata) (attr_mem, &encoding) == 0)
      92                 :         31 :                     is_signed = (encoding == DW_ATE_signed
      93                 :         31 :                                  || encoding == DW_ATE_signed_char);
      94                 :            :                 }
      95                 :            : 
      96                 :         31 :               Dwarf_Sword upper;
      97                 :         31 :               Dwarf_Sword lower;
      98         [ +  + ]:         31 :               if (is_signed)
      99                 :            :                 {
     100         [ +  - ]:        201 :                   if (INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr_integrate)
     101                 :            :                                                (&child, DW_AT_upper_bound,
     102                 :            :                                                 attr_mem), &upper) != 0)
     103                 :          0 :                     return -1;
     104                 :            :                 }
     105                 :            :               else
     106                 :            :                 {
     107                 :         27 :                   Dwarf_Word unsigned_upper;
     108         [ -  + ]:         27 :                   if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
     109                 :            :                                                (&child, DW_AT_upper_bound,
     110                 :            :                                                 attr_mem), &unsigned_upper) != 0)
     111                 :          0 :                     return -1;
     112                 :         27 :                   upper = unsigned_upper;
     113                 :            :                 }
     114                 :            : 
     115                 :            :               /* Having DW_AT_lower_bound is optional.  */
     116         [ +  + ]:        228 :               if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_lower_bound,
     117                 :            :                                                 attr_mem) != NULL)
     118                 :            :                 {
     119         [ +  - ]:          1 :                   if (is_signed)
     120                 :            :                     {
     121         [ +  - ]:          1 :                       if (INTUSE(dwarf_formsdata) (attr_mem, &lower) != 0)
     122                 :            :                         return -1;
     123                 :            :                     }
     124                 :            :                   else
     125                 :            :                     {
     126                 :          0 :                       Dwarf_Word unsigned_lower;
     127         [ #  # ]:          0 :                       if (INTUSE(dwarf_formudata) (attr_mem, &unsigned_lower) != 0)
     128                 :          0 :                         return -1;
     129                 :          0 :                       lower = unsigned_lower;
     130                 :            :                     }
     131                 :            :                 }
     132                 :            :               else
     133                 :            :                 {
     134                 :        227 :                   Dwarf_Die cu = CUDIE (die->cu);
     135                 :        227 :                   int lang = INTUSE(dwarf_srclang) (&cu);
     136         [ +  - ]:        227 :                   if (lang == -1
     137         [ -  + ]:        227 :                       || INTUSE(dwarf_default_lower_bound) (lang, &lower) != 0)
     138                 :          0 :                     return -1;
     139                 :            :                 }
     140         [ +  - ]:        228 :               if (unlikely (lower > upper))
     141                 :            :                 return -1;
     142                 :        228 :               count = upper - lower + 1;
     143                 :            :             }
     144                 :        228 :           break;
     145                 :            : 
     146                 :          0 :         case DW_TAG_enumeration_type:
     147                 :            :           /* We have to find the DW_TAG_enumerator child with the
     148                 :            :              highest value to know the array's element count.  */
     149                 :          0 :           count = 0;
     150                 :          0 :           Dwarf_Die enum_child;
     151                 :          0 :           int has_children = INTUSE(dwarf_child) (die, &enum_child);
     152         [ #  # ]:          0 :           if (has_children < 0)
     153                 :            :             return -1;
     154         [ #  # ]:          0 :           if (has_children > 0)
     155                 :          0 :             do
     156         [ #  # ]:          0 :               if (INTUSE(dwarf_tag) (&enum_child) == DW_TAG_enumerator)
     157                 :            :                 {
     158                 :          0 :                   Dwarf_Word value;
     159         [ #  # ]:          0 :                   if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
     160                 :            :                                                (&enum_child, DW_AT_const_value,
     161                 :            :                                                 attr_mem), &value) != 0)
     162                 :          0 :                     return -1;
     163         [ #  # ]:          0 :                   if (value >= count)
     164                 :          0 :                     count = value + 1;
     165                 :            :                 }
     166         [ #  # ]:          0 :             while (INTUSE(dwarf_siblingof) (&enum_child, &enum_child) > 0);
     167                 :            :           break;
     168                 :            : 
     169                 :          0 :         default:
     170                 :          0 :           continue;
     171                 :            :         }
     172                 :            : 
     173                 :        228 :       count_total *= count;
     174                 :            : 
     175                 :        228 :       any = true;
     176                 :            :     }
     177         [ +  + ]:        228 :   while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
     178                 :            : 
     179         [ -  + ]:        226 :   if (!any)
     180                 :            :     return -1;
     181                 :            : 
     182                 :            :   /* This is a subrange_type or enumeration_type and we've set COUNT.
     183                 :            :      Now determine the stride for this array.  */
     184                 :        226 :   Dwarf_Word stride = eltsize;
     185         [ -  + ]:        226 :   if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_stride,
     186                 :            :                                     attr_mem) != NULL)
     187                 :            :     {
     188         [ #  # ]:          0 :       if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
     189                 :            :         return -1;
     190                 :            :     }
     191         [ -  + ]:        226 :   else if (INTUSE(dwarf_attr_integrate) (die, DW_AT_bit_stride,
     192                 :            :                                          attr_mem) != NULL)
     193                 :            :     {
     194         [ #  # ]:          0 :       if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
     195                 :            :         return -1;
     196         [ #  # ]:          0 :       if (stride % 8)   /* XXX maybe compute in bits? */
     197                 :            :         return -1;
     198                 :          0 :       stride /= 8;
     199                 :            :     }
     200                 :            : 
     201                 :        226 :   *size = count_total * stride;
     202                 :        226 :   return 0;
     203                 :            : }
     204                 :            : 
     205                 :            : static int
     206                 :        985 : aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
     207                 :            :                 Dwarf_Die *type_mem, int depth)
     208                 :            : {
     209                 :        985 :   Dwarf_Attribute attr_mem;
     210                 :            : 
     211                 :            : /* Arrays of arrays of subrange types of arrays... Don't recurse too deep.  */
     212                 :            : #define MAX_DEPTH 256
     213   [ +  -  -  + ]:        985 :   if (die == NULL || depth++ >= MAX_DEPTH)
     214                 :            :     return -1;
     215                 :            : 
     216         [ +  + ]:        985 :   if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL)
     217                 :        757 :     return INTUSE(dwarf_formudata) (&attr_mem, size);
     218                 :            : 
     219   [ -  -  +  + ]:        228 :   switch (INTUSE(dwarf_tag) (die))
     220                 :            :     {
     221                 :          0 :     case DW_TAG_subrange_type:
     222                 :            :       {
     223                 :          0 :         Dwarf_Die aggregate_type_mem;
     224                 :          0 :         return aggregate_size (get_type (die, &attr_mem, type_mem),
     225                 :            :                                size, &aggregate_type_mem, depth);
     226                 :            :       }
     227                 :            : 
     228                 :        226 :     case DW_TAG_array_type:
     229                 :        226 :       return array_size (die, size, &attr_mem, depth);
     230                 :            : 
     231                 :            :     /* Assume references and pointers have pointer size if not given an
     232                 :            :        explicit DW_AT_byte_size.  */
     233                 :          2 :     case DW_TAG_pointer_type:
     234                 :            :     case DW_TAG_reference_type:
     235                 :            :     case DW_TAG_rvalue_reference_type:
     236                 :          2 :       *size = die->cu->address_size;
     237                 :          2 :       return 0;
     238                 :            :     }
     239                 :            : 
     240                 :            :   /* Most types must give their size directly.  */
     241                 :            :   return -1;
     242                 :            : }
     243                 :            : 
     244                 :            : NEW_VERSION (dwarf_aggregate_size, ELFUTILS_0.161)
     245                 :            : int
     246                 :        759 : dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size)
     247                 :            : {
     248                 :        759 :   Dwarf_Die die_mem, type_mem;
     249                 :            : 
     250         [ +  - ]:        759 :   if (INTUSE (dwarf_peel_type) (die, &die_mem) != 0)
     251                 :            :     return -1;
     252                 :            : 
     253                 :        759 :   return aggregate_size (&die_mem, size, &type_mem, 0);
     254                 :            : }
     255                 :            : NEW_INTDEF (dwarf_aggregate_size)
     256                 :            : OLD_VERSION (dwarf_aggregate_size, ELFUTILS_0.144)

Generated by: LCOV version 1.16