Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* CRIS port; frame cleanup crash
@ 2003-08-11 13:30 Orjan Friberg
  2003-08-12 15:11 ` Orjan Friberg
  2003-08-12 17:36 ` Andrew Cagney
  0 siblings, 2 replies; 12+ messages in thread
From: Orjan Friberg @ 2003-08-11 13:30 UTC (permalink / raw)
  To: gdb-patches

After a long overdue update of my gdb cvs tree, I found that something 
broke late March/early April.  I don't quite understand what goes on, 
but it seems to happen the first time a frame allocated by 
deprecated_frame_xmalloc_with_cleanup is freed by do_cleanups (which 
happens in cris_skip_prologue_main).  gdb segfaults on a call to free 
with a pointer to that frame.  The arm-tdep.c file contains the same 
construct of:

   old_chain = make_cleanup (null_cleanup, NULL);
   frame = deprecated_frame_xmalloc_with_cleanup (..., ...)
   <do something with frame>
   do_cleanups (old_chain);

The only thing I found that looked suspicous was that the frame variable 
is allocated by a call to obstack_alloc, but free'd with a "normal" call 
to free.  I would have guessed it should be with obstack_free, but then 
again, my understanding of what happens is limited so far.

Any pointers or suggestions are appreciated.

-- 
Orjan Friberg
Axis Communications



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

* Re: CRIS port; frame cleanup crash
  2003-08-11 13:30 CRIS port; frame cleanup crash Orjan Friberg
@ 2003-08-12 15:11 ` Orjan Friberg
  2003-08-12 17:36 ` Andrew Cagney
  1 sibling, 0 replies; 12+ messages in thread
From: Orjan Friberg @ 2003-08-12 15:11 UTC (permalink / raw)
  To: gdb-patches

Orjan Friberg wrote:
> After a long overdue update of my gdb cvs tree, I found that something 
> broke late March/early April.  I don't quite understand what goes on, 
> but it seems to happen the first time a frame allocated by 
> deprecated_frame_xmalloc_with_cleanup is freed by do_cleanups (which 
> happens in cris_skip_prologue_main).  gdb segfaults on a call to free 
> with a pointer to that frame.

I hacked around that particular failure by not allocating a frame, and 
simply relying on symbol information.  With that out of the way, I'm 
able to run the testsuite, albeit with some more FAILs than stock a gdb 5.3.

However, poking around in all the stuff that has been deprecated, I'm 
sort of at a loss as to where to start.  Replacing the deprecated 
function/macros one at a time doesn't look feasible, since a lot of 
functionality is replaced by the same functions 
(push_dummy_code/push_dummy_call for example).  Is there a preferred way 
of doing it, or is it just a matter of diving right into it?  I'd prefer 
to do it in a structured way to be able to catch when things start to 
break.  I see there are a couple of targets that have made the 
transition (d10v and m68hc11 for example), so that should provide some help.

Also, is there any documentation for the frame handling machinery that I 
didn't find?  I checked the archives, and read a bunch of Andrew 
Cagney's posts related to this, but couldn't really get the big picture 
from that.  (The Internals manual has only a brief mention of frames in 
section 3.1.)

Thanks for any help.

-- 
Orjan Friberg
Axis Communications



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

* Re: CRIS port; frame cleanup crash
  2003-08-11 13:30 CRIS port; frame cleanup crash Orjan Friberg
  2003-08-12 15:11 ` Orjan Friberg
@ 2003-08-12 17:36 ` Andrew Cagney
  2003-08-13 10:17   ` Orjan Friberg
  2004-02-12 18:59   ` Orjan Friberg
  1 sibling, 2 replies; 12+ messages in thread
From: Andrew Cagney @ 2003-08-12 17:36 UTC (permalink / raw)
  To: Orjan Friberg; +Cc: gdb-patches

