a8d9e8f
From a2246aaad96e062eb3bab55af9526aaa70adcfd0 Mon Sep 17 00:00:00 2001
a8d9e8f
From: Dima Kogan <dkogan@debian.org>
a8d9e8f
Date: Fri, 8 Dec 2017 01:45:10 -0800
a8d9e8f
Subject: [PATCH 1/2] libdw: dwarf_aggregate_size() works with
a8d9e8f
 multi-dimensional arrays
a8d9e8f
a8d9e8f
If we have a multidimensional array of dimensions (a,b,c) the number of elements
a8d9e8f
should be a*b*c, but prior to this patch dwarf_aggregate_size() would report
a8d9e8f
a+b+c instead.
a8d9e8f
a8d9e8f
This patch fixes the bug and adds a test that demonstrates the bug (the test
a8d9e8f
fails without the functional part of this patch).
a8d9e8f
a8d9e8f
Fixes: https://sourceware.org/bugzilla/show_bug.cgi?id=22546
a8d9e8f
a8d9e8f
Signed-off-by: Dima Kogan <dima@secretsauce.net>
a8d9e8f
---
a8d9e8f
 libdw/ChangeLog              |   5 +++++
a8d9e8f
 libdw/dwarf_aggregate_size.c |  43 ++++++++++++++++++++++---------------------
a8d9e8f
 tests/ChangeLog              |   6 ++++++
a8d9e8f
 tests/run-aggregate-size.sh  |   2 ++
a8d9e8f
 tests/run-peel-type.sh       |   1 +
a8d9e8f
 tests/testfile-sizes3.o.bz2  | Bin 1147 -> 1208 bytes
a8d9e8f
 6 files changed, 36 insertions(+), 21 deletions(-)
a8d9e8f
a8d9e8f
diff --git a/libdw/dwarf_aggregate_size.c b/libdw/dwarf_aggregate_size.c
a8d9e8f
index 838468d..3010c0a 100644
a8d9e8f
--- a/libdw/dwarf_aggregate_size.c
a8d9e8f
+++ b/libdw/dwarf_aggregate_size.c
a8d9e8f
@@ -63,7 +63,7 @@ array_size (Dwarf_Die *die, Dwarf_Word *size,
a8d9e8f
     return -1;
a8d9e8f
 
a8d9e8f
   bool any = false;
a8d9e8f
-  Dwarf_Word total = 0;
a8d9e8f
+  Dwarf_Word count_total = 1;
a8d9e8f
   do
a8d9e8f
     {
a8d9e8f
       Dwarf_Word count;
a8d9e8f
@@ -134,34 +134,35 @@ array_size (Dwarf_Die *die, Dwarf_Word *size,
a8d9e8f
 	  continue;
a8d9e8f
 	}
a8d9e8f
 
a8d9e8f
-      /* This is a subrange_type or enumeration_type and we've set COUNT.
a8d9e8f
-	 Now determine the stride for this array dimension.  */
a8d9e8f
-      Dwarf_Word stride = eltsize;
a8d9e8f
-      if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_byte_stride,
a8d9e8f
-					attr_mem) != NULL)
a8d9e8f
-	{
a8d9e8f
-	  if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
a8d9e8f
-	    return -1;
a8d9e8f
-	}
a8d9e8f
-      else if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_bit_stride,
a8d9e8f
-					     attr_mem) != NULL)
a8d9e8f
-	{
a8d9e8f
-	  if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
a8d9e8f
-	    return -1;
a8d9e8f
-	  if (stride % 8) 	/* XXX maybe compute in bits? */
a8d9e8f
-	    return -1;
a8d9e8f
-	  stride /= 8;
a8d9e8f
-	}
a8d9e8f
+      count_total *= count;
a8d9e8f
 
a8d9e8f
       any = true;
a8d9e8f
-      total += stride * count;
a8d9e8f
     }
a8d9e8f
   while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
a8d9e8f
 
a8d9e8f
   if (!any)
a8d9e8f
     return -1;
a8d9e8f
 
a8d9e8f
-  *size = total;
a8d9e8f
+  /* This is a subrange_type or enumeration_type and we've set COUNT.
a8d9e8f
+     Now determine the stride for this array.  */
a8d9e8f
+  Dwarf_Word stride = eltsize;
a8d9e8f
+  if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_stride,
a8d9e8f
+                                    attr_mem) != NULL)
a8d9e8f
+    {
a8d9e8f
+      if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
a8d9e8f
+        return -1;
a8d9e8f
+    }
a8d9e8f
+  else if (INTUSE(dwarf_attr_integrate) (die, DW_AT_bit_stride,
a8d9e8f
+                                         attr_mem) != NULL)
a8d9e8f
+    {
a8d9e8f
+      if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
a8d9e8f
+        return -1;
a8d9e8f
+      if (stride % 8) 	/* XXX maybe compute in bits? */
a8d9e8f
+        return -1;
a8d9e8f
+      stride /= 8;
a8d9e8f
+    }
a8d9e8f
+
a8d9e8f
+  *size = count_total * stride;
a8d9e8f
   return 0;
