Mirror of the gdb mailing list
 help / color / mirror / Atom feed
* dwarf2 and frame bases
@ 2004-11-10 23:57 Randolph Chung
  2004-11-10 23:58 ` Daniel Jacobowitz
  0 siblings, 1 reply; 9+ messages in thread
From: Randolph Chung @ 2004-11-10 23:57 UTC (permalink / raw)
  To: gdb

The "recurse" test has been failing on hppa for a long time. I think I
finally understand what is happening, but not sure of a fix....

the symptom of the problem is that watchpoints fail during recursion:

(gdb) watch b
Watchpoint 2: b
(gdb) continue
Continuing.
Watchpoint 2: b

Old value = 0
New value = 10
recurse (a=10) at ../../../gdb-cvs/gdb/testsuite/gdb.base/recurse.c:19
19        b *= recurse (a - 1);
(gdb) continue
Continuing.
Error evaluating expression for watchpoint 2
Cannot access memory at address 0x8
Watchpoint 2 deleted.

hppa-linux uses dwarf2, and doesn't implement hardware watchpoints.

The dwarf2 description for recurse looks like this:

 <1><a1d>: Abbrev Number: 2 (DW_TAG_subprogram)
     DW_AT_sibling     : <a53>
     DW_AT_name        : recurse
     DW_AT_decl_file   : 1
     DW_AT_decl_line   : 12
     DW_AT_type        : <a53>
     DW_AT_low_pc      : 0x10518
     DW_AT_high_pc     : 0x10598
     DW_AT_frame_base  : 1 byte block: 53       (DW_OP_reg3)
 <2><a3a>: Abbrev Number: 3 (DW_TAG_formal_parameter)
     DW_AT_name        : a
     DW_AT_decl_file   : 1
     DW_AT_decl_line   : 10
     DW_AT_type        : <a53>
     DW_AT_location    : 2 byte block: 91 5c    (DW_OP_fbreg: -36)
 <2><a46>: Abbrev Number: 4 (DW_TAG_variable)
     DW_AT_name        : b
     DW_AT_decl_file   : 1
     DW_AT_decl_line   : 13
     DW_AT_type        : <a53>
     DW_AT_location    : 2 byte block: 91 8     (DW_OP_fbreg: 8)

what seems to happen is that, to implement the watchpoint, we singlestep
through the code and evaluate 'b' at every insn. If we do this in the
prologue, we fail. The dwarf location expression handler tries to get
the frame base by using DW_AT_frame_base, which points to register 3,
but register 3 is not yet initialized in the prologue, so when we read
it, we get garbage. argh...

I don't know enough about dwarf to know how this is supposed to be
evaluated. Can someone please shed some light on this?

thanks
randolph
-- 
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: dwarf2 and frame bases
  2004-11-10 23:57 dwarf2 and frame bases Randolph Chung
@ 2004-11-10 23:58 ` Daniel Jacobowitz
  2004-11-11  3:09   ` Randolph Chung
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2004-11-10 23:58 UTC (permalink / raw)
  To: Randolph Chung; +Cc: gdb

On Wed, Nov 10, 2004 at 03:51:49PM -0800, Randolph Chung wrote:
> The "recurse" test has been failing on hppa for a long time. I think I
> finally understand what is happening, but not sure of a fix....
> 
> the symptom of the problem is that watchpoints fail during recursion:
> 
> (gdb) watch b
> Watchpoint 2: b
> (gdb) continue
> Continuing.
> Watchpoint 2: b
> 
> Old value = 0
> New value = 10
> recurse (a=10) at ../../../gdb-cvs/gdb/testsuite/gdb.base/recurse.c:19
> 19        b *= recurse (a - 1);
> (gdb) continue
> Continuing.
> Error evaluating expression for watchpoint 2
> Cannot access memory at address 0x8
> Watchpoint 2 deleted.

>      DW_AT_frame_base  : 1 byte block: 53       (DW_OP_reg3)

> what seems to happen is that, to implement the watchpoint, we singlestep
> through the code and evaluate 'b' at every insn. If we do this in the
> prologue, we fail. The dwarf location expression handler tries to get
> the frame base by using DW_AT_frame_base, which points to register 3,
> but register 3 is not yet initialized in the prologue, so when we read
> it, we get garbage. argh...
> 
> I don't know enough about dwarf to know how this is supposed to be
> evaluated. Can someone please shed some light on this?

'b' is in some particular frame.  It's up the stack from the current
frame at the time of that error message, I get.  So we should be
unwinding reg3 and using the unwound copy to determine the value of b.
Is the unwinding breaking?

What's the actual PC at the time of the error?  Is it in the prologue? 
Epilogue?  What's the stack pointer - at the time of setting the
watchpoint, and at the time of the error?

-- 
Daniel Jacobowitz


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: dwarf2 and frame bases
  2004-11-10 23:58 ` Daniel Jacobowitz
