LCOV - code coverage report
Current view: top level - libdw - dwarf_aggregate_size.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 37 60 61.7 %
Date: 2017-01-05 09:15:16 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          12 : get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
      39             : {
      40          12 :   Dwarf_Die *type = INTUSE(dwarf_formref_die)
      41             :     (INTUSE(dwarf_attr_integrate) (die, DW_AT_type, attr_mem), type_mem);
      42             : 
      43          12 :   if (INTUSE(dwarf_peel_type) (type, type) != 0)
      44             :     return NULL;
      45             : 
      46          12 :   return type;
      47             : }
      48             : 
      49             : static int
      50          12 : array_size (Dwarf_Die *die, Dwarf_Word *size,
      51             :             Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
      52             : {
      53             :   Dwarf_Word eltsize;
      54          12 :   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          12 :   if (INTUSE(dwarf_child) (die, &child) != 0)
      63             :     return -1;
      64             : 
      65             :   bool any = false;
      66             :   Dwarf_Word total = 0;
      67             :   do
      68             :     {
      69             :       Dwarf_Word count;
      70          12 :       switch (INTUSE(dwarf_tag) (&child))
      71             :         {
      72             :         case DW_TAG_subrange_type:
      73             :           /* This has either DW_AT_count or DW_AT_upper_bound.  */
      74          12 :           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             :             {
      82             :               Dwarf_Sword upper;
      83             :               Dwarf_Sword lower;
      84          12 :               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          12 :               if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_lower_bound,
      91             :                                                 attr_mem) != NULL)
      92             :                 {
      93           0 :                   if (INTUSE(dwarf_formsdata) (attr_mem, &lower) != 0)
      94             :                     return -1;
      95             :                 }
      96             :               else
      97             :                 {
      98             :                   /* Determine default lower bound from language,
      99             :                      as per "4.12 Subrange Type Entries".  */
     100          24 :                   Dwarf_Die cu = CUDIE (die->cu);
     101          12 :                   switch (INTUSE(dwarf_srclang) (&cu))
     102             :                     {
     103             :                     case DW_LANG_C:
     104             :                     case DW_LANG_C89:
     105             :                     case DW_LANG_C99:
     106             :                     case DW_LANG_C11:
     107             :                     case DW_LANG_C_plus_plus:
     108             :                     case DW_LANG_C_plus_plus_11:
     109             :                     case DW_LANG_C_plus_plus_14:
     110             :                     case DW_LANG_ObjC:
     111             :                     case DW_LANG_ObjC_plus_plus:
     112             :                     case DW_LANG_Java:
     113             :                     case DW_LANG_D:
     114             :                     case DW_LANG_UPC:
     115             :                     case DW_LANG_Go:
     116          12 :                       lower = 0;
     117          12 :                       break;
     118             : 
     119             :                     case DW_LANG_Ada83:
     120             :                     case DW_LANG_Ada95:
     121             :                     case DW_LANG_Cobol74:
     122             :                     case DW_LANG_Cobol85:
     123             :                     case DW_LANG_Fortran77:
     124             :                     case DW_LANG_Fortran90:
     125             :                     case DW_LANG_Fortran95:
     126             :                     case DW_LANG_Fortran03:
     127             :                     case DW_LANG_Fortran08:
     128             :                     case DW_LANG_Pascal83:
     129             :                     case DW_LANG_Modula2:
     130             :                     case DW_LANG_PLI:
     131           0 :                       lower = 1;
     132           0 :                       break;
     133             : 
     134             :                     default:
     135           0 :                       return -1;
     136             :                     }
     137             :                 }
     138          12 :               if (unlikely (lower > upper))
     139             :                 return -1;
     140          12 :               count = upper - lower + 1;
     141             :             }
     142          12 :           break;
     143             : 
     144             :         case DW_TAG_enumeration_type:
     145             :           /* We have to find the DW_TAG_enumerator child with the
     146             :              highest value to know the array's element count.  */
     147           0 :           count = 0;
     148             :           Dwarf_Die enum_child;
     149           0 :           int has_children = INTUSE(dwarf_child) (die, &enum_child);
     150           0 :           if (has_children < 0)
     151             :             return -1;
     152           0 :           if (has_children > 0)
     153             :             do
     154           0 :               if (INTUSE(dwarf_tag) (&enum_child) == DW_TAG_enumerator)
     155             :                 {
     156             :                   Dwarf_Word value;
     157           0 :                   if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
     158             :                                                (&enum_child, DW_AT_const_value,
     159             :                                                 attr_mem), &value) != 0)
     160           0 :                     return -1;
     161           0 :                   if (value >= count)
     162           0 :                     count = value + 1;
     163             :                 }
     164           0 :             while (INTUSE(dwarf_siblingof) (&enum_child, &enum_child) > 0);
     165             :           break;
     166             : 
     167             :         default:
     168           0 :           continue;
     169             :         }
     170             : 
     171             :       /* This is a subrange_type or enumeration_type and we've set COUNT.
     172             :          Now determine the stride for this array dimension.  */
     173          12 :       Dwarf_Word stride = eltsize;
     174          12 :       if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_byte_stride,
     175             :                                         attr_mem) != NULL)
     176             :         {
     177           0 :           if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
     178             :             return -1;
     179             :         }
     180          12 :       else if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_bit_stride,
     181             :                                              attr_mem) != NULL)
     182             :         {
     183           0 :           if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
     184             :             return -1;
     185           0 :           if (stride % 8)       /* XXX maybe compute in bits? */
     186             :             return -1;
     187           0 :           stride /= 8;
     188             :         }
     189             : 
     190          12 :       any = true;
     191          12 :       total += stride * count;
     192             :     }
     193          12 :   while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
     194             : 
     195          12 :   if (!any)
     196             :     return -1;
     197             : 
     198          12 :   *size = total;
     199          12 :   return 0;
     200             : }
     201             : 
     202             : static int
     203          41 : aggregate_size (Dwarf_Die *die, Dwarf_Word *size, Dwarf_Die *type_mem)
     204             : {
     205             :   Dwarf_Attribute attr_mem;
     206             : 
     207          41 :   if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL)
     208          27 :     return INTUSE(dwarf_formudata) (&attr_mem, size);
     209             : 
     210          14 :   switch (INTUSE(dwarf_tag) (die))
     211             :     {
     212             :     case DW_TAG_subrange_type:
     213           0 :       return aggregate_size (get_type (die, &attr_mem, type_mem),
     214             :                              size, type_mem); /* Tail call.  */
     215             : 
     216             :     case DW_TAG_array_type:
     217          12 :       return array_size (die, size, &attr_mem, type_mem);
     218             : 
     219             :     /* Assume references and pointers have pointer size if not given an
     220             :        explicit DW_AT_byte_size.  */
     221             :     case DW_TAG_pointer_type:
     222             :     case DW_TAG_reference_type:
     223             :     case DW_TAG_rvalue_reference_type:
     224           2 :       *size = die->cu->address_size;
     225           2 :       return 0;
     226             :     }
     227             : 
     228             :   /* Most types must give their size directly.  */
     229             :   return -1;
     230             : }
     231             : 
     232             : int
     233          41 : dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size)
     234             : {
     235             :   Dwarf_Die type_mem;
     236             : 
     237          41 :   if (INTUSE (dwarf_peel_type) (die, die) != 0)
     238             :     return -1;
     239             : 
     240          41 :   return aggregate_size (die, size, &type_mem);
     241             : }
     242             : INTDEF (dwarf_aggregate_size)
     243             : OLD_VERSION (dwarf_aggregate_size, ELFUTILS_0.144)
     244             : NEW_VERSION (dwarf_aggregate_size, ELFUTILS_0.161)

Generated by: LCOV version 1.12