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

Generated by: LCOV version 1.16