Nikita,
There was a lot of other stuff in that scripted_step.py beyond the plan class
itself. I didn't follow what that did altogether. But if I removed all that
stuff, and changed your plan slightly to not rely on the global TARGET and
START_ADDRESS (I attached my simplified version below), then I can do either:
> lldb main -o "command script import /tmp/scripted_step.py" -o "break set -n
> main" -o run
(lldb) target create "main"
Current executable set to 'main' (x86_64).
(lldb) command script import /tmp/scripted_step.py
(lldb) break set -n main
Breakpoint 1: where = main`main + 15 at main.c:5:5, address = 0x0000000100000f5f
(lldb) run
Process 93318 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000f5f main`main at main.c:5
2
3 int main()
4 {
-> 5 printf("Hello, world!\n");
^
6 return 0;
7 }
8
Target 0: (main) stopped.
Process 93318 launched: '/tmp/main' (x86_64)
(lldb) thread step-scripted -C scripted_step.SimpleStep
init
init done
should step
should stop
0x100000f66: mov al, 0x0 ; main:5
should stop done: False
should step
explains stop
explains stop done: True
should stop
0x100000f68: call 0x100000f7a ; main:5
should stop done: False
should step
explains stop
explains stop done: True
should stop
should stop done: True
Process 93318 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = Python thread plan
implemented by class scripted_step.SimpleStep.
frame #0: 0x0000000100000f7a main`printf
main`printf:
0x100000f7a <+0>: jmpq *0x1080(%rip) ; (void
*)0x0000000100000f90
0x100000f80: leaq 0x1081(%rip), %r11 ; _dyld_private
0x100000f87: pushq %r11
0x100000f89: jmpq *0x71(%rip) ; (void
*)0x00007fff69523184: dyld_stub_binder
Target 0: (main) stopped.
or using the Python API:
(lldb) script
lldb.thread.StepUsingScriptedThreadPlan("scripted_step.SimpleStep")
init
init done
should step
...
with the same results. Does that simple use of the scripted plan also work for
you?
Jim
from __future__ import print_function
import lldb
import sys
class SimpleStep:
def __init__(self, thread_plan, dict_):
print('init\n')
self.thread_plan = thread_plan
self.start_addr = thread_plan.GetThread().GetFrameAtIndex(0).GetPC()
self.end_addr = self.start_addr + 26 # ret
print('init done\n')
def explains_stop(self, event):
print('explains stop\n')
stop_reason = self.thread_plan.GetThread().GetStopReason()
# print('stop_reason: {}\n'.format(stop_reason))
if stop_reason == lldb.eStopReasonTrace:
print('explains stop done: True\n')
return True
else:
print('explains stop done: False\n')
return False
def should_stop(self, event):
print('should stop\n')
cur_pc = self.thread_plan.GetThread().GetFrameAtIndex(0).GetPC()
if cur_pc < self.start_addr or cur_pc >= self.end_addr:
#if cur_pc == self.end_addr:
self.thread_plan.SetPlanComplete(True)
print('should stop done: True\n')
return True
else:
# print('in range\n')
process = self.thread_plan.GetThread().GetProcess()
thread = process.GetSelectedThread()
frame = thread.GetSelectedFrame()
pc = frame.GetPCAddress()
func_name = pc.GetFunction().name
line_num = pc.GetLineEntry().line
insns = process.target.ReadInstructions(pc, 1, 'intel')
insn = insns.GetInstructionAtIndex(0)
mnemonic = insn.mnemonic
operands = insn.operands
if func_name:
file_str = '{}; {}:{}'.format(' ' * 2, func_name, line_num)
else:
file_str = ''
print('0x{:08x}: {} {}{}\n'
.format(pc.load_addr, mnemonic, operands, file_str))
print('should stop done: False\n')
return False
def should_step(self):
print('should step\n')
return True
> On Sep 23, 2019, at 11:51 PM, Nikita Karetnikov <[email protected]> wrote:
>
> Jim,
>
> >> 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?
>
> Apologies, by "nothing" I meant that the class code doesn't seem to be
> invoked.
> Here's the output:
>
> (lldb) log enable -f /tmp/lldb-step-log.txt lldb step
> (lldb) breakpoint delete
> About to delete all breakpoints, do you want to do that?: [Y/n] y
> All breakpoints removed. (1 breakpoint)
> (lldb) command script import scripted_step.py
> Process 37849 stopped
> * thread #1, stop reason = signal SIGSTOP
> frame #0: 0x000000010255e000 dyld`_dyld_start
> dyld`_dyld_start:
> -> 0x10255e000 <+0>: pop rdi
> 0x10255e001 <+1>: push 0x0
> 0x10255e003 <+3>: mov rbp, rsp
> 0x10255e006 <+6>: and rsp, -0x10
> (lldb) trace
> trace done
> Hello, world!
> Process 37849 exited with status = 0 (0x00000000)
>
> Note that the "trace" messages are printed, but nothing from the class in
> between.
>
> I'm also attaching the lldb step log for this run. The SimpleStep class is
> referenced in the log, but it's hard for me to understand what's going on
> since
> I'm not familiar with the internals of lldb. Do you see the problem?
>
> Have you tried reproducing this? debugserver just runs a "Hello, world!"
> program:
>
> debugserver localhost:8000 main
>
> > 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.
>
> If it turns out to be relevant, will you be able to share this patch? If you
> don't want to add it to the tree, can you at least share it on the list?
>
> Thanks,
> Nikita
>
> <lldb-step-log.txt>
_______________________________________________
lldb-dev mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev