[lldb-dev] Make a StackFrame return immediately

Filipe Cabecinhas filcab+lldb-dev at gmail.com
Fri Jul 29 14:10:13 PDT 2011


Hi,

Is it normal for these two threads to differ?

exe_ctx = m_interpreter.GetExecutionContext();

*
*

*exe_ctx.thread: 0x107900610,
exe_ctx.process->GetThreadList().GetSelectedThread(): 0x0*

Also, if we only have one thread, shouldn't that thread always be selected?
Somehow the ThreadList.m_selected_thread is being set to
LLDB_INVALID_THREADID right after I run my command.

Regards,

  Filipe

On Wed, Jul 27, 2011 at 10:27, Filipe Cabecinhas
<filcab+lldb-dev at gmail.com>wrote:

> Hi,
>
> I did that, and tried watching the thread list, to see when it changed…
> Couldn't find anything. I'll continue searching the code and debugging to
> see where the selected thread may be changing. Or is it something that
> shouldn't happen?
>
> I will also try this with a Cocoa program, to check the objective-c returns
> and if having more threads change anything.
>
> Regards,
>
>   Filipe Cabecinhas
>
>
> On Tue, Jul 26, 2011 at 17:36, Enrico Granata <egranata at apple.com> wrote:
>
>> Hi Filipe,
>> thanks for all the hard work you are doing on LLDB.
>>
>> While I have not really delved into your patch, I think a good way to find
>> out why you get this persistent error on stepping-over after your new
>> command would be to set a breakpoint in
>> CommandObjectThreadStepWithTypeAndScope::Execute
>>
>> The way I usually do this is creating an instance of LLDB debugging my
>> inferior process (a test program in your case), and then in another Terminal
>> window, opening a second LLDB and attaching it to the first instance (you
>> can use the process attach -p command to do so).
>> Then start to play with the first LLDB, and when you get to the point
>> where you would type thread step-over and get in trouble, just set a
>> breakpoint into the CommandObjectThreadStepWithTypeAndScope::Execute call
>> in the second LLDB instance.
>>
>> Now, you can step through the command's code and check where it's failing
>> exactly (and hopefully figure out why).
>>
>> Sincerely,
>>  *Enrico Granata*
>> ✆ 408.974.5572 | ✉ egranata@.com
>>
>> On Jul 26, 2011, at 5:29 PM, Filipe Cabecinhas wrote:
>>
>> Hi all,
>>
>> Multi-level returns were not working as intended, as I would write to the
>> frame's RegisterContext (yielding an error), instead of writing to the live
>> RegisterContext. I have fixed that and created another test-case for it.
>>
>> I still have the problem of not rebuilding the StackFrameList, and the
>> first "thread step-over" command right after a "frame return" is yielding an
>> error. Subsequent commands work fine.
>>
>> Regards,
>>
>>   Filipe
>>
>> On Mon, Jul 25, 2011 at 15:08, Filipe Cabecinhas <
>> filcab+lldb-dev at gmail.com> wrote:
>>
>>> Hi all,
>>>
>>> I've refactored the code to put most of the work on the StackFrameList
>>> class, but I still have one problem:
>>> The state of execution isn't being updated.
>>>
>>> - If I try to print the pc register after returning, it will just give me
>>> the old value (still in the function).
>>> - The first thread step-over command after returning from a function
>>> isn't working, too. But that may have to do with:
>>> - I can't update the stackframe list. thread backtrace always puts me
>>> inside the function.
>>>
>>> These three problems may be interconnected. I'll try to debug further.
>>>
>>>  I also can't do what Jim suggested. I got the Block reference, from the
>>> frame. I can see if it's inlined and its size, but can't tell where it
>>> starts/ends.
>>>
>>> I'll send two patches: They're the same except for the implemented
>>> command.
>>>
>>> In one, the command is "thread return", in the other it is "frame
>>> return".
>>>
>>> My problem is… Except for "frame select", the frame commands only work on
>>> the current frame (not on other frames), so I would see "frame return" as
>>> return only from the current frame. While "thread return" could return from
>>> any frame (defaulting for the current thread). What do you think?
>>>
>>> I'm also sending a test directory, using the "thread return" variation.
>>>
>>> Regards,
>>>
>>>   Filipe Cabecinhas
>>>
>>>
>>> On Fri, Jul 22, 2011 at 16:25, Filipe Cabecinhas <
>>> filcab+lldb-dev at gmail.com> wrote:
>>>
>>>> Thanks for the help and advice. I will ping back the list with more
>>>> stuff when I'm done.
>>>>
>>>> Regards,
>>>>
>>>>   Filipe
>>>>
>>>>
>>>> On Fri, Jul 22, 2011 at 16:23, Jim Ingham <jingham at apple.com> wrote:
>>>>
>>>>>
>>>>> On Jul 22, 2011, at 3:46 PM, Filipe Cabecinhas wrote:
>>>>>
>>>>> >
>>>>> >
>>>>> > 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.
>>>>> >
>>>>> > OK.
>>>>> >
>>>>> > 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?
>>>>>
>>>>> Yes. This functionality seems generally useful, so the code to do this
>>>>> should go somewhere in the core.  Then the command would just be a thin
>>>>> wrapper.  StackFrame doesn't seem right to me, since you are operating on
>>>>> the list of frames more than the individual frame.  So either
>>>>> StackFrameList, or its owner Thread, seem good places.
>>>>>
>>>>> >
>>>>> > 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).
>>>>> >
>>>>>
>>>>> Yes, that makes sense, you would either return from the currently
>>>>> selected frame, or from a frame given explicitly in the command.  Note in
>>>>> general in lldb we try to avoid positional arguments, so I would do:
>>>>>
>>>>> frame return --frame <FRAME NUMBER> <expression>
>>>>>
>>>>> BTW, you can also make LLDB commands "RAW" commands, which means that
>>>>> everything after the options is passed unparsed to the command.  That's very
>>>>> convenient for commands that take an expression as their argument, since
>>>>> then you don't end up having to backslash yourself to death.  See the
>>>>> "expression" command for an example of this.
>>>>>
>>>>> Oh, yeah, another thing, though very trivial, since you defined your
>>>>> command with:
>>>>>
>>>>>                       eFlagProcessMustBeLaunched |
>>>>> eFlagProcessMustBePaused
>>>>>
>>>>> you don't have to check whether the process & target are valid, the
>>>>> command interpreter shouldn't call you if they are not.
>>>>>
>>>>> Again, thanks for working on this!
>>>>>
>>>>> Jim
>>>>>
>>>>>
>>>>> > 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.
>>>>> >
>>>>> > Regards,
>>>>> >
>>>>> >   Filipe
>>>>> >
>>>>> >
>>>>> > 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
>>>>> >
>>>>> >
>>>>>
>>>>>
>>>>
>>>
>> <frame_return.zip><frame-return.patch>
>> _______________________________________________
>>
>> lldb-dev mailing list
>> lldb-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
>>
>>
>>  *Enrico Granata*
>> ✆ 408.974.5572 | ✉ egranata@.com
>>
>>
>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20110729/dc566ce9/attachment.html>


More information about the lldb-dev mailing list