a8d9e8f
 }
a8d9e8f
 
a8d9e8f
diff --git a/tests/run-aggregate-size.sh b/tests/run-aggregate-size.sh
a8d9e8f
index 42b0742..6d8aa24 100755
a8d9e8f
--- a/tests/run-aggregate-size.sh
a8d9e8f
+++ b/tests/run-aggregate-size.sh
a8d9e8f
@@ -54,6 +54,7 @@
a8d9e8f
 # volatile int ia[32];
a8d9e8f
 # const volatile void * const volatile restrict va[64];
a8d9e8f
 # struct s sa[8];
a8d9e8f
+# double d3d[3][4][5];
a8d9e8f
 #
a8d9e8f
 # typedef const int foo;
a8d9e8f
 # typedef volatile foo bar;
a8d9e8f
@@ -98,6 +99,7 @@ ca size 16
a8d9e8f
 ia size 128
a8d9e8f
 va size 512
a8d9e8f
 sa size 128
a8d9e8f
+d3d size 480
a8d9e8f
 f size 4
a8d9e8f
 b size 4
a8d9e8f
 EOF
a8d9e8f
diff --git a/tests/run-peel-type.sh b/tests/run-peel-type.sh
a8d9e8f
index 7fd96e8..668e316 100755
a8d9e8f
--- a/tests/run-peel-type.sh
a8d9e8f
+++ b/tests/run-peel-type.sh
a8d9e8f
@@ -55,6 +55,7 @@ ca raw type array_type
a8d9e8f
 ia raw type array_type
a8d9e8f
 va raw type array_type
a8d9e8f
 sa raw type array_type
a8d9e8f
+d3d raw type array_type
a8d9e8f
 f raw type base_type
a8d9e8f
 b raw type base_type
a8d9e8f
 EOF
a8d9e8f
a8d9e8f
-- 
a8d9e8f
1.8.3.1
a8d9e8f
a8d9e8f
From c25dc62e59dc42378370602b0d05415a42b051d6 Mon Sep 17 00:00:00 2001
a8d9e8f
From: Mark Wielaard <mark@klomp.org>
a8d9e8f
Date: Mon, 11 Dec 2017 23:58:34 +0100
a8d9e8f
Subject: [PATCH 2/2] libdw: dwarf_aggregate_size should not peel the given
a8d9e8f
 DIE.
a8d9e8f
a8d9e8f
Reserve memory for a new DIE first. The caller might not care, but it
a8d9e8f
isn't really nice to change the DIE the caller gave us.
a8d9e8f
a8d9e8f
See also https://sourceware.org/bugzilla/show_bug.cgi?id=22546#c5
a8d9e8f
a8d9e8f
Signed-off-by: Mark Wielaard <mark@klomp.org>
a8d9e8f
---
a8d9e8f
 libdw/ChangeLog              | 5 +++++
a8d9e8f
 libdw/dwarf_aggregate_size.c | 6 +++---
a8d9e8f
 2 files changed, 8 insertions(+), 3 deletions(-)
a8d9e8f
a8d9e8f
diff --git a/libdw/dwarf_aggregate_size.c b/libdw/dwarf_aggregate_size.c
a8d9e8f
index 3010c0a..6e50185 100644
a8d9e8f
--- a/libdw/dwarf_aggregate_size.c
a8d9e8f
+++ b/libdw/dwarf_aggregate_size.c
a8d9e8f
@@ -199,12 +199,12 @@ aggregate_size (Dwarf_Die *die, Dwarf_Word *size, Dwarf_Die *type_mem)
a8d9e8f
 int
a8d9e8f
 dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size)
a8d9e8f
 {
a8d9e8f
-  Dwarf_Die type_mem;
a8d9e8f
+  Dwarf_Die die_mem, type_mem;
a8d9e8f
 
a8d9e8f
-  if (INTUSE (dwarf_peel_type) (die, die) != 0)
a8d9e8f
+  if (INTUSE (dwarf_peel_type) (die, &die_mem) != 0)
a8d9e8f
     return -1;
a8d9e8f
 
a8d9e8f
-  return aggregate_size (die, size, &type_mem);
a8d9e8f
+  return aggregate_size (&die_mem, size, &type_mem);
a8d9e8f
 }
a8d9e8f
 INTDEF (dwarf_aggregate_size)
a8d9e8f
 OLD_VERSION (dwarf_aggregate_size, ELFUTILS_0.144)
a8d9e8f
-- 
a8d9e8f
1.8.3.1
a8d9e8f