This is the mail archive of the gdb@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Frame unwind functions


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 at suse dot cz
* (+420) 296.545.373 * http://www.suse.cz


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]