From patchwork Tue May 5 17:53:40 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Brobecker X-Patchwork-Id: 6568 Received: (qmail 52632 invoked by alias); 5 May 2015 17:53:45 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 52618 invoked by uid 89); 5 May 2015 17:53:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL, BAYES_00, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: rock.gnat.com Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Tue, 05 May 2015 17:53:43 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id A0354D3CE8 for ; Tue, 5 May 2015 13:53:41 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id b1Qknp8YgqPZ for ; Tue, 5 May 2015 13:53:41 -0400 (EDT) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id 70F23D3C65 for ; Tue, 5 May 2015 13:53:41 -0400 (EDT) Received: by joel.gnat.com (Postfix, from userid 1000) id 9911140EAD; Tue, 5 May 2015 10:53:41 -0700 (PDT) From: Joel Brobecker To: gdb-patches@sourceware.org Subject: [pushed/Ada] compare object sizes before comparing them with value_contents_eq Date: Tue, 5 May 2015 10:53:40 -0700 Message-Id: <1430848420-9899-1-git-send-email-brobecker@adacore.com> Hello, This is an issue which I noticed while working on trying to print an array of variant records. For instance, trying to print "A1", an array of elements whose size is variable, defined as follow (see gdb.ada/var_rec_arr testcase): subtype Small_Type is Integer range 0 .. 10; type Record_Type (I : Small_Type := 0) is record S : String (1 .. I); end record; function Ident (R : Record_Type) return Record_Type; type Array_Type is array (Integer range <>) of Record_Type; A1 : Array_Type := (1 => (I => 0, S => <>), 2 => (I => 1, S => "A"), 3 => (I => 2, S => "AB")); The debugger sometimes prints the array as follow: (gdb) print A1 $1 = ((i => 0, s => ""), (i => 0, s => ""), (i => 0, s => "")) The problem happens inside the part of the loop printing the array's elements, while trying to count the number of consecutive elements that have the same value (in order to replace them by the "" message when the number exceeds a threshold). In particular, in ada-valprint.c::val_print_packed_array_elements: elttype = TYPE_TARGET_TYPE (type); eltlen = TYPE_LENGTH (check_typedef (elttype)); while (...) { if (!value_contents_eq (v0, value_embedded_offset (v0), v1, value_embedded_offset (v1), eltlen)) break; The value comparison is performed using value_contents_eq but makes the assumption that elttype is not dynamic, which is not always true. In particular, in the case above, elttype is dynamic and therefore its TYPE_LENGTH changes from element to element. As it happens in this case, the eltlen is zero, which causes the call to value_contents_eq to return true, and therefore GDB thinks all 3 elements of the array are equal. This patch fixes the issue by making sure that both v0 and v1, which are values whose type we expect to be resolved, have identical lengths. If not, then the two elements of the array cannot possibly have the same value and we do not even need to do the binary comparison. Unfortunately, this is still not enough to get GDB to print the correct value for our array, because the assumption that v0 and v1 have a type which has been resolved is actually not met. So, the second part of the patch modifies the function that constructed the values to make sure dynamic types do get resolved. gdb/ChangeLog: * ada-valprint.c (val_print_packed_array_elements): Delete variable "len". Add a type-length check when comparing two consecutive elements of the array. Use the element's actual length in call to value_contents_eq. * ada-lang.c (ada_value_primitive_packed_val): Always return a value whose type has been resolved. Tested on x86_64-linux, and pushed. Thank you, diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 990bad7..e01b98b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,14 @@ 2015-05-05 Joel Brobecker + * ada-valprint.c (val_print_packed_array_elements): Delete + variable "len". Add a type-length check when comparing two + consecutive elements of the array. Use the element's actual + length in call to value_contents_eq. + * ada-lang.c (ada_value_primitive_packed_val): Always return + a value whose type has been resolved. + +2015-05-05 Joel Brobecker + * ada-lang.c (ada_value_primitive_packed_val): Recompute BIT_SIZE and LEN if the size of the resolved type is smaller than BIT_SIZE * HOST_CHAR_BIT. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index d0aea26..c56e8bb 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -2549,6 +2549,9 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, targ += delta; } + if (is_dynamic_type (value_type (v))) + v = value_from_contents_and_address (value_type (v), value_contents (v), + 0); return v; } diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c index 720854e..ba12a78 100644 --- a/gdb/ada-valprint.c +++ b/gdb/ada-valprint.c @@ -129,13 +129,11 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr, unsigned int things_printed = 0; unsigned len; struct type *elttype, *index_type; - unsigned eltlen; unsigned long bitsize = TYPE_FIELD_BITSIZE (type, 0); struct value *mark = value_mark (); LONGEST low = 0; elttype = TYPE_TARGET_TYPE (type); - eltlen = TYPE_LENGTH (check_typedef (elttype)); index_type = TYPE_INDEX_TYPE (type); { @@ -184,9 +182,12 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr, (i * bitsize) / HOST_CHAR_BIT, (i * bitsize) % HOST_CHAR_BIT, bitsize, elttype); + if (TYPE_LENGTH (check_typedef (value_type (v0))) + != TYPE_LENGTH (check_typedef (value_type (v1)))) + break; if (!value_contents_eq (v0, value_embedded_offset (v0), v1, value_embedded_offset (v1), - eltlen)) + TYPE_LENGTH (check_typedef (value_type (v0))))) break; }