This is the mail archive of the
mailing list for the GDB project.
[RFA/RFC] Restore old handling of multi-register variables
- From: Joel Brobecker <brobecker at adacore dot com>
- To: gdb-patches at sourceware dot org
- Cc: Joel Brobecker <brobecker at adacore dot com>
- Date: Mon, 3 Oct 2011 14:03:07 -0700
- Subject: [RFA/RFC] Restore old handling of multi-register variables
I came across a situation on AVR where pretty much none of the
local variable could be printed. Consider for instance the following
procedure Foo is
My_Variable : Integer := 16#12cd#;
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
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
Not ideal, but I see a better way to preserve support for all
these imprecise compilers out there...
* 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.
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
@@ -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));
+ 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);