> After a long overdue update of my gdb cvs tree, I found that something broke late March/early April.  I don't quite understand what goes on, but it seems to happen the first time a frame allocated by deprecated_frame_xmalloc_with_cleanup is freed by do_cleanups (which happens in cris_skip_prologue_main).  gdb segfaults on a call to free with a pointer to that frame.  The arm-tdep.c file contains the same construct of:
> 
>   old_chain = make_cleanup (null_cleanup, NULL);
>   frame = deprecated_frame_xmalloc_with_cleanup (..., ...)
>   <do something with frame>
>   do_cleanups (old_chain);

Er, that points at a bug:

struct frame_info *
deprecated_frame_xmalloc (void)
{
   struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
   frame->this_id.p = 1;
   return frame;
}

shouldn't be allocated from the frame obstack pool.  I'll commit a fix.

> However, poking around in all the stuff that has been deprecated, I'm sort of at a loss as to where to start.  Replacing the deprecated function/macros one at a time doesn't look feasible, since a lot of functionality is replaced by the same functions (push_dummy_code/push_dummy_call for example).  Is there a preferred way of doing it, or is it just a matter of diving right into it?  I'd prefer to do it in a structured way to be able to catch when things start to break.  I see there are a couple of targets that have made the transition (d10v and m68hc11 for example), so that should provide some help.

ia64, Arm, ... Some people are diving straight in, some are atacking the 
edges - updating any deprecated methods first.

Andrew



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

* Re: CRIS port; frame cleanup crash
  2003-08-12 17:36 ` Andrew Cagney
@ 2003-08-13 10:17   ` Orjan Friberg
  2004-02-12 18:59   ` Orjan Friberg
  1 sibling, 0 replies; 12+ messages in thread
From: Orjan Friberg @ 2003-08-13 10:17 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: gdb-patches

Andrew Cagney wrote:
> 
> Er, that points at a bug:
> 
> struct frame_info *
> deprecated_frame_xmalloc (void)
> {
>   struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
>   frame->this_id.p = 1;
>   return frame;
> }
> 
> shouldn't be allocated from the frame obstack pool.  I'll commit a fix.

Thanks a lot; it works fine now.

-- 
Orjan Friberg
Axis Communications



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

* Re: CRIS port; frame cleanup crash
  2003-08-12 17:36 ` Andrew Cagney
  2003-08-13 10:17   ` Orjan Friberg
@ 2004-02-12 18:59   ` Orjan Friberg
  2004-02-12 20:06     ` Andrew Cagney
  1 sibling, 1 reply; 12+ messages in thread
From: Orjan Friberg @ 2004-02-12 18:59 UTC (permalink / raw)
  To: gdb-patches

Ok, take two on trying to update the CRIS port to the new frame handling 
mechanism.  I'm planning to hook in the DWARF CFI frame unwinder, but I 
don't know if that affects any of the other stuff I'm going to have to 
do.  (I'm going to have to update to the new dummy stuff later, but I 
was hoping I could do that separately.)

Thanks in advance for any answers to questions, or comments on what I've 
understood or misunderstood amongst all of this (or even pointers to 
information I might have missed).

First of all, what does "unwind" mean in the frame context?  I know it 
sounds silly, but I've been trying unsuccessfully to wrap my head around 
that word.  Is there some fundamental thing I may have missed concerning 
the new frame handling, or can I just replace "unwind" with "dig out" in 
my head?

About the struct unwind_cache: looking at the other architectures, I'm 
still not sure what I need in this struct.  (I'm guessing stuff from the 
old struct frame_extra_info should go here if still needed.)  Is there a 
recommended starting point for this struct?  Some of the common members 
between architectures' unwind caches seem to be:

prev_sp: Most comments say "The previous frame's inner most stack 
address.  Used as this frame ID's stack_addr."  So would that be the 
what the stack pointer was when the current frame was entered?

base: Is this "base" as in "base for local variables" or does it refer 
to something else?  Most architectures seem to set this to the frame's 
frame pointer.

sp_offset and size I think I understand: how much the stack pointer has 
been changed so far in the frame, and how much stack space was allocated 
in this frame (absolute value of sp_offset) so far.


Thanks,
Orjan

-- 
Orjan Friberg
Axis Communications



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

* Re: CRIS port; frame cleanup crash
  2004-02-12 18:59   ` Orjan Friberg
@ 2004-02-12 20:06     ` Andrew Cagney
  2004-02-14 13:38       ` Orjan Friberg
  0 siblings, 1 reply; 12+ messages in thread
From: Andrew Cagney @ 2004-02-12 20:06 UTC (permalink / raw)
  To: Orjan Friberg; +Cc: gdb-patches

> Ok, take two on trying to update the CRIS port to the new frame handling mechanism.  I'm planning to hook in the DWARF CFI frame unwinder, but I don't know if that affects any of the other stuff I'm going to have to do.  (I'm going to have to update to the new dummy stuff later, but I was hoping I could do that separately.)

CRIS is already using generic dummy frames so it should be in good 
shape.  The only potential got-ya is with unwind_dummy_id - you'll need 
to check that the correct ID is returned.

> Thanks in advance for any answers to questions, or comments on what I've understood or misunderstood amongst all of this (or even pointers to information I might have missed).
> 
> First of all, what does "unwind" mean in the frame context?  I know it sounds silly, but I've been trying unsuccessfully to wrap my head around that word.  Is there some fundamental thing I may have missed concerning the new frame handling, or can I just replace "unwind" with "dig out" in my head?

The term "unwind" is used by the dwarf-2 specification. 
http://www.eagercon.com/dwarf/dwarf3std.htm
it includes a working example in the appendix.

The important thing is to "dig out" the register from the correct frame. 
  frame_unwind_register (next_frame, "pc") will "dig out" the PC from 
the next frame (often found in next frame's link register) returning the 
value as it should be in "this_frame".

> About the struct unwind_cache: looking at the other architectures, I'm still not sure what I need in this struct.  (I'm guessing stuff from the old struct frame_extra_info should go here if still needed.)  Is there a recommended starting point for this struct?  Some of the common members between architectures' unwind caches seem to be:

Yes, frame_extra_info is a very good starting point.  "init_saved_regs" 
is also a very a good starting point for the new cache init code.

> prev_sp: Most comments say "The previous frame's inner most stack address.  Used as this frame ID's stack_addr."  So would that be the what the stack pointer was when the current frame was entered?

Probably :-(

The i386 call instruction adjusts the SP leading to:
   /* Now that we have the base address for the stack frame we can
      calculate the value of %esp in the calling frame.  */
   cache->saved_sp = cache->base + 8;

> base: Is this "base" as in "base for local variables" or does it refer to something else?  Most architectures seem to set this to the frame's frame pointer.

Thats correct.

> sp_offset and size I think I understand: how much the stack pointer has been changed so far in the frame, and how much stack space was allocated in this frame (absolute value of sp_offset) so far.

that's correct

Also:
    struct trad_frame_saved_reg *saved_regs;
(from mips et.al.) which can help simplify the implementation of 
register unwind.

Andrew



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

* Re: CRIS port; frame cleanup crash
  2004-02-12 20:06     ` Andrew Cagney
@ 2004-02-14 13:38       ` Orjan Friberg
  2004-02-14 14:52         ` Andrew Cagney
  0 siblings, 1 reply; 12+ messages in thread
From: Orjan Friberg @ 2004-02-14 13:38 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: gdb-patches

Andrew Cagney wrote:
> 
> The term "unwind" is used by the dwarf-2 specification. 
> http://www.eagercon.com/dwarf/dwarf3std.htm
> it includes a working example in the appendix.

Excellent, thanks a lot.  Section 6.4 regarding Call Frame Information 
cleared up some of the confusion regarding unwinding.

> The important thing is to "dig out" the register from the correct frame. 
>  frame_unwind_register (next_frame, "pc") will "dig out" the PC from the 
> next frame (often found in next frame's link register) returning the 
> value as it should be in "this_frame".

This explanation has me slightly puzzled.  I gather from the code that 
"PC" refers to the current program location within a frame, and not an 
actual CPU register.  Is "next" synonymous with "outer" in your 
explanation above?  (Perhaps a stupid question; maybe unwind by 
definition works on the outer frame/caller.)  And "link register" I 
assume is the equivalent of a subroutine return pointer.

Approaching it from another direction, what would be a good test to see 
if the unwind code works correctly?  At present, step (into function 
calls), next (over function calls), finish, and backtrace seem to work 
ok for both leaf- and non-leaf-functions (for CRIS the prologue differs 
slightly as the SRP isn't pushed in case of a leaf function).  Is there 
any particular existing testcase that would be good at detecting errors 
in the frame code?

Another question: should I hook in the dwarf-2 frame sniffer from the 
very beginning?  Or wait until the other stuff seems to be working ok?

Thanks,
Orjan

-- 
Orjan Friberg
Axis Communications



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

* Re: CRIS port; frame cleanup crash
  2004-02-14 13:38       ` Orjan Friberg
@ 2004-02-14 14:52         ` Andrew Cagney
  2004-02-15 17:41           ` Orjan Friberg
  2004-02-16 18:19           ` Orjan Friberg
  0 siblings, 2 replies; 12+ messages in thread
From: Andrew Cagney @ 2004-02-14 14:52 UTC (permalink / raw)
  To: Orjan Friberg; +Cc: gdb-patches, Michael Elizabeth Chastain, Joel Brobecker

[Joel, MichaelC, FYI]

> Andrew Cagney wrote:
> 
>> The term "unwind" is used by the dwarf-2 specification. http://www.eagercon.com/dwarf/dwarf3std.htm
>> it includes a working example in the appendix.

> 
> Excellent, thanks a lot.  Section 6.4 regarding Call Frame Information cleared up some of the confusion regarding unwinding.



>> The important thing is to "dig out" the register from the correct frame.  frame_unwind_register (next_frame, "pc") will "dig out" the PC from the next frame (often found in next frame's link register) returning the value as it should be in "this_frame".

> 
> This explanation has me slightly puzzled.  I gather from the code that "PC" refers to the current program location within a frame, and not an actual CPU register.  Is "next" synonymous with "outer" in your explanation above?  (Perhaps a stupid question; maybe unwind by definition works on the outer frame/caller.)  And "link register" I assume is the equivalent of a subroutine return pointer.

Yes, "pc" is a misnomer, within GDB it doesn't mean the "pc register", 
"resume address" is closer.  Check the comments in frame.c:struct 
frame_info for definitions of: "next", "inner", "newer" and separatly 
"prev", "outer", "older".  Yes, link register is the return address 
register.

This frame (the caller) calls next frame (the callee).  As part of that 
the callers resume addresses ends up in the callee's return-address 
register.  The callee (next) then saves the return-address register on 
the stack.  Hence to get the callers (this) PC, it needs to be dug out 
of the callers (next) frame's stack.  Anyway, sounds like you've got it 
right.

> Approaching it from another direction, what would be a good test to see if the unwind code works correctly?  At present, step (into function calls), next (over function calls), finish, and backtrace seem to work ok for both leaf- and non-leaf-functions (for CRIS the prologue differs slightly as the SRP isn't pushed in case of a leaf function).  Is there any particular existing testcase that would be good at detecting errors in the frame code?

Exactly that.

Also "advance.exp", in particular the sequence:

./gdb advance
(gdb) break func
(gdb) run
(gdb) advance func3
--- should break in main and not func3

is a good check of the frame ID.

And callfuncs.exp, and a sequence like:

./gdb callfuncs
(gdb) break add
(gdb) break main
(gdb) run
(gdb) print add(1,2)
(gdb) bt
(gdb) print add(3,4)
(gdb) bt
add(3,4)
<dummy frame>
add (1,2)
<dummy frame>
main ()
(gdb)

is a good check of dummy frames

> Another question: should I hook in the dwarf-2 frame sniffer from the very beginning?  Or wait until the other stuff seems to be working ok?

Towards the end.  It's good to first get the old code working reasonably 
well.

Andrew



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

* Re: CRIS port; frame cleanup crash
  2004-02-14 14:52         ` Andrew Cagney
@ 2004-02-15 17:41           ` Orjan Friberg
  2004-02-16 18:19           ` Orjan Friberg
  1 sibling, 0 replies; 12+ messages in thread
From: Orjan Friberg @ 2004-02-15 17:41 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: gdb-patches

Andrew Cagney wrote:
> 
> This frame (the caller) calls next frame (the callee).  As part of that 
> the callers resume addresses ends up in the callee's return-address 
> register.  The callee (next) then saves the return-address register on 
> the stack.  Hence to get the callers (this) PC, it needs to be dug out 
> of the callers (next) frame's stack.  Anyway, sounds like you've got it 
> right.

Thanks a lot for the clarification.  I think I'm less confused now.

> Also "advance.exp", in particular the sequence:
> 
> ./gdb advance
> (gdb) break func
> (gdb) run
> (gdb) advance func3
> --- should break in main and not func3
> 
> is a good check of the frame ID.

Thanks for the tip.  Running advance.exp results in all PASS.  (When 
issuing the command sequence above manually on the CRIS target and 
comparing with my Linux host, I end up at different locations in main 
(at marker1() and func (c), respectively), but advance.exp seems to 
indicate that either is ok.)  So, at least it's not completely broken.

I'll get to callfuncs.exp next for the dummy frames implementation.

Thanks,
Orjan

-- 
Orjan Friberg
Axis Communications



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

* Re: CRIS port; frame cleanup crash
  2004-02-14 14:52         ` Andrew Cagney
  2004-02-15 17:41           ` Orjan Friberg
@ 2004-02-16 18:19           ` Orjan Friberg
  2004-02-16 18:43             ` Andrew Cagney
  1 sibling, 1 reply; 12+ messages in thread
From: Orjan Friberg @ 2004-02-16 18:19 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Cagney

Andrew Cagney wrote:
> 
> And callfuncs.exp, and a sequence like:
> 
> ./gdb callfuncs
> (gdb) break add
> (gdb) break main
> (gdb) run
> (gdb) print add(1,2)
> (gdb) bt
> (gdb) print add(3,4)
> (gdb) bt
> add(3,4)
> <dummy frame>
> add (1,2)
> <dummy frame>
> main ()
> (gdb)
> 
> is a good check of dummy frames

Ok, backtrace doesn't work at all.  (find_dummy_frame() isn't able to 
locate the dummy frame because fp doesn't match dummyframe->top.)  A 
couple of questions regarding this:

frame_align(): this function is only concerned with architecture issues, 
and not ABI issues, right?  What I mean is that we're not mimicking 
anything the compiler would do the way we do when we set up arguments 
for a function call.  If the architecture has no alignment restrictions 
on the stack, then we shouldn't have to do any stack alignment, although 
the compiler might align it for performance reasons.

push_dummy_call(): the CRIS code allocates more space on the stack than 
is actually needed; is this going to cause me problems?  Since, as I 
understand it, the SP returned from push_dummy_call() must match the SP 
unwound when unwinding the dummy id I'm thinking I'll either have to get 
rid of the over-allocation on the stack (preferred) or compensate for it 
when unwinding the dummy id.  Is this correct?

FWIW, everything up to and including the cmp10(...) test in 
callfuncs.exp works, so at least the argument setup seems ok.

Thanks,
Orjan

-- 
Orjan Friberg
Axis Communications



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

* Re: CRIS port; frame cleanup crash
  2004-02-16 18:19           ` Orjan Friberg
@ 2004-02-16 18:43             ` Andrew Cagney
  2004-02-18 17:06               ` Orjan Friberg
  0 siblings, 1 reply; 12+ messages in thread
From: Andrew Cagney @ 2004-02-16 18:43 UTC (permalink / raw)
  To: Orjan Friberg; +Cc: gdb-patches

> Andrew Cagney wrote:
> 
> And callfuncs.exp, and a sequence like:
> 
> ./gdb callfuncs
> (gdb) break add
> (gdb) break main
> (gdb) run
> (gdb) print add(1,2)
> (gdb) bt
> (gdb) print add(3,4)
> (gdb) bt
> add(3,4)
> <dummy frame>
> add (1,2)
> <dummy frame>
> main ()
> (gdb)
> 
> is a good check of dummy frames
> 
> Ok, backtrace doesn't work at all.  (find_dummy_frame() isn't able to locate the dummy frame because fp doesn't match dummyframe->top.)  A couple of questions regarding this:

Ok, you've tripped over a bit of screwed up GDB history.  'till the 
frame rewrite the choice of dummyframe->top was very arbitrary cf:

           /* An older target that hasn't explicitly or implicitly
              saved the dummy frame's top-of-stack.  Try matching the
              FP against the saved SP and FP.  NOTE: If you're trying
              to fix a problem with GDB not correctly finding a dummy
              frame, check the comments that go with FRAME_ALIGN() and
              UNWIND_DUMMY_ID().  */

> frame_align(): this function is only concerned with architecture issues, and not ABI issues, right?  What I mean is that we're not mimicking anything the compiler would do the way we do when we set up arguments for a function call.  If the architecture has no alignment restrictions on the stack, then we shouldn't have to do any stack alignment, although the compiler might align it for performance reasons.

It's more an ABI issue.

Frame alighment is oftem more strict than ISA alignment.  For instance, 
a 32-bit machine may require 4-byte alignment, but the ABI might specify 
that a stack must be 8 or even 16-byte aligned when entering a function.

> push_dummy_call(): the CRIS code allocates more space on the stack than is actually needed; is this going to cause me problems?  Since, as I understand it, the SP returned from push_dummy_call() must match the SP unwound when unwinding the dummy id I'm thinking I'll either have to get rid of the over-allocation on the stack (preferred) or compensate for it when unwinding the dummy id.  Is this correct?

That is correct.

       /* Sanity.  The exact same SP value is returned by
          PUSH_DUMMY_CALL, saved as the dummy-frame TOS, and used by
          unwind_dummy_id to form the frame ID's stack address.  */

As for which of the two choices is prefered, which ever makes your life 
easier.

> FWIW, everything up to and including the cmp10(...) test in callfuncs.exp works, so at least the argument setup seems ok.

ya!

Andrew



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

* Re: CRIS port; frame cleanup crash
  2004-02-16 18:43             ` Andrew Cagney
@ 2004-02-18 17:06               ` Orjan Friberg
  0 siblings, 0 replies; 12+ messages in thread
From: Orjan Friberg @ 2004-02-18 17:06 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: gdb-patches

Andrew Cagney wrote:
>> FWIW, everything up to and including the cmp10(...) test in 
>> callfuncs.exp works, so at least the argument setup seems ok.
> 
> 
> ya!

... and it gets even better!  Running advance.exp, callfuncs.exp, 
finish.exp, funcargs.exp, restore.exp, scope.exp, and store.exp now 
results in:

# of expected passes            731
# of unsupported tests          1

structs.exp still gives me 30+ FAILs, but OTOH I haven't implemented a 
return_value yet (still using store/extract_return_value and 
use_struct_convention).

There's still some cleaning up to do before I submit a patch, but it 
does looks promising.  Andrew, thanks for all your help.

-- 
Orjan Friberg
Axis Communications



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

end of thread, other threads:[~2004-02-18 17:06 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-08-11 13:30 CRIS port; frame cleanup crash Orjan Friberg
2003-08-12 15:11 ` Orjan Friberg
2003-08-12 17:36 ` Andrew Cagney
2003-08-13 10:17   ` Orjan Friberg
2004-02-12 18:59   ` Orjan Friberg
2004-02-12 20:06     ` Andrew Cagney
2004-02-14 13:38       ` Orjan Friberg
2004-02-14 14:52         ` Andrew Cagney
2004-02-15 17:41           ` Orjan Friberg
2004-02-16 18:19           ` Orjan Friberg
2004-02-16 18:43             ` Andrew Cagney
2004-02-18 17:06               ` Orjan Friberg

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