LCOV - code coverage report
Current view: top level - libdw - dwarf_aggregate_size.c (source / functions) Hit Total Coverage
Test: elfutils-0.176 Lines: 43 66 65.2 %
Date: 2019-02-15 17:57:54 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 aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
      50             :                            Dwarf_Die *type_mem, int depth);
      51             : 
      52             : static int
      53          14 : array_size (Dwarf_Die *die, Dwarf_Word *size,
      54             :             Dwarf_Attribute *attr_mem, int depth)
      55             : {
      56             :   Dwarf_Word eltsize;
      57             :   Dwarf_Die type_mem, aggregate_type_mem;
      58          14 :   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             :   Dwarf_Die child;
      66          14 :   if (INTUSE(dwarf_child) (die, &child) != 0)
      67             :     return -1;
      68             : 
      69             :   bool any = false;
      70             :   Dwarf_Word count_total = 1;
      71             :   do
      72             :     {
      73             :       Dwarf_Word count;
      74          16 :       switch (INTUSE(dwarf_tag) (&child))
      75             :         {
      76          16 :         case DW_TAG_subrange_type:
      77             :           /* This has either DW_AT_count or DW_AT_upper_bound.  */
      78          16 :           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          16 :             {
      86             :               Dwarf_Sword upper;
      87             :               Dwarf_Sword lower;
      88          16 :               if (INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr_integrate)
      89             :                                            (&child, DW_AT_upper_bound,
      90             :                                             attr_mem), &upper) != 0)
      91           0 :                 return -1;
      92             : 
      93             :               /* Having DW_AT_lower_bound is optional.  */
      94          16 :               if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_lower_bound,
      95             :                                                 attr_mem) != NULL)
      96             :                 {
      97           1 :                   if (INTUSE(dwarf_formsdata) (attr_mem, &lower) != 0)
      98             :                     return -1;
      99             :                 }
     100             :               else
     101             :                 {
     102          30 :                   Dwarf_Die cu = CUDIE (die->cu);
     103          15 :                   int lang = INTUSE(dwarf_srclang) (&cu);
     104          15 :                   if (lang == -1
     105          15 :                       || INTUSE(dwarf_default_lower_bound) (lang, &lower) != 0)
     106           0 :                     return -1;
     107             :                 }
     108          16 :               if (unlikely (lower > upper))
     109             :                 return -1;
     110          16 :               count = upper - lower + 1;
     111             :             }
     112          16 :           break;
     113             : 
     114           0 :         case DW_TAG_enumeration_type:
     115             :           /* We have to find the DW_TAG_enumerator child with the
     116             :              highest value to know the array's element count.  */
     117           0 :           count = 0;
     118             :           Dwarf_Die enum_child;
     119           0 :           int has_children = INTUSE(dwarf_child) (die, &enum_child);
     120           0 :           if (has_children < 0)
     121             :             return -1;
     122           0 :           if (has_children > 0)
     123             :             do
     124           0 :               if (INTUSE(dwarf_tag) (&enum_child) == DW_TAG_enumerator)
     125             :                 {
     126             :                   Dwarf_Word value;
     127           0 :                   if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
     128             :                                                (&enum_child, DW_AT_const_value,
     129             :                                                 attr_mem), &value) != 0)
     130           0 :                     return -1;
     131           0 :                   if (value >= count)
     132           0 :                     count = value + 1;
     133             :                 }
     134           0 :             while (INTUSE(dwarf_siblingof) (&enum_child, &enum_child) > 0);
     135             :           break;
     136             : 
     137           0 :         default:
     138           0 :           continue;
     139             :         }
     140             : 
     141          16 :       count_total *= count;
     142             : 
     143          16 :       any = true;
     144             :     }
     145          16 :   while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
     146             : 
     147          14 :   if (!any)
     148             :     return -1;
     149             : 
     150             :   /* This is a subrange_type or enumeration_type and we've set COUNT.
     151             :      Now determine the stride for this array.  */
     152          14 :   Dwarf_Word stride = eltsize;
     153          14 :   if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_stride,
     154             :                                     attr_mem) != NULL)
     155             :     {
     156           0 :       if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
     157             :         return -1;
     158             :     }
     159          14 :   else if (INTUSE(dwarf_attr_integrate) (die, DW_AT_bit_stride,
     160             :                                          attr_mem) != NULL)
     161             :     {
     162           0 :       if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
     163             :         return -1;
     164           0 :       if (stride % 8)   /* XXX maybe compute in bits? */
     165             :         return -1;
     166           0 :       stride /= 8;
     167             :     }
     168             : 
     169          14 :   *size = count_total * stride;
     170          14 :   return 0;
     171             : }
     172             : 
     173             : static int
     174         252 : aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
     175             :                 Dwarf_Die *type_mem, int depth)
     176             : {
     177             :   Dwarf_Attribute attr_mem;
     178             : 
     179             : /* Arrays of arrays of subrange types of arrays... Don't recurse too deep.  */
     180             : #define MAX_DEPTH 256
     181         252 :   if (die == NULL || depth++ >= MAX_DEPTH)
     182             :     return -1;
     183             : 
     184         252 :   if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL)
     185         236 :     return INTUSE(dwarf_formudata) (&attr_mem, size);
     186             : 
     187          16 :   switch (INTUSE(dwarf_tag) (die))
     188             :     {
     189           0 :     case DW_TAG_subrange_type:
     190             :       {
     191             :         Dwarf_Die aggregate_type_mem;
     192           0 :         return aggregate_size (get_type (die, &attr_mem, type_mem),
     193             :                                size, &aggregate_type_mem, depth);
     194             :       }
     195             : 
     196          14 :     case DW_TAG_array_type:
     197          14 :       return array_size (die, size, &attr_mem, depth);
     198             : 
     199             :     /* Assume references and pointers have pointer size if not given an
     200             :        explicit DW_AT_byte_size.  */
     201           2 :     case DW_TAG_pointer_type:
     202             :     case DW_TAG_reference_type:
     203             :     case DW_TAG_rvalue_reference_type:
     204           2 :       *size = die->cu->address_size;
     205           2 :       return 0;
     206             :     }
     207             : 
     208             :   /* Most types must give their size directly.  */
     209             :   return -1;
     210             : }
     211             : 
     212             : int
     213         238 : dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size)
     214             : {
     215             :   Dwarf_Die die_mem, type_mem;
     216             : 
     217         238 :   if (INTUSE (dwarf_peel_type) (die, &die_mem) != 0)
     218             :     return -1;
     219             : 
     220         238 :   return aggregate_size (&die_mem, size, &type_mem, 0);
     221             : }
     222             : INTDEF (dwarf_aggregate_size)
     223             : OLD_VERSION (dwarf_aggregate_size, ELFUTILS_0.144)
     224             : NEW_VERSION (dwarf_aggregate_size, ELFUTILS_0.161)

Generated by: LCOV version 1.13