From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22619 invoked by alias); 8 May 2014 18:47:20 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 22499 invoked by uid 89); 8 May 2014 18:47:19 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.2 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 08 May 2014 18:47:18 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s48IlHTa026501 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Thu, 8 May 2014 14:47:17 -0400 Received: from barimba.redhat.com (ovpn-113-185.phx2.redhat.com [10.3.113.185]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s48Il38C005237; Thu, 8 May 2014 14:47:16 -0400 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 2/2] handle VLA in a struct or union Date: Thu, 08 May 2014 18:47:00 -0000 Message-Id: <1399574816-12845-3-git-send-email-tromey@redhat.com> In-Reply-To: <1399574816-12845-1-git-send-email-tromey@redhat.com> References: <1399574816-12845-1-git-send-email-tromey@redhat.com> X-SW-Source: 2014-05/txt/msg00097.txt.bz2 It is valid in C to have a VLA in a struct or union type, but gdb did not handle this. This patch adds support for these cases in the obvious way. Built and regtested on x86-64 Fedora 20. New tests included. However, before this goes in, I'd like to understand the oddity pointed out by a change in is_dynamic_type. That is, this test: /* This can happen with Ada for reasons unknown. */ && TYPE_FIELD_TYPE (type, i) != NULL is needed to avoid a crash with the Ada "iwide.exp" test. This type: (top-gdb) p real_type.main_type.name $15 = 0x7ffff0354c6d "ada__tags__type_specific_data___XVE" ... has a seemingly invalid field: (top-gdb) p real_type.main_type.nfields $9 = 13 [...] (top-gdb) p real_type.main_type.flds_bnds.fields[12] $12 = { loc = { bitpos = 576, enumval = 576, physaddr = 576, physname = 0x240
, dwarf_block = 0x240 }, artificial = 0, loc_kind = FIELD_LOC_KIND_BITPOS, bitsize = 0, type = 0x0, name = 0x0 } Joel, can you comment? Thanks. 2014-05-08 Tom Tromey * gdbtypes.c (is_dynamic_type, resolve_dynamic_type) : New cases. 2014-05-08 Tom Tromey * gdb.base/vla-datatypes.exp: Add tests for VLA-in-structure and VLA-in-union. * gdb.base/vla-datatypes.c (vla_factory): Add vla_struct, vla_union types. Initialize objects of those types and compute their sizes. --- gdb/ChangeLog | 5 ++ gdb/gdbtypes.c | 94 ++++++++++++++++++++++++++++++++ gdb/testsuite/ChangeLog | 8 +++ gdb/testsuite/gdb.base/vla-datatypes.c | 16 ++++++ gdb/testsuite/gdb.base/vla-datatypes.exp | 14 +++++ 5 files changed, 137 insertions(+) diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 95b861e..59f354a 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1636,6 +1636,20 @@ is_dynamic_type (struct type *type) return 1; return is_dynamic_type (TYPE_TARGET_TYPE (type)); } + + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + { + int i; + + for (i = 0; i < TYPE_NFIELDS (type); ++i) + if (!field_is_static (&TYPE_FIELD (type, i)) + /* This can happen with Ada for reasons unknown. */ + && TYPE_FIELD_TYPE (type, i) != NULL + && is_dynamic_type (TYPE_FIELD_TYPE (type, i))) + return 1; + } + break; } return 0; @@ -1753,6 +1767,86 @@ resolve_dynamic_type (struct type *type, CORE_ADDR addr) case TYPE_CODE_RANGE: resolved_type = resolve_dynamic_range (type); break; + + case TYPE_CODE_UNION: + { + int i; + unsigned int max_len; + + resolved_type = copy_type (type); + TYPE_FIELDS (resolved_type) + = TYPE_ALLOC (resolved_type, + TYPE_NFIELDS (resolved_type) * sizeof (struct field)); + memcpy (TYPE_FIELDS (resolved_type), + TYPE_FIELDS (type), + TYPE_NFIELDS (resolved_type) * sizeof (struct field)); + for (i = 0; i < TYPE_NFIELDS (resolved_type); ++i) + { + struct type *t; + + if (field_is_static (&TYPE_FIELD (type, i))) + continue; + + t = resolve_dynamic_type (TYPE_FIELD_TYPE (resolved_type, i), + addr); + + TYPE_FIELD_TYPE (resolved_type, i) = t; + if (TYPE_LENGTH (t) > max_len) + max_len = TYPE_LENGTH (t); + } + + TYPE_LENGTH (resolved_type) = max_len; + } + break; + + case TYPE_CODE_STRUCT: + { + int i; + int vla_field = TYPE_NFIELDS (type) - 1; + + resolved_type = copy_type (type); + TYPE_FIELDS (resolved_type) + = TYPE_ALLOC (resolved_type, + TYPE_NFIELDS (resolved_type) * sizeof (struct field)); + memcpy (TYPE_FIELDS (resolved_type), + TYPE_FIELDS (type), + TYPE_NFIELDS (resolved_type) * sizeof (struct field)); + for (i = 0; i < TYPE_NFIELDS (resolved_type); ++i) + { + struct type *t; + + if (field_is_static (&TYPE_FIELD (type, i))) + continue; + + t = resolve_dynamic_type (TYPE_FIELD_TYPE (resolved_type, i), + addr); + + /* This is a bit odd. We do not support a VLA in any + position of a struct except for the last. GCC does + have an extension that allows a VLA in the middle of a + structure, but the DWARF it emits is relatively useless + to us, so we can't represent such a type properly -- + and even if we could, we do not have enough information + to redo structure layout anyway. Nevertheless, we + check all the fields in case something odd slips + through, since it's better to see an error than + incorrect results. */ + if (t != TYPE_FIELD_TYPE (resolved_type, i) + && i != vla_field) + error (_("Attempt to resolve a variably-sized type which appears " + "in the interior of a structure type")); + + TYPE_FIELD_TYPE (resolved_type, i) = t; + } + + /* Due to the above restrictions we can successfully compute + the size of the resulting structure here, as the offset of + the final field plus its size. */ + TYPE_LENGTH (resolved_type) + = (TYPE_FIELD_BITPOS (resolved_type, vla_field) / TARGET_CHAR_BIT + + TYPE_LENGTH (TYPE_FIELD_TYPE (resolved_type, vla_field))); + } + break; } return resolved_type; diff --git a/gdb/testsuite/gdb.base/vla-datatypes.c b/gdb/testsuite/gdb.base/vla-datatypes.c index 51e342e..8561a4e 100644 --- a/gdb/testsuite/gdb.base/vla-datatypes.c +++ b/gdb/testsuite/gdb.base/vla-datatypes.c @@ -46,6 +46,18 @@ vla_factory (int n) BAR bar_vla[n]; int i; + struct vla_struct + { + int something; + int vla_field[n]; + } vla_struct_object; + + union vla_union + { + int vla_field[n]; + } vla_union_object; + + vla_struct_object.something = n; for (i = 0; i < n; i++) { int_vla[i] = i*2; @@ -61,6 +73,8 @@ vla_factory (int n) foo_vla[i].a = i*2; bar_vla[i].x = i*2; bar_vla[i].y.a = i*2; + vla_struct_object.vla_field[i] = i*2; + vla_union_object.vla_field[i] = i*2; } size_t int_size = sizeof(int_vla); /* vlas_filled */ @@ -74,6 +88,8 @@ vla_factory (int n) size_t uchar_size = sizeof(unsigned_char_vla); size_t foo_size = sizeof(foo_vla); size_t bar_size = sizeof(bar_vla); + size_t vla_struct_object_size = sizeof(vla_struct_object); + size_t vla_union_object_size = sizeof(vla_union_object); return; /* break_end_of_vla_factory */ } diff --git a/gdb/testsuite/gdb.base/vla-datatypes.exp b/gdb/testsuite/gdb.base/vla-datatypes.exp index 8247658..36af38d 100644 --- a/gdb/testsuite/gdb.base/vla-datatypes.exp +++ b/gdb/testsuite/gdb.base/vla-datatypes.exp @@ -53,6 +53,10 @@ gdb_test "print foo_vla" \ gdb_test "print bar_vla" \ "\\\{\\\{x = 0, y = \\\{a = 0\\\}\\\}, \\\{x = 2, y = \\\{a = 2\\\}\\\}, \\\{x = 4, y = \\\{a = 4\\\}\\\}, \\\{x = 6, y = \\\{a = 6\\\}\\\}, \\\{x = 8, y = \\\{a = 8\\\}\\\}\\\}" \ "print bar_vla" +gdb_test "print vla_struct_object" \ + "\\\{something = 5, vla_field = \\\{0, 2, 4, 6, 8\\\}\\\}" +gdb_test "print vla_union_object" \ + "\\\{vla_field = \\\{0, 2, 4, 6, 8\\\}\\\}" # Check whatis of VLA's. gdb_test "whatis int_vla" "type = int \\\[5\\\]" "whatis int_vla" @@ -74,6 +78,8 @@ gdb_test "whatis unsigned_char_vla" "type = unsigned char \\\[5\\\]" \ "whatis unsigned_char_vla" gdb_test "whatis foo_vla" "type = struct foo \\\[5\\\]" "whatis foo_vla" gdb_test "whatis bar_vla" "type = BAR \\\[5\\\]" "whatis bar_vla" +gdb_test "whatis vla_struct_object" "type = struct vla_struct" +gdb_test "whatis vla_union_object" "type = union vla_union" # Check ptype of VLA's. gdb_test "ptype int_vla" "type = int \\\[5\\\]" "ptype int_vla" @@ -96,6 +102,10 @@ gdb_test "ptype foo_vla" "type = struct foo {\r\n\\s+int a;\r\n} \\\[5\\\]" \ gdb_test "ptype bar_vla" \ "type = struct bar {\r\n\\s+int x;\r\n\\s+struct foo y;\r\n} \\\[5\\\]" \ "ptype bar_vla" +gdb_test "ptype vla_struct_object" \ + "type = struct vla_struct {\r\n\\s+int something;\r\n\\s+int vla_field\\\[5\\\];\r\n}" +gdb_test "ptype vla_union_object" \ + "type = union vla_union {\r\n\\s+int vla_field\\\[5\\\];\r\n}" # Check the size of the VLA's. gdb_breakpoint [gdb_get_line_number "break_end_of_vla_factory"] @@ -119,6 +129,10 @@ gdb_test "print uchar_size == sizeof(unsigned_char_vla)" " = 1" \ "size of unsigned_char_vla" gdb_test "print foo_size == sizeof(foo_vla)" " = 1" "size of foo_vla" gdb_test "print bar_size == sizeof(bar_vla)" " = 1" "size of bar_vla" +gdb_test "print vla_struct_object_size == sizeof(vla_struct_object)" \ + " = 1" "size of vla_struct_object" +gdb_test "print vla_union_object_size == sizeof(vla_union_object)" \ + " = 1" "size of vla_union_object" # Check side effects for sizeof argument. set sizeof_int [get_sizeof "int" 4] -- 1.9.0