[lldb-dev] Make a StackFrame return immediately

Filipe Cabecinhas filcab+lldb-dev at gmail.com
Fri Jul 22 15:46:56 PDT 2011

On Fri, Jul 22, 2011 at 15:18, Jim Ingham <jingham at apple.com> wrote:

> Filipe,
> Thanks for working on this.
> Note, gdb's "return" command doesn't do anything to attempt to clean up
> local objects.  It just pops the frames off the stack & returns the value.
>  This, like moving the PC by hand, is one of those commands that you just
> shouldn't use if you don't know what could go wrong...  Anyway, people
> mostly use this to hack system routines to do something else, in which case
> you stop at the very beginning and return directly - you haven't gotten far
> enough to need to do any cleanup.
> Seems to me that the sensible thing to do about the return expression is
> take whatever the user gives you and cast it to the return type of the
> function you are returning from, if you know it.  If you don't then just
> write it as whatever they have given you, and the user will have to get it
> right when they write the expression.  That's the best you can do in this
> case.


> It also seems to me that much more of this could be generic.  The algorithm
> gdb uses is to get the register context one frame up on the stack, and write
> that to the real registers, and then throw away the cached stack and remake
> it from the changed registers.  That can all be done generically.  Mind
> there are target specific bits but they are all hidden under the register
> code.  It is the unwinder's job to know what the register state of the
> functions up on the stack are, you should rely on that.
> The only ABI specific bit is that you need to ask the ABI where to store
> the return value.  For things smaller than a register that is easy.  For
> struct returns it can be hard, because the compiler usually passes in a
> pointer to the save location, but you would have to track the history of
> that value to know where it is stored at the point you are trying to return
> from, and that's not trivial.  Again, if you are at the beginning of the
> function you're returning from, this is easy to do.

Ok. You're suggesting taking the code out of the ABI and putting it on the
command (or maybe the StackFrame)? I initially wrote the code thinking
calling conventions could vary a lot but, for the returns, they don't vary
that much (and lldb allows us to abstract most of what varies). Or would it
be preferred to just contain the code in the command object?

I suppose the command should also be changed to the "frame" command, to
mimic gdb (it returns from the current frame, not the bottom-most).

> You can also check whether the block you are in is inlined, and if it is,
> then all you do is move the PC to the end of the block.  You can't really do
> anything about the return value then, because you can't really tell where it
> is going, but at least you can return properly from the inlined function.
> Hope that helps...
I will try that one too, thanks.



> Jim
> On Jul 22, 2011, at 12:35 PM, Filipe Cabecinhas wrote:
> >
> >
> > On Mon, Jul 18, 2011 at 18:05, Greg Clayton <gclayton at apple.com> wrote:
> > On Jul 18, 2011, at 5:23 PM, Filipe Cabecinhas wrote:
> >
> > > Hi,
> > >
> > > Is there a way to mimic gdb's "return <expr>" command?
> >
> > Not if you want to change the return value.
> >
> > If you don't want to change the return value you can use "thread
> step-out". "thread step-out" (which is aliased to "finish"), is context
> sensitive to the frame you are currently in, so if you run and stop in a
> frame and then do a "frame select 12", and then to a "thread step-out", you
> will return to frame 13.
> >
> > Yes, that command will run until the frame returns (like gdb's finish
> command), but what if we want to return immediately?
> >
> > > (gdb) help return
> > > Make selected stack frame return to its caller.
> > > Control remains in the debugger, but when you continue
> > > execution will resume in the frame above the one now selected.
> > > If an argument is given, it is an expression for the value to return.
> > >
> > >
> > > I've been looking at the StackFrame class, but it doesn't look like it
> can do that.
> > > If I wanted to implement it, where should I look first? I can get the
> return address (StackFrame.GetRegisterContext().get().GetReturnAddress(), I
> think) write it to the PC (StackFrame.ChangePC()), but I have no idea how to
> get the expression's result into the return registers/memory.
> >
> > LLDB currently doesn't have any real idea of where the return address
> goes, we currently let the compiler handle all ABI issues by the way we make
> expressions.
> >
> > There is another issue where if a function isn't external, the compiler
> can make a call to this function and how the function returns the value,
> violate the ABI. In most cases you won't get affected by this, but it would
> be nice if we knew for sure from the compiler or debug info where the return
> value is. The old ARM compiler used to inject artificial DW_TAG_variable
> debug information entries into the DWARF that would tell you the result of
> functions which has a location that describes the returned value and where
> it is.
> >
> >
> > > ClangExpression isn't a big help there, since the result comes to
> debugger-land.
> >
> > Yep, and even so there is the issue that internal functions can violate
> the ABI...
> >
> > FYI: anything ABI related is currently in the ABI plug-ins:
> >
> > lldb/source/Plugins/ABI/*
> >
> > The ABI function:
> >
> >    virtual bool
> >    ABI::GetReturnValue (Thread &thread,
> >                         Value &value) const = 0;
> >
> > Take a look a the ABIMacOSX_i386 and ABIMacOSX_x86_64 versions of this
> function and see if this does close to what you want. You can also fill in
> more functionality inside these for types you want it to support. Currently
> we fill the "value" argument with the result, but we don't fill in the
> context (See the "void Value::SetContext (ContextType context_type, void
> *p)" function for details, but the  ABI::GetReturnValue functions can be
> modified to fill in the register context for return values that are returned
> in registers, and the address (See the "Value::SetValueType (...)" function)
> if needed.
> >
> > These functions currently will attempt to extract the return value for a
> function according to the ABI rules for simple pointer size or less types
> only (no structs, floats, complex etc). So this might help you for the
> simple cases. If you were to implement this command you would want to add a
> new "return" subcommand in the "thread" multi-word command. In the "Execute"
> function of the new "return" command you would want to evaluate an
> expression an store the result, set a breakpoint at the return address,
> install a breakpoint callback and run and hit the breakpoint, then try and
> instert the expression result into the appropriate location (you would need
> to modify the "ABI::GetReturnValue(...)" to fill in the "value" param more
> completely with the location of the return type.
> >
> > Greg Clayton
> >
> >
> > I implemented a thread return command, which works (right now) for
> integers and pointers, for i386 and x86-64. The command has some caveats
> (like the ones discussed here), but it works (at least) for a few simple
> examples in C.
> >
> > "thread return <expr>" returns the result of evaluating that expression.
> I'm not casting the expression, so there may be some problems (especially
> when returning floating point types is implemented).
> >
> > But…
> > We have no idea if the compiler generated a stackframe for this function
> or not. We may be returning from two functions, and not one.
> > We have no ideia if the compiler changed the calling conventions for this
> code.
> > We don't know about the callee-saved registers (I suppose there isn't a
> way to find out the epilogue of the function… Especially since it may be
> mixed with "regular code")
> >
> > There are a lot more issues for C++ code (e.g: calling dtors).
> >
> > I also have some problems updating the state lldb thinks the thread is
> in.
> >
> > "register read pc" won't read the real value
> > "thread backtrace" doesn't get updated.
> >
> > How can I fix that? I am also looking for comments on stuff to
> fix/improve.
> >
> > I also have some tests (a directory to put in lldb/test/).
> >
> > Regards,
> >
> >   Filipe Cabecinhas
> >
> > P.S: Converting between a ValueObject object and
> >
> <thread-return.patch><thread_return.zip>_______________________________________________
> > lldb-dev mailing list
> > lldb-dev at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20110722/678e5eb6/attachment.html>

More information about the lldb-dev mailing list