@ 2004-11-11  3:09   ` Randolph Chung
  2004-11-11  9:57     ` Daniel Jacobowitz
  0 siblings, 1 reply; 9+ messages in thread
From: Randolph Chung @ 2004-11-11  3:09 UTC (permalink / raw)
  To: gdb

> 'b' is in some particular frame.  It's up the stack from the current
> frame at the time of that error message, I get.  So we should be
> unwinding reg3 and using the unwound copy to determine the value of b.
> Is the unwinding breaking?

but the unwound copy is wrong too... :) i explain more below..

> What's the actual PC at the time of the error?  Is it in the prologue? 
first insn of the prologue.

> Epilogue?  What's the stack pointer - at the time of setting the
> watchpoint, and at the time of the error?

well, the frame_base dwarf descriptor points to r3, but the stack
pointer is actually r30. r3 is the frame pointer.

when compiled without optimization, gcc emits these prologues/epilogues
for each function:

prologue:
    stw rp, -14(%sp)
    copy %r3, %r1
    copy %r30, %r3
    stw,ma %r1, 80(%sp) /* or other frame size)

epilogue:
    ldw -14(%r3), %rp
    ldw,mb -80(%sp), %r3

(remember also that on hppa the frame grows towards higher addresses)

so in the function body, r3 is the frame base. 'b' is at *(r3 + 8)

r3 is also a callee-saved register, so its contents are undefined on
entry to the function. so even if you were to unwind r3, you won't get
the right frame base.

randolph
-- 
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: dwarf2 and frame bases
  2004-11-11  3:09   ` Randolph Chung
@ 2004-11-11  9:57     ` Daniel Jacobowitz
  2004-11-11 17:12       ` Randolph Chung
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2004-11-11  9:57 UTC (permalink / raw)
  To: Randolph Chung; +Cc: gdb

On Wed, Nov 10, 2004 at 04:09:33PM -0800, Randolph Chung wrote:
> > 'b' is in some particular frame.  It's up the stack from the current
> > frame at the time of that error message, I get.  So we should be
> > unwinding reg3 and using the unwound copy to determine the value of b.
> > Is the unwinding breaking?
> 
> but the unwound copy is wrong too... :) i explain more below..

Then, that's a bug in the unwinder.

> r3 is also a callee-saved register, so its contents are undefined on
> entry to the function. so even if you were to unwind r3, you won't get
> the right frame base.

That's your mistake.  At the first instruction of the prologue,
unwinding r3 for the previous frame should use the copy already in
r3; you need to be falling back to a prologue analyzer and cutting it
off at $pc.  I thought you already were?

-- 
Daniel Jacobowitz


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: dwarf2 and frame bases
  2004-11-11  9:57     ` Daniel Jacobowitz
@ 2004-11-11 17:12       ` Randolph Chung
  2004-11-11 19:42         ` Daniel Jacobowitz
  2004-11-11 19:47         ` Mark Kettenis
  0 siblings, 2 replies; 9+ messages in thread
From: Randolph Chung @ 2004-11-11 17:12 UTC (permalink / raw)
  To: gdb

> > but the unwound copy is wrong too... :) i explain more below..
> 
> Then, that's a bug in the unwinder.

after a night's sleep and some more looking through the code, this is
making a bit more sense...

> > r3 is also a callee-saved register, so its contents are undefined on
> > entry to the function. so even if you were to unwind r3, you won't get
> > the right frame base.
> 
> That's your mistake.  At the first instruction of the prologue,
> unwinding r3 for the previous frame should use the copy already in
> r3; you need to be falling back to a prologue analyzer and cutting it
> off at $pc.  I thought you already were?

yes, but...

so, if you are at the first insn of the prologue, and you unwind r3, you
would get the *previous frame*'s frame base.  if you used this value to
calculate the address of your locals, you will get the value they have
in the previous frame.

sounds like it should still work (i.e it should still be a valid
address), except the hppa targer has an explicit check for when we
expect r3 to be modified but we may be in the process of changing it
(since it's a 3 insn sequence). In that case, we zero the register to
tell the unwinder not to use the value in the r3 to calculate the frame
base (it uses the stack pointer and other unwind information in that
case)

See http://sources.redhat.com/ml/gdb-patches/2004-06/msg00108.html for
more details.

i know it is kind of hacky, but the frame unwinding code is explicitly
asking "what is the frame base of this frame", and the target code is
especially tuned for that..... 

i see two possible solutions:
1) perhaps the hppa target should use some other mechanism (instead of 
   mucking with r3) to tell the next frame that the frame pointer is 
   not available.....
2) in the dwarf code, when trying to get the frame base, should we
   explicitly ask for the frame base instead of using the dwarf 
   expression? perhaps this could be something that can be overridden
   by the target, so that the default still uses the dwarf information.

randolph
-- 
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: dwarf2 and frame bases
  2004-11-11 17:12       ` Randolph Chung
@ 2004-11-11 19:42         ` Daniel Jacobowitz
  2004-11-11 22:58           ` Randolph Chung
  2004-11-11 19:47         ` Mark Kettenis
  1 sibling, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2004-11-11 19:42 UTC (permalink / raw)
  To: Randolph Chung; +Cc: gdb

On Thu, Nov 11, 2004 at 08:48:52AM -0800, Randolph Chung wrote:
> so, if you are at the first insn of the prologue, and you unwind r3, you
> would get the *previous frame*'s frame base.  if you used this value to
> calculate the address of your locals, you will get the value they have
> in the previous frame.

Correct.  A watchpoint on "b" is associate with a particular frame,
because it's a local.  You want the previous frame's copy.  You get the
previous frame's copy.  Everyone wins.

> sounds like it should still work (i.e it should still be a valid
> address), except the hppa targer has an explicit check for when we
> expect r3 to be modified but we may be in the process of changing it
> (since it's a 3 insn sequence). In that case, we zero the register to
> tell the unwinder not to use the value in the r3 to calculate the frame
> base (it uses the stack pointer and other unwind information in that
> case)
> 
> See http://sources.redhat.com/ml/gdb-patches/2004-06/msg00108.html for
> more details.

This sounds totally messed up.

Suppose we're in frame A, called from frame B.  We're at the first
instruction.  If we ask the sentinel frame to unwind the value of r3,
we'll get its real register value - regardless of where we are in the
sequence.  If we ask frame A to unwind r3, we want to get frame B's r3.
Where frame A is in its prologue has no effect on what frame B's r3 was
at the time of calling A.

There's no more details in that message, just a patch :-)  I can't
trace exactly what it's doing.

> i know it is kind of hacky, but the frame unwinding code is explicitly
> asking "what is the frame base of this frame", and the target code is
> especially tuned for that..... 
> 
> i see two possible solutions:
> 1) perhaps the hppa target should use some other mechanism (instead of 
>    mucking with r3) to tell the next frame that the frame pointer is 
>    not available.....

The next frame's frame pointer _is_ available.  This is what I don't
understand.  You were asked, "unwind r3 for frame B" and instead you're
zeroing it based on where frame A is?

> 2) in the dwarf code, when trying to get the frame base, should we
>    explicitly ask for the frame base instead of using the dwarf 
>    expression? perhaps this could be something that can be overridden
>    by the target, so that the default still uses the dwarf information.

No.  The "frame base" as a GDB concept is completely separate from
DW_AT_frame_base used for local variables; let's not confuse them
further.

-- 
Daniel Jacobowitz


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: dwarf2 and frame bases
  2004-11-11 17:12       ` Randolph Chung
  2004-11-11 19:42         ` Daniel Jacobowitz
@ 2004-11-11 19:47         ` Mark Kettenis
  2004-11-11 21:18           ` Daniel Jacobowitz
  1 sibling, 1 reply; 9+ messages in thread
From: Mark Kettenis @ 2004-11-11 19:47 UTC (permalink / raw)
  To: randolph; +Cc: gdb

   Date: Thu, 11 Nov 2004 08:48:52 -0800
   From: Randolph Chung <randolph@tausq.org>

   sounds like it should still work (i.e it should still be a valid
   address), except the hppa targer has an explicit check for when we
   expect r3 to be modified but we may be in the process of changing it
   (since it's a 3 insn sequence). In that case, we zero the register to
   tell the unwinder not to use the value in the r3 to calculate the frame
   base (it uses the stack pointer and other unwind information in that
   case)

   See http://sources.redhat.com/ml/gdb-patches/2004-06/msg00108.html for
   more details.

   i know it is kind of hacky, but the frame unwinding code is explicitly
   asking "what is the frame base of this frame", and the target code is
   especially tuned for that..... 

It is certainly hacky, and defenitely wrong.  "Thou shallt not lie
about your register contents".  

   i see two possible solutions:
   1) perhaps the hppa target should use some other mechanism (instead of 
      mucking with r3) to tell the next frame that the frame pointer is 
      not available.....

Why does the next frame need that frame pointer?

   2) in the dwarf code, when trying to get the frame base, should we
      explicitly ask for the frame base instead of using the dwarf 
      expression? perhaps this could be something that can be overridden
      by the target, so that the default still uses the dwarf information.

The problem here is that the debug information provided my the
compiler is wrong, or at least incomplete.  This should be fixed in
the compiler, not in GDB.  Unfortunately this probably means we need
to have proper support for location expressions in GDB.

Mark


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: dwarf2 and frame bases
  2004-11-11 19:47         ` Mark Kettenis
@ 2004-11-11 21:18           ` Daniel Jacobowitz
  0 siblings, 0 replies; 9+ messages in thread
From: Daniel Jacobowitz @ 2004-11-11 21:18 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: randolph, gdb

On Thu, Nov 11, 2004 at 08:41:40PM +0100, Mark Kettenis wrote:
> The problem here is that the debug information provided my the
> compiler is wrong, or at least incomplete.  This should be fixed in
> the compiler, not in GDB.  Unfortunately this probably means we need
> to have proper support for location expressions in GDB.

Is there anything in particular that you know is missing?  The only
open issue I know of is multiple locations with overapping live ranges.
Using a location list for the frame base should work.

[But it's not clear how useful making DW_AT_frame_base work from the
first instruction of the function is... the locals are all still
uninitialized anyway.]

-- 
Daniel Jacobowitz


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: dwarf2 and frame bases
  2004-11-11 19:42         ` Daniel Jacobowitz
@ 2004-11-11 22:58           ` Randolph Chung
  0 siblings, 0 replies; 9+ messages in thread
From: Randolph Chung @ 2004-11-11 22:58 UTC (permalink / raw)
  To: gdb; +Cc: gdb-patches

> Suppose we're in frame A, called from frame B.  We're at the first
> instruction.  If we ask the sentinel frame to unwind the value of r3,
> we'll get its real register value - regardless of where we are in the
> sequence.  If we ask frame A to unwind r3, we want to get frame B's r3.
> Where frame A is in its prologue has no effect on what frame B's r3 was
> at the time of calling A.

ok ok, how about this fix? all the recurse.exp tests pass now.

thanks,
randolph

2004-11-11  Randolph Chung  <tausq@debian.org>

	* hppa-tdep.c (hppa_frame_cache): Properly handle the frame pointer
	register so that it can be unwound from anywhere in the prologue.

Index: hppa-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-tdep.c,v
retrieving revision 1.177
diff -u -p -r1.177 hppa-tdep.c
--- hppa-tdep.c	10 Nov 2004 16:26:55 -0000	1.177
+++ hppa-tdep.c	11 Nov 2004 21:02:42 -0000
@@ -1562,6 +1573,7 @@ hppa_frame_cache (struct frame_info *nex
   long frame_size;
   struct unwind_table_entry *u;
   CORE_ADDR prologue_end;
+  int fp_in_r1 = 0;
   int i;
 
   if (hppa_debug)
@@ -1694,6 +1712,10 @@ hppa_frame_cache (struct frame_info *nex
 	    looking_for_sp = 0;
 	    cache->saved_regs[HPPA_FP_REGNUM].addr = 0;
 	  }
+	else if (inst == 0x08030241) /* copy %r3, %r1 */
+	  {
+	    fp_in_r1 = 1;
+	  }
 	
 	/* Account for general and floating-point register saves.  */
 	reg = inst_saves_gr (inst);
