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]

Re: IBM S/390 prologue analysis revisited


Andrew Cagney <ac131313@redhat.com> writes:

> > You mean: [just for the record]: new prologue analyzer for S/390
> > http://sources.redhat.com/ml/gdb-patches/2003-04/msg00352.html
> 
> One PS,
> 
> Since this was posted (but you'd declined to commit) I added
> trad-frame.[hc].  This provides functionality that overlaps what is
> found in the s390 patch (it's slightly more compact).
> 
> > /* A traditional saved regs table, indexed by REGNUM, encoding where
> >    the value of REGNUM for the previous frame can be found in this
> >    frame.
> >    The table is initialized with an identity encoding (ADDR == -1,
> >    REALREG == REGNUM) indicating that the value of REGNUM in the
> >    previous frame can be found in register REGNUM (== REALREG) in this
> >    frame.
> >    The initial encoding can then be changed:
> >    Modify ADDR (REALREG >= 0, ADDR != -1) to indicate that the value
> >    of register REGNUM in the previous frame can be found in memory at
> >    ADDR in this frame (addr_p, !realreg_p, !value_p).
> >    Modify REALREG (REALREG >= 0, ADDR == -1) to indicate that the
> >    value of register REGNUM in the previous frame is found in register
> >    REALREG in this frame (!addr_p, realreg_p, !value_p).
> >    Call trad_frame_register_value (REALREG == -1) to indicate that
> > the
> >    value of register REGNUM in the previous frame is found in ADDR
> >    (!addr_p, !realreg_p, value_p).  */
> 
> Editor note: It's missing the undefined state.  I'll add it.

I'd say that 'struct trad_frame_saved_reg' and 'struct prologue_value'
are inverses of each other.  They represent information at different
steps in the process:
- First you interpret your prologue to get a bunch of prologue values.
- Then you use those to compute a set of trad_frame_saved_reg values.
- Finally, those are what you'd use to find registers.

Let me explain what I mean.

The S/390 prologue analyzer creates a table of registers' current
values, expressed as simple expressions:
  - "unknown",
  - "the constant K", or
  - "the original value of register R plus the constant K"

To build this info, you just "interpret" the prologue, starting at the
entry point, using prologue values instead of actual integers.  Here's
the code for the S/390 "add register" instruction when it appears in a
prologue:

      ...
      /* AR r1, r2 -- add register */
      else if (is_rr (insn, op_ar, &r1, &r2))
        pv_add (&gpr[r1], &gpr[r1], &gpr[r2]);
      ...

That is, you just "add" the current values of r1 and r2, and store the
"result" in r1.  (The "pv_*" functions do addition, subtraction,
etc. on prologue values, returning "unknown" whenever the answer can't
be expressed in one of the forms above.)  When you stop, you've got
the information you need to unwind: a description of the machine's
resultant state after running the prologue.

So, suppose your prologue moves the SP into the FP, and then subtracts
100 from the SP.  In that case, the S/390 prologue analyzer will end
up with the following "values" in those registers:

  SP: "the original value of SP plus the constant -100"
  FP: "the original value of SP plus the constant 0"

Given this it's easy to find the original SP, the frame size, and so
on.

But here's what's cool: suppose your prologue is actually:
- save the SP in the FP
- move the constant "-100" into register R4
- subtract R4 from SP

That extra step, going through register R4, would break a traditional
prologue analyzer, even though it's equivalent to the original
sequence (as far as SP and FP are concerned), unless you add special
code to recognize that maneuver.  But the S/390 prologue analyzer
handles this just fine, with no special cases, producing a final state
of:

  R4: "the constant -100"
  SP: "the original value of SP plus the constant -100"
  FP: "the original value of SP plus the constant 0"

So you still get the information you wanted.

This is the point where trad_frame_saved_reg comes in: that final
state information there is not exactly what you need for register
unwinding.  To find the original SP, say, you need to search the
register set for a register whose current value is "the original value
of SP plus the constant Q".  In the above case, we could recover the
original SP from either the current SP or the current FP.  (The FP is
a little easier, but if you make sure you can handle either case, then
you've got support for FP-less functions, too.)  But if you simply
make a pass over the entire register set, and record where one can
find the original values of registers, then you've produced a complete
set of 'struct trad_frame_saved_reg' values in one pass.

So as things stand, prologue values and trad_frame_saved_reg
structures are inverses of each other: they play different roles.  A
trad_frame_saved_reg points to one of the values your prologue
"interpreter" tracks: a register, stack slot, or whatever.


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