Search code examples
debugginglldb

Continue after python-lldb script has finished


Is there a better way to issue the continue command, after my python-lldb script has finished ?

def HelloWorld(debugger, command, result, internal_dict):
    """
        HelloWorld function. It will print "Hello World", regardless of where lldb stopped.
        Auto-Continues after script has ran.
    """
    target = debugger.GetSelectedTarget()
    process = target.GetProcess()
    print("[*] Hello World from :{}".format(process))
    process.Continue()

The example gives control back to the app but I no longer have the interactive lldb console.

The answers on this page didn't help: LLDB: silently continue after python script is done executing

Sidenote: same behavior if I attach via XCode or Terminal.


Solution

  • lldb can run in two modes "synchronous" or "asynchronous".

    In asynchronous mode, all execution control commands (step, next, etc.) complete and return control to lldb as soon as the debugee starts executing.

    In synchronous mode, execution control commands wait for the process to stop before returning.

    The correct sync/async behavior is figured out heuristically by lldb, but can also be set by hand using the SBDebugger.SetAsync API.

    When executing a Python backed lldb command, lldb sets itself into synchronous mode. That's generally what you want, for instance if you want your command do a step, check something and do another step, you wouldn't want the first step command to return before the actual step in the process was complete or your "check something" action would happen too soon.

    However, if you want your command to return control immediately after continuing, not waiting for the process to stop, then you can call debugger.SetAsync(True) right before the final process.Continue() in your Python backed command.

    Note, there's one other complication to this story. When a process is launched by lldb, the default behavior is to share the terminal with the debugee. So while the process is running, it will own the terminal, and until the process stops you won't see an lldb prompt (that would overwrite process output) or have a way to enter commands. If you want to have the debugger live and accepting commands while the process is running you need to give lldb & the app separate terminals. In lldb, use process launch --ttyand in Xcode there's a set of radio buttons in the Options tab of the Run scheme that lets you choose a separate terminal instead of using the Xcode Console.

    BTW, it sounded from your note like the process you got from the exe_ctx argument (which you've left out in this version) wasn't working for you?, But maybe that's confused with other issues. If I SetAsync(True) before doing the continue, then continuing exe_ctx.process works fine for me.

    And finally, if your Python command does switch the process state from stopped to running, you should tell lldb that by calling:

    result.SetStatus(lldb.eReturnStatusSuccessContinuingResult)
    

    or

    result.SetStatus(lldb.eReturnStatusSuccessContinuingNoResult)
    

    This matters if your command gets used in a breakpoint callback or stop-hook, where lldb uses the result to track whether the breakpoint command or stop hook forcibly restarted the target.