[lldb-dev] Stepping in a breakpoint callback with Python

Jim Ingham via lldb-dev lldb-dev at lists.llvm.org
Mon Sep 23 12:36:31 PDT 2019

> On Sep 21, 2019, at 11:11 AM, Nikita Karetnikov <nikita at karetnikov.org> wrote:
> Jim,
> > My model for this sort of tracing activity is that you are writing a fancy kind
> > of “step” operation.  You would write a fancy step & record plan that would
> > proceed along however you wanted and log at each stop.  Then your breakpoint
> > callback would just queue up this step-and-trace plan as its last act.  That’s
> > what the Scripted ThreadPlans are for:
> >
> > https://lldb.llvm.org/use/python-reference.html#using-the-python-api-to-create-custom-stepping-logic
> How do I queue up the thread plan in the callback?
> Here's my attempt:
> https://gist.github.com/nkaretnikov/6ee00afabf73332c5a89eacb610369c2#file-scripted_step-py
> This is based on:
> https://github.com/llvm/llvm-project/blob/master/lldb/examples/python/scripted_step.py
> The original 'SimpleStep' class implementation works when run as:
> thread step-scripted -C scripted_step.SimpleStep
> Not sure if my current version of 'SimpleStep' is correct (I've made a few
> changes since testing via 'thread step-scripted'), but nothing happens (no
> prints on '__init__') when I add the class via 'StepUsingScriptedThreadPlan' in
> the callback.
> What's the proper way to do this?

What happens?  Did you look at the "step" log to see what lldb thought it was doing - i.e. "log enable -f /tmp/lldb-step-log.txt lldb step".  Also, what is lldb doing then nothing happens?

One thing I've recently found (in some other work I've been doing) is that if you run the step asynchronously, then the call that ran the thread plan still holds the API lock, and any calls the scripted thread plan makes block against the other plan holding the lock.

We already have a workaround for getting the "run lock" in Python code run for internal purposes.  That is a bit of a hack, using the notion that the internal state thread is always running code on behalf of the agent that had the API lock - even though it is running on a separate thread.  So we make a separate run lock for the internal state thread, and use that for code running on that thread.  We probably need to do the same thing for the Target API lock.

> Or do I need to mimic one of the classes with a 'thread_plan.QueueThreadPlan*'
> method call?  I couldn't figure out how to trace with anything besides the
> 'SimpleStep' class when running via 'thread step-scripted', so I stuck with it.

Both the command version (step-scripted) and the Python API will queue the initial plan for you. You shouldn't need to do that.


> > I’m not quite sure what you are describing with the process events approach.
> > Are you trying to do this while also running in the lldb driver, or can you
> > write a stand-alone tool to do this?  If the latter, then it should be enough
> > to program everything at the event loop level.  You will know when your
> > breakpoint is hit, then you can issue the steps one by one and do whatever
> > logging you want each time you stop.  I’m not sure why this would need events
> > sent from the breakpoint callback.
> Nevermind the events thing, then.  I just run the lldb command and then do:
> command script import $FILE
> Ideally, I want to keep it this way so I could debug manually if needed.
> Thanks,
> Nikita

More information about the lldb-dev mailing list