Great, this is very helpful, will give a try. Btw: is there any threading requirement of lldb API? For example, are all the Apis must be called on the event thread or they are free to be called on any thread? I know windows debug API has some limitation on this.
Sent from my iPad > On Jan 29, 2016, at 2:59 AM, Pavel Labath <lab...@google.com> wrote: > > Hi Jeffrey, > > I see a couple of problems with the way you are using the lldb's API. > The main problem is you are launching the target via the command-line > API, which does not allow you to specify the listener upon creation. > When you start it this way all events go to the default debugger > listener (debugger.GetListener()), and by the time you connect your > own listener, some of these events have already been broadcast, and > that is why you get nondeterministic behavior. You should use the > SBTarget.Launch function to specify the listener from the start. > > The second problem is the handling of the Stopped events. Sometimes > LLDB needs to stop the inferior do to some internal work, but this the > program is immediately resumed. This event is broadcast as a "stopped" > event with a special "restarted" bit set (see > SBProcess.GetRestartedFromEvent, and > <http://lists.llvm.org/pipermail/lldb-dev/2016-January/009291.html>) > > hope that helps, > pl > > > > On 29 January 2016 at 03:53, Jeffrey Tan via lldb-dev > <lldb-dev@lists.llvm.org> wrote: >> Hi, >> >> On mac OS, I am having difficulty understanding the launch debugger events >> sequence of lldb. I used the following code to play around LLDB. I found, >> for some binaries, debugger will enter stopped/paused mode, waiting for my >> further input, print stack shows: >> dbg> bt >> * thread #1: tid = 0x15153e, 0x00007fff5fc0d2af >> dyld`gdb_image_notifier(dyld_image_mode, unsigned int, dyld_image_info >> const*) + 1 >> * frame #0: 0x00007fff5fc0d2af dyld`gdb_image_notifier(dyld_image_mode, >> unsigned int, dyld_image_info const*) + 1 >> frame #1: 0x000000000000401d >> >> But some other binaries, it just print "Process event: stopped, reason: 1" >> and inferior just exits immediately without waiting for debugger's further >> input. >> >> Questions: >> 1. When I launch a binary, is there supposed to be a loader breakpoint >> waiting for debugger continue? Any other debug events do I expect to get and >> continue? >> 2. What about attach? >> 3. What is the dyld`gdb_image_notifier() debugger break above? Why does it >> happen for some binary but not others? >> >> Thanks for any information! >> >> # Should be first for LLDB package to be added to search path. >> from find_lldb import lldb >> from lldb import eStateStepping, eStateRunning, eStateExited, SBBreakpoint, >> SBEvent, SBListener, SBProcess, SBTarget >> import sys >> import os >> import subprocess >> from sys import stdin, stdout >> from threading import Thread >> >> class LLDBListenerThread(Thread): >> should_quit = False >> >> def __init__(self, process): >> Thread.__init__(self) >> self.listener = SBListener('Chrome Dev Tools Listener') >> self._add_listener_to_process(process) >> self._broadcast_process_state(process) >> self._add_listener_to_target(process.target) >> >> def _add_listener_to_target(self, target): >> # Listen for breakpoint/watchpoint events >> (Added/Removed/Disabled/etc). >> broadcaster = target.GetBroadcaster() >> mask = SBTarget.eBroadcastBitBreakpointChanged | >> SBTarget.eBroadcastBitWatchpointChanged | >> SBTarget.eBroadcastBitModulesLoaded >> broadcaster.AddListener(self.listener, mask) >> >> def _add_listener_to_process(self, process): >> # Listen for process events (Start/Stop/Interrupt/etc). >> broadcaster = process.GetBroadcaster() >> mask = SBProcess.eBroadcastBitStateChanged >> broadcaster.AddListener(self.listener, mask) >> >> def _broadcast_process_state(self, process): >> state = 'stopped' >> if process.state == eStateStepping or process.state == >> eStateRunning: >> state = 'running' >> elif process.state == eStateExited: >> state = 'exited' >> self.should_quit = True >> thread = process.selected_thread >> print 'Process event: %s, reason: %d' % (state, >> thread.GetStopReason()) >> >> def _breakpoint_event(self, event): >> breakpoint = SBBreakpoint.GetBreakpointFromEvent(event) >> print 'Breakpoint event: %s' % str(breakpoint) >> >> def run(self): >> while not self.should_quit: >> event = SBEvent() >> if self.listener.WaitForEvent(1, event): >> if event.GetType() == SBTarget.eBroadcastBitModulesLoaded: >> print 'Module load: %s' % str(event) >> elif SBProcess.EventIsProcessEvent(event): >> >> self._broadcast_process_state(SBProcess.GetProcessFromEvent(event)) >> elif SBBreakpoint.EventIsBreakpointEvent(event): >> self._breakpoint_event(event) >> >> def _interctive_loop(debugger): >> process = debugger.GetSelectedTarget().process >> event_thread = LLDBListenerThread(process) >> event_thread.start() >> >> while (True): >> stdout.write('dbg> ') >> command = stdin.readline().rstrip() >> if len(command) == 0: >> continue >> debugger.HandleCommand(command) >> >> >> def main(): >> debugger = lldb.SBDebugger.Create() >> >> print('Working Directory: %s' % os.getcwd()) >> debugger.HandleCommand('target create /usr/bin/find') >> debugger.HandleCommand('run .') >> _interctive_loop(debugger) >> >> if __name__ == '__main__': >> main() >> >> >> _______________________________________________ >> lldb-dev mailing list >> lldb-dev@lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev >> _______________________________________________ lldb-dev mailing list lldb-dev@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev