[lldb-dev] Unwinding call frames with separated data and return address stacks

Thomas Goodfellow via lldb-dev lldb-dev at lists.llvm.org
Tue Mar 5 00:09:12 PST 2019

Hi Jason

Thanks for the advice - I've been surprised overall how capable DWARF
expressions are so wouldn't have been surprised to learn that there is
also a category of pseudo-variables (not that I can think of any
others, or other circumstances where it would be useful: the usual
combined code/data stack is ubiquitous). The RestoreType suggestion is
interesting as it might be a less-intrusive change.


On Mon, 4 Mar 2019 at 22:05, Jason Molenda <jmolenda at apple.com> wrote:
> Hi Tom, interesting problem you're working on there.
> I'm not sure any of the DWARF expression operators would work here.  You want to have an expression that works for a given frame, saying "to find the caller's pc value, look at the saved-pc stack, third entry from the bottom of that stack."  But that would require generating a different DWARF expression for the frame each time it shows up in a backtrace - which is unlike lldb's normal design of having an UnwindPlan for a function which is computed once and reused for the duration of the debug session.
> I supposed you could add a user-defined DW_OP which means "get the current stack frame number" and then have your expression deref the emulated saved-pc stack to get the value?
> lldb uses an intermediate representation of unwind information (UnwindPlan) which will use a DWARF expression, but you could also add an entry to UnwindPlan::Row::RegisterLocation::RestoreType which handled this, I suppose.
> > On Mar 4, 2019, at 2:46 AM, Thomas Goodfellow via lldb-dev <lldb-dev at lists.llvm.org> wrote:
> >
> > I'm adding LLDB support for an unconventional platform which uses two
> > stacks: one purely for return addresses and another for frame context
> > (spilled registers, local variables, etc). There is no explicit link
> > between the two stacks, i.e. the frame context doesn't include any
> > pointer or index to identify the return address: the epilog for a
> > subroutine amounts to unwinding the frame context then finally popping
> > the top return address from the return stack. It has some resemblance
> > to the Intel CET scheme of shadow stacks, but without the primary
> > stack having a copy of the return address.
> >
> > I can extend the emulation of the platform to better support LLDB. For
> > example while the real hardware platform provides no access to the
> > return address stack the emulation can expose it in the memory map,
> > provide an additional debug register for querying it, etc, which DWARF
> > expressions could then extract return addresses from. However doing
> > this seems to require knowing the frame number and I haven't found a
> > way of doing this (a pseudo-register manipulated by DWARF expressions
> > worked but needed some LLDB hacks to sneak it through the existing
> > link register handling, also seemed likely to be unstable against LLDB
> > implementation changes)
> >
> > Is there a way to access the call frame number (or a reliable proxy)
> > from a DWARF expression? Or an existing example of unwinding a shadow
> > stack?
> >
> > Thanks,
> > Tom
> > _______________________________________________
> > lldb-dev mailing list
> > lldb-dev at lists.llvm.org
> > https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

More information about the lldb-dev mailing list