LCOV - code coverage report
Current view: top level - libdw - dwarf_aggregate_size.c (source / functions) Coverage Total Hit
Test: elfutils-0.193 Lines: 65.6 % 96 63
Test Date: 2025-08-30 14:31:09 Functions: 100.0 % 4 4
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 42.9 % 77 33

             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                 :         868 : get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
      40                 :             : {
      41                 :         868 :   Dwarf_Die *type = INTUSE(dwarf_formref_die)
      42                 :             :     (INTUSE(dwarf_attr_integrate) (die, DW_AT_type, attr_mem), type_mem);
      43                 :             : 
      44   [ +  +  -  + ]:         868 :   if (type == NULL || INTUSE(dwarf_peel_type) (type, type) != 0)
      45                 :         374 :     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                 :         432 : array_size (Dwarf_Die *die, Dwarf_Word *size,
      55                 :             :             Dwarf_Attribute *attr_mem, int depth)
      56                 :             : {
      57                 :         432 :   Dwarf_Word eltsize;
      58                 :         432 :   Dwarf_Die type_mem, aggregate_type_mem;
      59         [ -  + ]:         432 :   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                 :         432 :   Dwarf_Die child;
      67         [ -  + ]:         432 :   if (INTUSE(dwarf_child) (die, &child) != 0)
      68                 :             :     return -1;
      69                 :             : 
      70                 :             :   bool any = false;
      71                 :             :   Dwarf_Word count_total = 1;
      72                 :         436 :   do
      73                 :             :     {
      74                 :         436 :       Dwarf_Word count;
      75      [ +  -  - ]:         436 :       switch (INTUSE(dwarf_tag) (&child))
      76                 :           0 :         {
      77                 :         436 :         case DW_TAG_subrange_type:
      78                 :             :           /* This has either DW_AT_count or DW_AT_upper_bound.  */
      79         [ -  + ]:         436 :           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                 :         436 :               bool is_signed = true;
      88         [ +  + ]:         436 :               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         [ +  - ]:         382 :                   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         [ +  + ]:         436 :               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                 :         434 :                   Dwarf_Word lang;
     136                 :         434 :                   Dwarf_Die cu = CUDIE (die->cu);
     137                 :         434 :                   int res = INTUSE(dwarf_language) (&cu, &lang, NULL);
     138         [ +  - ]:         434 :                   if (res < 0
     139         [ -  + ]:         434 :                       || INTUSE(dwarf_language_lower_bound) (lang, &lower) != 0)
     140                 :           0 :                     return -1;
     141                 :             :                 }
     142         [ +  - ]:         436 :               if (unlikely (lower > upper))
     143                 :             :                 return -1;
     144                 :         436 :               count = upper - lower + 1;
     145                 :             :             }
     146                 :         436 :           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                 :         436 :       count_total *= count;
     176                 :             : 
     177                 :         436 :       any = true;
     178                 :             :     }
     179         [ +  + ]:         436 :   while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
     180                 :             : 
     181         [ -  + ]:         432 :   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                 :         432 :   Dwarf_Word stride = eltsize;
     187         [ -  + ]:         432 :   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         [ -  + ]:         432 :   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                 :         432 :   *size = count_total * stride;
     204                 :         432 :   return 0;
     205                 :             : }
     206                 :             : 
     207                 :             : static int
     208                 :        2006 : aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
     209                 :             :                 Dwarf_Die *type_mem, int depth)
     210                 :             : {
     211                 :        2006 :   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   [ +  -  -  + ]:        2006 :   if (die == NULL || depth++ >= MAX_DEPTH)
     216                 :             :     return -1;
     217                 :             : 
     218         [ +  + ]:        2006 :   if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL)
     219                 :        1570 :     return INTUSE(dwarf_formudata) (&attr_mem, size);
     220                 :             : 
     221   [ -  -  +  + ]:         436 :   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                 :         432 :     case DW_TAG_array_type:
     231                 :         432 :       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                 :        1574 : dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size)
     249                 :             : {
     250                 :        1574 :   Dwarf_Die die_mem, type_mem;
     251                 :             : 
     252         [ +  - ]:        1574 :   if (INTUSE (dwarf_peel_type) (die, &die_mem) != 0)
     253                 :             :     return -1;
     254                 :             : 
     255                 :        1574 :   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 2.0-1