@@ -1802,9 +1824,6 @@ hppa_frame_cache (struct frame_info *nex
         and saved on the stack, the Save_SP flag is set.  We use this to
         decide whether to use the frame pointer for unwinding.
 	
-	fp may be zero if it is not available in an inner frame because
-	it has been modified by not yet saved.
-	
         TODO: For the HP compiler, maybe we should use the alloca_frame flag 
 	instead of Save_SP.  */
  
@@ -1867,13 +1886,26 @@ hppa_frame_cache (struct frame_info *nex
 	}
     }
 
-  /* If the frame pointer was not saved in this frame, but we should be saving
-     it, set it to an invalid value so that another frame will not pick up the 
-     wrong frame pointer.  This can happen if we start unwinding after the 
-     frame pointer has been modified, but before we've saved it to the
-     stack.  */
-  if (u->Save_SP && !trad_frame_addr_p (cache->saved_regs, HPPA_FP_REGNUM))
-    trad_frame_set_value (cache->saved_regs, HPPA_FP_REGNUM, 0);
+  /* If Save_SP is set, then we expect the frame pointer to be saved in the
+     frame.  However, there is a one-insn window where we haven't saved it
+     yet, but we've already clobbered it.  Detect this case and fix it up.
+
+     The prologue sequence for frame-pointer functions is:
+	0: stw %rp, -20(%sp)
+	4: copy %r3, %r1
+	8: copy %sp, %r3
+	c: stw,ma %r1, XX(%sp)
+
+     So if we are at offset c, the r3 value that we want is not yet saved
+     on the stack, but it's been overwritten.  The prologue analyzer will
+     set fp_in_r1 when it sees the copy insn so we know to get the value 
+     from r1 instead.  */
+  if (u->Save_SP && !trad_frame_addr_p (cache->saved_regs, HPPA_FP_REGNUM)
+      && fp_in_r1)
+    {
+      ULONGEST r1 = frame_unwind_register_unsigned (next_frame, 1);
+      trad_frame_set_value (cache->saved_regs, HPPA_FP_REGNUM, r1);
+    }
 
   {
     /* Convert all the offsets into addresses.  */


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2004-11-11 21:18 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-11-10 23:57 dwarf2 and frame bases Randolph Chung
2004-11-10 23:58 ` Daniel Jacobowitz
2004-11-11  3:09   ` Randolph Chung
2004-11-11  9:57     ` Daniel Jacobowitz
2004-11-11 17:12       ` Randolph Chung
2004-11-11 19:42         ` Daniel Jacobowitz
2004-11-11 22:58           ` Randolph Chung
2004-11-11 19:47         ` Mark Kettenis
2004-11-11 21:18           ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox