Mirror of the gdb mailing list
 help / color / mirror / Atom feed
From: Michal Ludvig <mludvig@suse.cz>
To: GDB list <gdb@sources.redhat.com>, Andrew Cagney <ac131313@redhat.com>
Subject: Frame unwind functions
Date: Tue, 11 Mar 2003 18:35:00 -0000	[thread overview]
Message-ID: <3E6E2C79.5050409@suse.cz> (raw)

Hi all,
since there are different unwind mechanisms in different branches of GDB 
I got a bit lost. I need to sort my thoughts to understand the principles.

First my view of how things now work:

A) One pass to get frame-id:
- process hits a breakpoint and GDB takes control of it.
- it can get values of all registers by simply reading them, and is
   especially interested in PC (%eip on i386) and SP (%esp).
- GDB can somehow determine the frame address FP (ie. top of the stack),
   either by taking it from %ebp on i386 or by CFI unwinding of SP.
- PC and FP together makes a Frame-ID of the innermost frame.
   (Or is frame-id something else?)

B) Now how to do a backtrace:
- first call to get_prev_frame() passes as an argument a pre-filled
   struct frame_info as the 'next_frame' parameter. It only has
   next_frame->pc filled with current PC (%eip), next_frame->unwind
   pointing to sentinel unwinder and a level==-1, which describes
   a sentinel frame.
- GDB creates an empty prev_frame, and sets its level.
- to get current PC we call next_frame->unwind->pc(). In the case of a
   sentinel frame it just reads a PC register from the inferior.
- How to get current FP depends of type of the current frame
   (ie. prev_frame).
   - on i386 we read it from FP register (%ebp)
   - in a CFI frame we read the value of the SP register (by calling
     unwind->reg(SP_REGNUM) for the next_frame, which is a sentinel one,
     ie. we read the SP register directly) and unwind it to get it's
     value at the beginning of the function.
- PC and FP together make up frame id.

C) All subsequent calls to get_prev_frame() always pass next_frame as 
the parameter and:
- Create prev_frame with appropriate level.
- Get current PC in this frame by calling next_frame->unwind->pc()
   - in the case of the normal i386 frame it reads a return address from
     the stack where next_frame->frame points to (plus sizeof(PC)).
   - in the case of CFI frames we must ask the CFI engine to give us the
     return address of the next_frame.
   - if next_frame is a sigtramp frame, PC is read from the saved
     sigcontext on the stack.
- Get FP for this frame
   - in the case of the normal i386 frame it reads the saved %ebp at the
     address of next_frame->frame.
   - in the case of CFI frames we must obtain the SP first. This is
     basically next_frame->frame value (perhaps adjusted by an offset).
     Now we ask the engine to give us the value of SP at the time the
     function was entered, i.e. we must unwind it. This way we get FP.
   - If next_frame is a sigtramp, SP (or FP) is read from the stack
     similarly to PC.
- PC and FP together make up frame id.

So far so good, I hope. Or did I miss something?

But how about registers and parameters?
- In the innermost frame I know the values of all registers.
- By using a CFI engine I could unwind some of them to the state they've
   had when the frame was entered - do I save these values somewhere or
   are they generated on-the-fly when the given frame's unwind_reg() is
   called?
- In the backtrace the function's arguments are printed as well.
   - on i386 it's not a problem since they are on the stack
   - on x86-64 we pass some of them in registers
     - that's fine for the first frame (#0) - I know all registers and I
       can use location lists to find current position of a given arg.
     - for the second frame (#1) I could call
       next_frame->unwind->reg(regnum) to get the register I need and
       unwind it even more by calling this_frame->unwind->reg(regnum) to
       get it's value at the beginning of the frame.
     - but how about the next frames (#2,...)? I can always call
       next_frame->unwind->reg(regnum) and if the next_frame wouldn't
       know its "initial" value (ie. the value at the place of PC) it
       would recursively call next_frame->next_frame->unwind->register()
       untill it get's the value.
This is not desired I think. If I understand the MarkK's code from 
i386newframe branch he saves all known register's positions (stack 
addresses) to frame->unwind_cache (casted to struct i386_frame_cache). 
But it isn't a generic approach. Should all these registers be somehow 
written to the regcache instead? Or to frame->saved_regs? If so, then 
when and where? I think CFI uses it's own frame->context structure for 
this purpose, but I'd like to avoid using it for non-cfi frames.

If I would have all registers saved in each next_frame then I could only 
call next_frame->unwind->reg(regnum) and get the current value. Then 
store it somewhere in this_frame and use as if I just read it from the 
inferior. I believe there is something similar already implemented in 
the GDB but I don't know how. Could someone explain me this thing, please?

Well, long mail, isn't it? But I would like to know if I understand 
correctly what the new frame unwinding stuff does or if I'm missing 
something important.

Thanks for your time,

Michal Ludvig
-- 
* SuSE CR, s.r.o     * mludvig@suse.cz
* (+420) 296.545.373 * http://www.suse.cz


             reply	other threads:[~2003-03-11 18:35 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-03-11 18:35 Michal Ludvig [this message]
2003-03-11 22:04 ` Andrew Cagney
2003-03-12  8:11   ` Michal Ludvig
2003-03-12 15:15     ` Andrew Cagney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3E6E2C79.5050409@suse.cz \
    --to=mludvig@suse.cz \
    --cc=ac131313@redhat.com \
    --cc=gdb@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox