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