From a2246aaad96e062eb3bab55af9526aaa70adcfd0 Mon Sep 17 00:00:00 2001 From: Dima Kogan 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 --- 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 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 --- 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