[lldb-dev] Understanding debugger launch events sequence

Jim Ingham via lldb-dev lldb-dev at lists.llvm.org
Fri Jan 29 11:22:03 PST 2016


I can’t comment on Windows, I don’t know what requirements the Windows API’s place on the debugger.  

Its been a while since I’ve worked on Linux, but I don’t remember anything that would privilege one thread over another.

lldb supports running multiple targets and processes in one debugger, and also supports multiple debuggers running each one target or any combination.  Since each Debugger gets a separate script interpreter (and all its state) by running multiple processes in one SBDebugger you could offer users the possibility of having scripted commands to control a set of processes (e.g. hitting a breakpoint in one process could trigger actions in the other.)  It might be possible to do some interesting things that way.  

OTOH, keeping to one process per debugger is a much simpler programming model.  So if you were planning to have YOUR code that runs the debugger handle the possible interactions among processes, then it is probably going to be easier to manage doing it that way.

Jim



> On Jan 29, 2016, at 10:43 AM, Jeffrey Tan <jeffrey.fudan at gmail.com> wrote:
> 
> Thanks Jim. Is this true for other platforms? Our IDE is going to support Mac and Linux and may extend to Windows some time later. 
> Just curious, why does Xcode create multiple SBDebuggers assuming it is debugging a single process? Are you talking about multiple-processes scenario(One SBDebugger for one process)? 
> 
> 
> On Fri, Jan 29, 2016 at 9:21 AM, Jim Ingham <jingham at apple.com <mailto:jingham at apple.com>> wrote:
> There is no requirement that the lldb API’s be called on a particular thread on OS X.  LLDB tries to be robust against being called from multiple threads simultaneously for the same debugger, but you can still make it fall over if you try hard, particularly if you allow multiple threads to restart the process you are debugging.  Running multiple SBDebuggers on separate threads works fine, that’s the mode Xcode uses, and we haven’t had problems with this in quite a while.
> 
> Jim
> 
> > On Jan 29, 2016, at 8:54 AM, Jeffrey.fudan via lldb-dev <lldb-dev at lists.llvm.org <mailto:lldb-dev at lists.llvm.org>> wrote:
> >
> > 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 <labath at google.com <mailto:labath at 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 <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 at lists.llvm.org <mailto:lldb-dev at 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 at lists.llvm.org <mailto:lldb-dev at lists.llvm.org>
> >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev <http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev>
> >>>
> > _______________________________________________
> > lldb-dev mailing list
> > lldb-dev at lists.llvm.org <mailto:lldb-dev at lists.llvm.org>
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev <http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev>
> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20160129/6256d8fd/attachment.html>


More information about the lldb-dev mailing list