Message ID | 20220920072629.2736207-4-nils-christian.kempke@intel.com |
---|---|
State | Superseded |
Headers |
Return-Path: <gdb-patches-bounces+patchwork=sourceware.org@sourceware.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DFD1438582A6 for <patchwork@sourceware.org>; Tue, 20 Sep 2022 07:27:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DFD1438582A6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1663658838; bh=AbA7+iKdavuf1vIT7M7Z4KPolm6pj8qO73CneOpqKWM=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=pD0TWk+QtIuLMaLbghjK284mrO/iwoyE4gpF/b5b7DlJapYD7NfH//zuE3ga7TW5S nI/X9/8kg+THaXCWYvgtG/AndIXEZd1GILbFACUxCOWogF17pF9XPV/+w+OYO6ltGT PnjSeeiZhmCpwOgtGfjuJ6Fu4oOYCQgly5BDTzmM= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by sourceware.org (Postfix) with ESMTPS id 404423858297 for <gdb-patches@sourceware.org>; Tue, 20 Sep 2022 07:26:50 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 404423858297 X-IronPort-AV: E=McAfee;i="6500,9779,10475"; a="300440998" X-IronPort-AV: E=Sophos;i="5.93,329,1654585200"; d="scan'208";a="300440998" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Sep 2022 00:26:49 -0700 X-IronPort-AV: E=Sophos;i="5.93,329,1654585200"; d="scan'208";a="621158653" Received: from labpcdell3650-003.iul.intel.com (HELO localhost) ([172.28.49.87]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Sep 2022 00:26:48 -0700 To: gdb-patches@sourceware.org Subject: [PATCH 3/4] gdb, typeprint: fix pointer/reference typeprint for icc/ifort Date: Tue, 20 Sep 2022 09:26:28 +0200 Message-Id: <20220920072629.2736207-4-nils-christian.kempke@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220920072629.2736207-1-nils-christian.kempke@intel.com> References: <20220920072629.2736207-1-nils-christian.kempke@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list <gdb-patches.sourceware.org> List-Unsubscribe: <https://sourceware.org/mailman/options/gdb-patches>, <mailto:gdb-patches-request@sourceware.org?subject=unsubscribe> List-Archive: <https://sourceware.org/pipermail/gdb-patches/> List-Post: <mailto:gdb-patches@sourceware.org> List-Help: <mailto:gdb-patches-request@sourceware.org?subject=help> List-Subscribe: <https://sourceware.org/mailman/listinfo/gdb-patches>, <mailto:gdb-patches-request@sourceware.org?subject=subscribe> From: Nils-Christian Kempke via Gdb-patches <gdb-patches@sourceware.org> Reply-To: Nils-Christian Kempke <nils-christian.kempke@intel.com> Cc: tom@tromey.com Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" <gdb-patches-bounces+patchwork=sourceware.org@sourceware.org> |
Series |
Dynamic properties of pointers
|
|
Commit Message
Kempke, Nils-Christian
Sept. 20, 2022, 7:26 a.m. UTC
Intel classic compilers (icc/icpc/ifort) for references and pointers to arrays generate DWARF that looks like <2><17d>: Abbrev Number: 22 (DW_TAG_variable) <17e> DW_AT_decl_line : 41 <17f> DW_AT_decl_file : 1 <180> DW_AT_name : (indirect string, offset: 0x1f1): vlaref <184> DW_AT_type : <0x214> <188> DW_AT_location : 2 byte block: 76 50 (DW_OP_breg6 (rbp): -48) ... <1><214>: Abbrev Number: 12 (DW_TAG_reference_type) <215> DW_AT_type : <0x219> <1><219>: Abbrev Number: 27 (DW_TAG_array_type) <21a> DW_AT_type : <0x10e> <21e> DW_AT_data_location: 2 byte block: 97 6 (DW_OP_push_object_address; DW_OP_deref) <2><221>: Abbrev Number: 28 (DW_TAG_subrange_type) <222> DW_AT_upper_bound : <0x154> <2><226>: Abbrev Number: 0 (for pointers replace the DW_TAG_reference_type with a DW_TAG_pointer_type). This is, to my knowledge, allowed and corret DWARF but posed a problem in GDB. Usually, GDB would deal with gcc references (or pointers) that look like <2><96>: Abbrev Number: 8 (DW_TAG_variable) <97> DW_AT_location : 2 byte block: 91 50 (DW_OP_fbreg: -48) <9a> DW_AT_name : (indirect string, offset: 0x2aa): vlaref <9e> DW_AT_decl_file : 3 <9f> DW_AT_decl_line : 41 <a0> DW_AT_type : <0x1de> ... <1><1de>: Abbrev Number: 17 (DW_TAG_reference_type) <1df> DW_AT_type : <0x1e3> <1><1e3>: Abbrev Number: 22 (DW_TAG_array_type) <1e4> DW_AT_type : <0x1bf> <2><1e8>: Abbrev Number: 23 (DW_TAG_subrange_type) <1e9> DW_AT_type : <0x1f2> <1ed> DW_AT_count : <0x8a> <2><1f1>: Abbrev Number: 0 The DWARF above describes a reference with an address. At the address of this reference, so evaluating what lies at the DW_AT_location of the DW_TAG_variable, we find the address we need to use to resolve the array under the reference and print the array's values. This is also exactly what GDB does per default when printing a reference-to-array type. It evaluates the reference, and then takes that address to resolve the array (implicitly assuming that the value of the reference coincides with the address of the array). The difference to the icc output is icc's usage of DW_AT_data_location. This attribute can be used to specify a location for the actual data of an array that is different from the object's address. If it is present in addition to a DW_AT_location (as is the case above) the array values are actually located at whatever DW_AT_data_location is evaluated to and not at the address DW_AT_location of the variable points to. When dealing with the icc output this posed a problem in GDB. It would still evaluate the reference. It would then forget all about the reference and use the address obtained that way to resolve the array type (which, as mentioned, works fine with the gcc output). It would then discover the DW_AT_data_location attribute in the array's DIE and it would try to resolve it. Here is where GDB ran into a problem: according to DWARF5 and as seen in this example as well, DW_AT_data_location usually starts with a DW_OP_push_object_address. This operation pushes the address of the object currently being evaluated on the stack. The object currently being evaluated however in this case is the reference, not the array. But as GDB already evaluated the reference and as it would only know about the array's address anymore it would use that address in order to resolve the DW_AT_data_location. This failed and GDB could not print any references emitted that way, as it would usually try to access illegal memory addresses. GDB would usually display (gdb) print vlaref $1 = (int (&)[3]) <error reading variable> (in rare cases the memory address might even be valid and GDB would print random output for the array. The problem is the exact same when dealing with pointers emitted by the Intel classic compilers. For resolving this problem, we make GDB check whether the pointer's underlying type shows a DW_AT_data_location, and, if so, we assume that, in order to resolve the type, not the value of the pointer (so the value at DW_AT_location of the pointer) but the address of the pointer (so the acutal value of DW_AT_location) is be required. This patch implements the the fix for references and pointers. With this patch the above example prints as (gdb) print vlaref $1 = (int (&)[3]) @0x7fffffffc4e0: {5, 7, 9} --- gdb/gdbtypes.c | 24 ++++++++++++++++++++++++ gdb/valprint.c | 18 ++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-)
Comments
On 2022-09-20 03:26, Nils-Christian Kempke via Gdb-patches wrote: > Intel classic compilers (icc/icpc/ifort) for references and pointers > to arrays generate DWARF that looks like > > <2><17d>: Abbrev Number: 22 (DW_TAG_variable) > <17e> DW_AT_decl_line : 41 > <17f> DW_AT_decl_file : 1 > <180> DW_AT_name : (indirect string, offset: 0x1f1): vlaref > <184> DW_AT_type : <0x214> > <188> DW_AT_location : 2 byte block: 76 50 > (DW_OP_breg6 (rbp): -48) > ... > <1><214>: Abbrev Number: 12 (DW_TAG_reference_type) > <215> DW_AT_type : <0x219> > <1><219>: Abbrev Number: 27 (DW_TAG_array_type) > <21a> DW_AT_type : <0x10e> > <21e> DW_AT_data_location: 2 byte block: 97 6 > (DW_OP_push_object_address; DW_OP_deref) > <2><221>: Abbrev Number: 28 (DW_TAG_subrange_type) > <222> DW_AT_upper_bound : <0x154> > <2><226>: Abbrev Number: 0 > > (for pointers replace the DW_TAG_reference_type with a > DW_TAG_pointer_type). This is, to my knowledge, allowed and corret DWARF > but posed a problem in GDB. Usually, GDB would deal with gcc references > (or pointers) that look like > > <2><96>: Abbrev Number: 8 (DW_TAG_variable) > <97> DW_AT_location : 2 byte block: 91 50 > (DW_OP_fbreg: -48) > <9a> DW_AT_name : (indirect string, offset: 0x2aa): vlaref > <9e> DW_AT_decl_file : 3 > <9f> DW_AT_decl_line : 41 > <a0> DW_AT_type : <0x1de> > ... > <1><1de>: Abbrev Number: 17 (DW_TAG_reference_type) > <1df> DW_AT_type : <0x1e3> > <1><1e3>: Abbrev Number: 22 (DW_TAG_array_type) > <1e4> DW_AT_type : <0x1bf> > <2><1e8>: Abbrev Number: 23 (DW_TAG_subrange_type) > <1e9> DW_AT_type : <0x1f2> > <1ed> DW_AT_count : <0x8a> > <2><1f1>: Abbrev Number: 0 > > The DWARF above describes a reference with an address. At the address > of this reference, so evaluating what lies at the DW_AT_location of the > DW_TAG_variable, we find the address we need to use to resolve the > array under the reference and print the array's values. > This is also exactly what GDB does per default when printing a > reference-to-array type. It evaluates the reference, and then takes that > address to resolve the array (implicitly assuming that the value of the > reference coincides with the address of the array). > > The difference to the icc output is icc's usage of DW_AT_data_location. > This attribute can be used to specify a location for the actual data of > an array that is different from the object's address. If it is present > in addition to a DW_AT_location (as is the case above) the array values > are actually located at whatever DW_AT_data_location is evaluated to > and not at the address DW_AT_location of the variable points to. > > When dealing with the icc output this posed a problem in GDB. It would > still evaluate the reference. It would then forget all about the reference > and use the address obtained that way to resolve the array type (which, > as mentioned, works fine with the gcc output). It would then discover the > DW_AT_data_location attribute in the array's DIE and it would try to > resolve it. > Here is where GDB ran into a problem: according to DWARF5 and as seen in > this example as well, DW_AT_data_location usually starts with a > DW_OP_push_object_address. This operation pushes the address of the > object currently being evaluated on the stack. The object currently being > evaluated however in this case is the reference, not the > array. This is where I block. My understanding is that the DW_OP_push_object_address within the array's DIE always pushes the address of the array variable itself. Regardless of where we are coming from. Evaluating the reference involves evaluating the array, now the "current" object is the array. This DWARF, that you quoted above: <1><219>: Abbrev Number: 27 (DW_TAG_array_type) <21a> DW_AT_type : <0x10e> <21e> DW_AT_data_location: 2 byte block: 97 6 (DW_OP_push_object_address; DW_OP_deref) Would make sense if the array variable itself was a descriptor whose first field is a pointer to the actual array data. The DW_OP_deref would read that pointer and push it on the the stack. But if no array descriptor is used (the array variable is the data directly), then either no DW_AT_data_location should be used, or a DW_AT_data_location consisting of only DW_OP_push_object_address should be used). The DW_AT_data_location including a DW_OP_deref is not meant to deal with the fact that the array is accessed through another DIE that is a reference. This is my understanding after reading section D.2.1 (Fortran Simple Array Example) in DWARF5. Simon
Hi Simon, Thanks for the review! > -----Original Message----- > From: Simon Marchi <simark@simark.ca> > Sent: Monday, September 26, 2022 6:02 PM > To: Kempke, Nils-Christian <nils-christian.kempke@intel.com>; gdb- > patches@sourceware.org > Cc: tom@tromey.com > Subject: Re: [PATCH 3/4] gdb, typeprint: fix pointer/reference typeprint for > icc/ifort > > > > On 2022-09-20 03:26, Nils-Christian Kempke via Gdb-patches wrote: > > Intel classic compilers (icc/icpc/ifort) for references and pointers > > to arrays generate DWARF that looks like > > > > <2><17d>: Abbrev Number: 22 (DW_TAG_variable) > > <17e> DW_AT_decl_line : 41 > > <17f> DW_AT_decl_file : 1 > > <180> DW_AT_name : (indirect string, offset: 0x1f1): vlaref > > <184> DW_AT_type : <0x214> > > <188> DW_AT_location : 2 byte block: 76 50 > > (DW_OP_breg6 (rbp): -48) > > ... > > <1><214>: Abbrev Number: 12 (DW_TAG_reference_type) > > <215> DW_AT_type : <0x219> > > <1><219>: Abbrev Number: 27 (DW_TAG_array_type) > > <21a> DW_AT_type : <0x10e> > > <21e> DW_AT_data_location: 2 byte block: 97 6 > > (DW_OP_push_object_address; DW_OP_deref) > > <2><221>: Abbrev Number: 28 (DW_TAG_subrange_type) > > <222> DW_AT_upper_bound : <0x154> > > <2><226>: Abbrev Number: 0 > > > > (for pointers replace the DW_TAG_reference_type with a > > DW_TAG_pointer_type). This is, to my knowledge, allowed and corret > DWARF > > but posed a problem in GDB. Usually, GDB would deal with gcc references > > (or pointers) that look like > > > > <2><96>: Abbrev Number: 8 (DW_TAG_variable) > > <97> DW_AT_location : 2 byte block: 91 50 > > (DW_OP_fbreg: -48) > > <9a> DW_AT_name : (indirect string, offset: 0x2aa): vlaref > > <9e> DW_AT_decl_file : 3 > > <9f> DW_AT_decl_line : 41 > > <a0> DW_AT_type : <0x1de> > > ... > > <1><1de>: Abbrev Number: 17 (DW_TAG_reference_type) > > <1df> DW_AT_type : <0x1e3> > > <1><1e3>: Abbrev Number: 22 (DW_TAG_array_type) > > <1e4> DW_AT_type : <0x1bf> > > <2><1e8>: Abbrev Number: 23 (DW_TAG_subrange_type) > > <1e9> DW_AT_type : <0x1f2> > > <1ed> DW_AT_count : <0x8a> > > <2><1f1>: Abbrev Number: 0 > > > > The DWARF above describes a reference with an address. At the address > > of this reference, so evaluating what lies at the DW_AT_location of the > > DW_TAG_variable, we find the address we need to use to resolve the > > array under the reference and print the array's values. > > This is also exactly what GDB does per default when printing a > > reference-to-array type. It evaluates the reference, and then takes that > > address to resolve the array (implicitly assuming that the value of the > > reference coincides with the address of the array). > > > > The difference to the icc output is icc's usage of DW_AT_data_location. > > This attribute can be used to specify a location for the actual data of > > an array that is different from the object's address. If it is present > > in addition to a DW_AT_location (as is the case above) the array values > > are actually located at whatever DW_AT_data_location is evaluated to > > and not at the address DW_AT_location of the variable points to. > > > > When dealing with the icc output this posed a problem in GDB. It would > > still evaluate the reference. It would then forget all about the reference > > and use the address obtained that way to resolve the array type (which, > > as mentioned, works fine with the gcc output). It would then discover the > > DW_AT_data_location attribute in the array's DIE and it would try to > > resolve it. > > Here is where GDB ran into a problem: according to DWARF5 and as seen in > > this example as well, DW_AT_data_location usually starts with a > > DW_OP_push_object_address. This operation pushes the address of the > > object currently being evaluated on the stack. The object currently being > > evaluated however in this case is the reference, not the > > array. > > This is where I block. My understanding is that the > DW_OP_push_object_address within the array's DIE always pushes the > address of the array variable itself. Regardless of where we are coming > from. Evaluating the reference involves evaluating the array, now the > "current" object is the array. > > This DWARF, that you quoted above: > > <1><219>: Abbrev Number: 27 (DW_TAG_array_type) > <21a> DW_AT_type : <0x10e> > <21e> DW_AT_data_location: 2 byte block: 97 6 > (DW_OP_push_object_address; DW_OP_deref) > > Would make sense if the array variable itself was a descriptor whose > first field is a pointer to the actual array data. The DW_OP_deref > would read that pointer and push it on the the stack. But if no array > descriptor is used (the array variable is the data directly), then > either no DW_AT_data_location should be used, or a DW_AT_data_location > consisting of only DW_OP_push_object_address should be used). > > The DW_AT_data_location including a DW_OP_deref is not meant to deal > with the fact that the array is accessed through another DIE that is a > reference. > > This is my understanding after reading section D.2.1 (Fortran Simple > Array Example) in DWARF5. > > Simon Yes, so this part in the DWARF is also where I am quite unsure about what the DWARF actually allows. I agree that the DWARF icc/ifort emit is a bit weird. And I also prefer the way gfortran/ifx emit Fortran/C pointers.. And I agree that the original thought behind DW_AT_data_location was different. My main confusion is here: looking at the example D.2.1, if I follow your argument, why would we then use the address of arrayvar to evaluate the bounds? Would DW_OP_push_object_address within the DW_TAG_subrange_type then not also need to push the subrange's address (and indicate some offset to the address of its base type, the DW_TAG_subrange_type)? The example uses the address of 'arrayvar'. I find the example a bit confusing and I do not clearly understand what the 'current object' is. As we only have a chain of DWARF DIE's I tend to assume that the innermost variable in the chain is meant. Everything else seems not well defined, e.g., why assume that the DW_TAG_array_type changes the 'current object' but the DW_TAG_subrange_type does not? I get your point however - and I agree - if there was no pointer/reference construct wrapped around the array type I would also assume that DW_AT_data_location looks like you pointed out. A bit more about this patch: icc/ifort will likely not change their DWARF anymore (before they are EOLed). I do find the patch a bit hacky, but at least currently I feel like the DWARF is not technically wrong - even though unusual. Whether or not it should go into GDB - I don't know. It is on the more vital side for enabling pointer printing in icc/ifort (which elsewise would just print non-sense). From my point of view we can also drop it from this series. It is tailored to icc/ifort and unless some other compiler decides to emit the same (weird-ish) DWARF we will not need it in GDB. We just wanted to at least put it out there once. Thanks again! Nils Intel Deutschland GmbH Registered Address: Am Campeon 10, 85579 Neubiberg, Germany Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de> Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva Chairperson of the Supervisory Board: Nicole Lau Registered Office: Munich Commercial Register: Amtsgericht Muenchen HRB 186928
[AMD Official Use Only - General] Hi Kempke and Simon, If you don't mind I would like to step in for a second on comment on your last question: > > Yes, so this part in the DWARF is also where I am quite unsure about what > the DWARF actually allows. I agree that the DWARF icc/ifort emit is a bit > weird. > And I also prefer the way gfortran/ifx emit Fortran/C pointers.. > And I agree that the original thought behind DW_AT_data_location was > different. > > My main confusion is here: > > looking at the example D.2.1, if I follow your argument, why would we then > use the address of arrayvar to evaluate the bounds? Would > DW_OP_push_object_address within the DW_TAG_subrange_type then not > also need to push the subrange's address (and indicate some offset to the > address of its base type, the DW_TAG_subrange_type)? > > The example uses the address of 'arrayvar'. I find the example a bit > confusing and I do not clearly understand what the 'current object' is. As we > only have a chain of DWARF DIE's I tend to assume that the innermost > variable in the chain is meant. > Everything else seems not well defined, e.g., why assume that the > DW_TAG_array_type changes the 'current object' but the > DW_TAG_subrange_type does not? > The key difference here is that the DW_TAG_reference_type is a "standalone" type and there is always an object or a member (a physical location description) behind it while the DW_TAG_subrange_type is a by definition tied to a "standalone" array types. Unfortunately, it is not really meaningful to have an object of a DW_TAG_subrange_type so the type is more there to allow factorizing of the debug information. In the case of DW_TAG_reference_type, there is always an object that is the reference to something and if you dereference it, you get another object that the original object referenced, which is a very different case then the DW_TAG_subrange_type and the array type that references it. That being said, I don't believe that there is anywhere in DWARF stating that if there is an actual object of a DW_TAG_subrange_type type that the DW_OP_push_object_address operation (in any of the attributes of that type) should not use it, it just that the way how this type is defined doesn't really allow you to have a separate object of that type. At the end of the day, the definition of DW_OP_push_object_address operation just states that the operation pushes the address of the object currently being evaluated, It even states that it could be a component of an object, but it still has to be something tangible (a real location). I hope this clarifies things a bit for you. Regards, Zoran
> The key difference here is that the DW_TAG_reference_type is a "standalone" type and there is always an object or a member (a physical location description) behind it while the DW_TAG_subrange_type is a by definition tied to a "standalone" array types. Unfortunately, it is not really meaningful to have an object of a DW_TAG_subrange_type so the type is more there to allow factorizing of the debug information. > > In the case of DW_TAG_reference_type, there is always an object that is the reference to something and if you dereference it, you get another object that the original object referenced, which is a very different case then the DW_TAG_subrange_type and the array type that references it. > > That being said, I don't believe that there is anywhere in DWARF stating that if there is an actual object of a DW_TAG_subrange_type type that the DW_OP_push_object_address operation (in any of the attributes of that type) should not use it, it just that the way how this type is defined doesn't really allow you to have a separate object of that type. Well, you can have a standaline DW_TAG_subrange_type object, in languages where you can define types to be subranges of other types. I just tried this Ada example: https://learn.adacore.com/courses/intro-to-ada/chapters/strongly_typed_language.html#subtypes And I got this, a variable with the subrange as its type: 0x00001a08: DW_TAG_subprogram DW_AT_name [DW_FORM_strp] ("greet") 0x00001a63: DW_TAG_subrange_type DW_AT_lower_bound [DW_FORM_data1] (0x05) DW_AT_upper_bound [DW_FORM_data1] (0x06) DW_AT_name [DW_FORM_strp] ("greet__weekend_days") DW_AT_type [DW_FORM_ref4] (0x00001a2a "greet__days") 0x00001a7b: DW_TAG_variable DW_AT_name [DW_FORM_string] ("s") DW_AT_type [DW_FORM_ref4] (0x00001a63 "greet__weekend_days") DW_AT_location [DW_FORM_exprloc] (DW_OP_fbreg -125) > At the end of the day, the definition of DW_OP_push_object_address operation just states that the operation pushes the address of the object currently being evaluated, It even states that it could be a component of an object, but it still has to be something tangible (a real location). I think that the confusion comes from the fact that DW_TAG_subrange_type can serve two different and unrelated purposes. One as a standard standalone type, as shown above. And two, as a direct child of a DW_TAG_array_type, used to express the bounds. Section 5.5 - Array Type Entries says: Each array dimension is described by a debugging information entry with either the tag DW_TAG_subrange_type or the tag DW_TAG_enumeration_type. These entries are children of the array type entry and are ordered to reflect the appearance of the dimensions in the source program (that is, leftmost dimension first, next to leftmost second, and so on). My interpretation of this text is that it describes that second special use case where DW_TAG_subrange_type describes the bounds of the array, but does not represent a concrete object itself, as it would with its first purpose. As Zoran said, maybe this helped "factorize" the debug information and make the DWARF committee write less text, but I think it also adds confusion. I think it should be interpreted as if the DW_TAG_array_type had the DW_AT_{lower,upper}_bound attributes directly. I think this is what is intended by the standard, looking at the D.2.1 example. The comments on the DW_AT_{lower,upper}_bound expressions show that they consider DW_OP_push_object_address to have pushed the array's address. That said, assuming that this is indeed "broken" DWARF, icc/ifort produce what they produce, and I am open to make GDB handle it. We work around broken DWARF all the time for different compilers. However, the commit message would need to explain this, the code should make it clear that this is a workaround for a specific form of DWARF emitted by icc/ifort, and ideally gated behind a compiler check. This way, in 20 years, when we decide we no longer want to support 20 year old hacks, it's easy to identify and remove them. It would also be good to have a gdb.dwarf2 test case for this, explaining that "this is not really valid DWARF but we want to support it anyway". Simon
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index a4d79a64e95..ce48b968f4b 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -2809,6 +2809,18 @@ resolve_dynamic_pointer (struct type *type, if (addr_stack->valaddr.data () != NULL) pinfo.addr = extract_typed_address (addr_stack->valaddr.data (), type); + else if (TYPE_DATA_LOCATION (TYPE_TARGET_TYPE (type)) != nullptr) + { + /* If the underlying type has a DW_AT_data_location attribute + we assume that we need to take the reference's address (the + value of its DW_AT_location) to resolve the type instead + of the reference's value (the dereferenced DW_AT_location). + This is because DW_AT_data_location usually uses + DW_OP_push_obj_address which pushes the address of the + currently observed object on the stack. Here, this is the + reference itself and not its underlying type. */ + pinfo.addr = addr_stack->addr; + } else pinfo.addr = read_memory_typed_address (addr_stack->addr, type); pinfo.next = addr_stack; @@ -2874,6 +2886,18 @@ resolve_dynamic_type_internal (struct type *type, if (addr_stack->valaddr.data () != NULL) pinfo.addr = extract_typed_address (addr_stack->valaddr.data (), type); + else if (TYPE_DATA_LOCATION (TYPE_TARGET_TYPE (type)) != nullptr) + { + /* If the underlying type has a DW_AT_data_location attribute + we assume that we need to take the reference's address (the + value of its DW_AT_location) to resolve the type instead + of the reference's value (the dereferenced DW_AT_location). + This is because DW_AT_data_location usually uses + DW_OP_push_obj_address which pushes the address of the + currently observed object on the stack. Here, this is the + reference itself and not its underlying type. */ + pinfo.addr = addr_stack->addr; + } else pinfo.addr = read_memory_typed_address (addr_stack->addr, type); pinfo.next = addr_stack; diff --git a/gdb/valprint.c b/gdb/valprint.c index 0c3066602fe..7fee691cae0 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -565,8 +565,22 @@ generic_val_print_ref (struct type *type, gdb_assert (embedded_offset == 0); } else - deref_val = value_at (TYPE_TARGET_TYPE (type), - unpack_pointer (type, valaddr + embedded_offset)); + { + /* If the underlying type has a DW_AT_data_location attribute we need + to take the reference's address (so the value of its DW_AT_location) + to resolve the type instead of the references value (the + dereferenced DW_AT_location). This is because + DW_AT_data_location uses DW_OP_push_obj_address which pushes the + address of the currently observed object on the stack, which is the + reference itself here and not its underlying type. */ + if (TYPE_DATA_LOCATION (TYPE_TARGET_TYPE (type)) != nullptr) + deref_val = value_at (TYPE_TARGET_TYPE (type), + value_address (original_value)); + else + deref_val = value_at (TYPE_TARGET_TYPE (type), + unpack_pointer (type, + valaddr + embedded_offset)); + } } /* Else, original_value isn't a synthetic reference or we don't have to print the reference's contents.