LCOV - code coverage report
Current view: top level - libdw - dwarf_aggregate_size.c (source / functions) Hit Total Coverage
Test: elfutils-0.171 Lines: 42 65 64.6 %
Date: 2018-06-04 08:50:22 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          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          14 : get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
      39             : {
      40          14 :   Dwarf_Die *type = INTUSE(dwarf_formref_die)
      41             :     (INTUSE(dwarf_attr_integrate) (die, DW_AT_type, attr_mem), type_mem);
      42             : 
      43          14 :   if (INTUSE(dwarf_peel_type) (type, type) != 0)
      44             :     return NULL;
      45             : 
      46          14 :   return type;
      47             : }
      48             : 
      49             : static int
      50          14 : array_size (Dwarf_Die *die, Dwarf_Word *size,
      51             :             Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
      52             : {
      53             :   Dwarf_Word eltsize;
      54          14 :   if (INTUSE(dwarf_aggregate_size) (get_type (die, attr_mem, type_mem),
      55             :                                     &eltsize) != 0)
      56             :       return -1;
      57             : 
      58             :   /* An array can have DW_TAG_subrange_type or DW_TAG_enumeration_type
      59             :      children instead that give the size of each dimension.  */
      60             : 
      61             :   Dwarf_Die child;
      62          14 :   if (INTUSE(dwarf_child) (die, &child) != 0)
      63             :     return -1;
      64             : 
      65             :   bool any = false;
      66             :   Dwarf_Word count_total = 1;
      67             :   do
      68             :     {
      69             :       Dwarf_Word count;
      70          16 :       switch (INTUSE(dwarf_tag) (&child))
      71             :         {
      72          16 :         case DW_TAG_subrange_type:
      73             :           /* This has either DW_AT_count or DW_AT_upper_bound.  */
      74          16 :           if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_count,
      75             :                                             attr_mem) != NULL)
      76             :             {
      77           0 :               if (INTUSE(dwarf_formudata) (attr_mem, &count) != 0)
      78           0 :                 return -1;
      79             :             }
      80             :           else
      81          16 :             {
      82             :               Dwarf_Sword upper;
      83             :               Dwarf_Sword lower;
      84          16 :               if (INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr_integrate)
      85             :                                            (&child, DW_AT_upper_bound,
      86             :                                             attr_mem), &upper) != 0)
      87           0 :                 return -1;
      88             : 
      89             :               /* Having DW_AT_lower_bound is optional.  */
      90          16 :               if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_lower_bound,
      91             :                                                 attr_mem) != NULL)
      92             :                 {
      93           1 :                   if (INTUSE(dwarf_formsdata) (attr_mem, &lower) != 0)
      94             :                     return -1;
      95             :                 }
      96             :               else
      97             :                 {
      98          30 :                   Dwarf_Die cu = CUDIE (die->cu);
      99          15 :                   int lang = INTUSE(dwarf_srclang) (&cu);
     100          15 :                   if (lang == -1
     101          15 :                       || INTUSE(dwarf_default_lower_bound) (lang, &lower) != 0)
     102           0 :                     return -1;
     103             :                 }
     104          16 :               if (unlikely (lower > upper))
     105             :                 return -1;
     106          16 :               count = upper - lower + 1;
     107             :             }
     108          16 :           break;
     109             : 
     110           0 :         case DW_TAG_enumeration_type:
     111             :           /* We have to find the DW_TAG_enumerator child with the
     112             :              highest value to know the array's element count.  */
     113           0 :           count = 0;
     114             :           Dwarf_Die enum_child;
     115           0 :           int has_children = INTUSE(dwarf_child) (die, &enum_child);
     116           0 :           if (has_children < 0)
     117             :             return -1;
     118           0 :           if (has_children > 0)
     119             :             do
     120           0 :               if (INTUSE(dwarf_tag) (&enum_child) == DW_TAG_enumerator)
     121             :                 {
     122             :                   Dwarf_Word value;
     123           0 :                   if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
     124             :                                                (&enum_child, DW_AT_const_value,
     125             :                                                 attr_mem), &value) != 0)
     126           0 :                     return -1;
     127           0 :                   if (value >= count)
     128           0 :                     count = value + 1;
     129             :                 }
     130           0 :             while (INTUSE(dwarf_siblingof) (&enum_child, &enum_child) > 0);
     131             :           break;
     132             : 
     133           0 :         default:
     134           0 :           continue;
     135             :         }
     136             : 
     137          16 :       count_total *= count;
     138             : 
     139          16 :       any = true;
     140             :     }
     141          16 :   while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
     142             : 
     143          14 :   if (!any)
     144             :     return -1;
     145             : 
     146             :   /* This is a subrange_type or enumeration_type and we've set COUNT.
     147             :      Now determine the stride for this array.  */
     148          14 :   Dwarf_Word stride = eltsize;
     149          14 :   if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_stride,
     150             :                                     attr_mem) != NULL)
     151             :     {
     152           0 :       if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
     153             :         return -1;
     154             :     }
     155          14 :   else if (INTUSE(dwarf_attr_integrate) (die, DW_AT_bit_stride,
     156             :                                          attr_mem) != NULL)
     157             :     {
     158           0 :       if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
     159             :         return -1;
     160           0 :       if (stride % 8)   /* XXX maybe compute in bits? */
     161             :         return -1;
     162           0 :       stride /= 8;
     163             :     }
     164             : 
     165          14 :   *size = count_total * stride;
     166          14 :   return 0;
     167             : }
     168             : 
     169             : static int
     170          45 : aggregate_size (Dwarf_Die *die, Dwarf_Word *size, Dwarf_Die *type_mem)
     171             : {
     172             :   Dwarf_Attribute attr_mem;
     173             : 
     174          45 :   if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL)
     175          29 :     return INTUSE(dwarf_formudata) (&attr_mem, size);
     176             : 
     177          16 :   switch (INTUSE(dwarf_tag) (die))
     178             :     {
     179           0 :     case DW_TAG_subrange_type:
     180           0 :       return aggregate_size (get_type (die, &attr_mem, type_mem),
     181             :                              size, type_mem); /* Tail call.  */
     182             : 
     183          14 :     case DW_TAG_array_type:
     184          14 :       return array_size (die, size, &attr_mem, type_mem);
     185             : 
     186             :     /* Assume references and pointers have pointer size if not given an
     187             :        explicit DW_AT_byte_size.  */
     188           2 :     case DW_TAG_pointer_type:
     189             :     case DW_TAG_reference_type:
     190             :     case DW_TAG_rvalue_reference_type:
     191           2 :       *size = die->cu->address_size;
     192           2 :       return 0;
     193             :     }
     194             : 
     195             :   /* Most types must give their size directly.  */
     196             :   return -1;
     197             : }
     198             : 
     199             : int
     200          45 : dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size)
     201             : {
     202             :   Dwarf_Die die_mem, type_mem;
     203             : 
     204          45 :   if (INTUSE (dwarf_peel_type) (die, &die_mem) != 0)
     205             :     return -1;
     206             : 
     207          45 :   return aggregate_size (&die_mem, size, &type_mem);
     208             : }
     209             : INTDEF (dwarf_aggregate_size)
     210             : OLD_VERSION (dwarf_aggregate_size, ELFUTILS_0.144)
     211             : NEW_VERSION (dwarf_aggregate_size, ELFUTILS_0.161)

Generated by: LCOV version 1.13