[lldb-dev] Scripting on frame finish?

Jim Ingham via lldb-dev lldb-dev at lists.llvm.org
Fri Aug 5 15:40:15 PDT 2016


The finish breakpoint is an interesting notion, file a pr & I'll add it when I have some time.

A while back I added the ability to make "stepping" operations that are scripted.  Seemed to me that could be used for this purpose, but it turns out I needed a couple more things to make it work, which I just added.  So with current TOT, you can use this little class (say in /tmp/PrintOnFinish.py):

class PrintOnFinish:
    def __init__ (self, thread_plan, dict):
        self.thread_plan = thread_plan
        self.step_out_thread_plan = thread_plan.QueueThreadPlanForStepOut(0, True)
        self.thread = self.thread_plan.GetThread()

    def explains_stop (self, event):
            return False

    def is_stale(self):
        if self.step_out_thread_plan.IsPlanStale():
            print ("Our	finish plan is stale so	we should print	now.")
            return True
	else:
            return False

    def should_stop (self, event):
        if  self.step_out_thread_plan.IsPlanComplete():
            print("Finish plan was complete, time to print.")
            self.thread_plan.SetPlanComplete(True)

        return True

def BreakpointCommand (frame, bp_loc, dict):
    print ("hit	breakpoint, scheduling action when frame is popped.")
    thread = frame.GetThread().StepUsingScriptedThreadPlan("PrintOnFinish.PrintOnFinish", False)

Then the simplest use is:

 > lldb /tmp/main
(lldb) target create "/tmp/main"
Current executable set to '/tmp/main' (x86_64).
(lldb) com scr imp /tmp/PrintOnFinish.py
(lldb) br s -n foo
Breakpoint 1: where = main`foo + 18 at main.c:5, address = 0x0000000100000ed2
(lldb) br co add -F PrintOnFinish.BreakpointCommand
(lldb) run
Process 3089 launched: '/tmp/main' (x86_64)
I am before calling foo.
*** Hit breakpoint, scheduling action when frame is popped.
Process 3089 stopped
* thread #1: tid = 0x94e8f2, function: foo , stop reason = breakpoint 1.1
    frame #0: 0x0000000100000ed2 main`foo at main.c:5
   2   	
   3   	int foo (int input)
   4   	{
-> 5   	  printf ("I am in foo with %d.\n", input);
   6   	  return input * 5;
   7   	}
   8   	
(lldb) c
Process 3089 resuming
I am in foo with 10.
*** Finish plan was complete, time to print.
Process 3089 stopped
* thread #1: tid = 0x94e8f2, function: main , stop reason = Python thread plan implemented by class PrintOnFinish.PrintOnFinish., return = (int) $0 = 50

    frame #0: 0x0000000100000f1f main`main at main.c:14
   11  	{
   12  	  int foo_var = 10;
   13  	  printf("I am before calling foo.\n");
-> 14  	  foo_var = foo(foo_var);
   15  	  printf("I am after calling foo: %d.\n", foo_var);
   16  	  return 0;
   17  	}

Note, we stopped after stepping out because I have the should_stop return True.  If you don't want this plan to 
force a stop, then just return False instead.

It also works if you get out of the function by stepping:

(lldb) run
There is a running process, kill it and restart?: [Y/n] 
Process 3089 exited with status = 9 (0x00000009) 
Process 3097 launched: '/tmp/main' (x86_64)
I am before calling foo.
*** Hit breakpoint, scheduling action when frame is popped.
Process 3097 stopped
* thread #1: tid = 0x94eaaa, function: foo , stop reason = breakpoint 1.1
    frame #0: 0x0000000100000ed2 main`foo at main.c:5
   2   	
   3   	int foo (int input)
   4   	{
-> 5   	  printf ("I am in foo with %d.\n", input);
   6   	  return input * 5;
   7   	}
   8   	
(lldb) n
I am in foo with 10.
Process 3097 stopped
* thread #1: tid = 0x94eaaa, function: foo , stop reason = step over
    frame #0: 0x0000000100000edf main`foo at main.c:6
   3   	int foo (int input)
   4   	{
   5   	  printf ("I am in foo with %d.\n", input);
-> 6   	  return input * 5;
   7   	}
   8   	
   9   	int
(lldb) n
*** Our finish plan is stale so we should print now.
Process 3097 stopped
* thread #1: tid = 0x94eaaa, function: main , stop reason = step over
    frame #0: 0x0000000100000f1f main`main at main.c:14
   11  	{
   12  	  int foo_var = 10;
   13  	  printf("I am before calling foo.\n");
-> 14  	  foo_var = foo(foo_var);
   15  	  printf("I am after calling foo: %d.\n", foo_var);
   16  	  return 0;
   17  	}

The stuff I needed to add was (1) the ability to push a step plan without immediately continuing.  That returns control to the user, and allows them to step around or do whatever they want and only trigger the printing when they actually exit.  And (2) the hook for is_stale, which was needed if the user got out of the function by some other means than "continue" like a bunch of steps.

If all you want to do is make a breakpoint that prints something when you hit it, continues out of the function and prints again, the same script will do that w/o today's changes.

Jim

> On Aug 5, 2016, at 12:15 PM, Christian Convey via lldb-dev <lldb-dev at lists.llvm.org> wrote:
> 
> Hi guys,
> 
> Any suggestions on the following?
> 
> I've got some scripts written for gdb's Python API, and I'm trying to
> port them to LLDB.  Those script include some code that ideally
> executes during, or shortly after, each completed call to a particular
> function.  I.e., the user says he/she is interested in function "foo",
> and I want to have some of my script code run every time a stack frame
> for "foo" is pushed or popped from a call stack.
> 
> Ideally the LLDB version will retain all of the following functionality:
> 
> * The ability to correlate individual calls of the function
>  with individual completions, particularly when recursion is
>  involved.
> 
> * Having completions be reported not only when the function
>  in question returns normally, but also when it completes
>  because a longjmp or C++ exception blew past it.
> 
> 
> In gdb's Python API, I've been using the "gdb.FinishBreakpoint" class
> for this.  But I haven't found an equivalent mechanism in LLDB.
> 
> The closest thing I've spotted is LLDB's "step out" command, but I'm
> not clear regarding if/how that could make my life difficult in other
> ways, particularly in the presence of recursion.
> 
> Any suggestions?
> 
> Many thanks,
> Christian
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev



More information about the lldb-dev mailing list