From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14634 invoked by alias); 3 Oct 2011 21:03:28 -0000 Received: (qmail 14626 invoked by uid 22791); 3 Oct 2011 21:03:27 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 03 Oct 2011 21:03:13 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id A38452BB0FF; Mon, 3 Oct 2011 17:03:12 -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 a+0mnIA2rjyY; Mon, 3 Oct 2011 17:03:12 -0400 (EDT) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id 7689E2BB0FE; Mon, 3 Oct 2011 17:03:12 -0400 (EDT) Received: by joel.gnat.com (Postfix, from userid 1000) id CC48E145615; Mon, 3 Oct 2011 17:03:07 -0400 (EDT) From: Joel Brobecker To: gdb-patches@sourceware.org Cc: Joel Brobecker Subject: [RFA/RFC] Restore old handling of multi-register variables Date: Mon, 03 Oct 2011 21:03:00 -0000 Message-Id: <1317675787-7351-1-git-send-email-brobecker@adacore.com> 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 X-SW-Source: 2011-10/txt/msg00052.txt.bz2 I came across a situation on AVR where pretty much none of the local variable could be printed. Consider for instance the following code: procedure Foo is My_Variable : Integer := 16#12cd#; begin Do_Nothing (My_Variable'Address); end Foo; After having run the program up until the call to `Do_Nothing', the debugger is unable to print the value of the variable: (gdb) p my_variable $1 = 0 The problem is that the address of my_variable is improperly computed. The debug info says: .uleb128 0x4 ; (DIE (0x48) DW_TAG_variable) .long .LASF5 ; DW_AT_name: "my_variable" .long 0x57 ; DW_AT_type .byte 0x2 ; DW_AT_location .byte 0x8c ; DW_OP_breg28 .sleb128 1 This says that the address of my_variable is to be computed by adding 1 to the value of register r28. But this is not actually correct. Registers on AVR are 1-byte long, whereas addresses are 2-byte long. In reality, we should be reading an address spanning over r28 and r29, and then add 1. Although the debugging information is at fault in this case, this used to work. I also think that we might be hitting the same problem on platforms that are still using stabs. It's just very visible on the AVR because registers on this microcontroller are only 1 byte long (whereas addresses are 2 bytes long). I've opened a ticket internally for looking at the debugging info generated by the compiler. But in the meantime, I propose to restore the old way of handling multi-register entities: When trying to fetch the value of an entity from a register, and the size of that entity is larger than the register value, assume that the value is to be fetched by reading multiple consecutive registers. Not ideal, but I see a better way to preserve support for all these imprecise compilers out there... gdb/ChangeLog: * findvar.c (value_from_register): Handle the case where the size of the entity to be read is larger than the size of the register where the entity is supposed to be read from. Tested on x86_64-linux. No regression. Thoughts? Thanks, -- Joel --- gdb/findvar.c | 30 ++++++++++++++++++++++++++++-- 1 files changed, 28 insertions(+), 2 deletions(-) diff --git a/gdb/findvar.c b/gdb/findvar.c index 8e986f1..c7e4c63 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -668,9 +668,35 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame) v = gdbarch_value_from_register (gdbarch, type, regnum, frame); /* Get the data. */ - v2 = get_frame_register_value (frame, regnum); + if (len > register_size (gdbarch, regnum)) + { + /* This is probably a situation where the data is stored over + multiple registers. We normally expect the debugging info + to describe this multi-register layout explicitly, but this + is not always the case - either because the debugging info + format does not support that level of detail (stabs) or + because the compiler is generating incorrect debugging info. + Try to be as helpful as possible, by assuming that the data + is stored over consecutive registers. */ + int optim, unavail, ok; + + ok = get_frame_register_bytes (frame, regnum, value_offset (v), + len, value_contents_raw (v), + &optim, &unavail); + if (!ok) + { + if (optim) + set_value_optimized_out (v, 1); + if (unavail) + mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type)); + } + } + else + { + v2 = get_frame_register_value (frame, regnum); - value_contents_copy (v, 0, v2, value_offset (v), len); + value_contents_copy (v, 0, v2, value_offset (v), len); + } } return v; -- 1.7.1