[lldb-dev] Understanding debugger launch events sequence

Jeffrey Tan via lldb-dev lldb-dev at lists.llvm.org
Fri Jan 29 11:50:45 PST 2016


Jim/Pavel, my toy code works reliably after using SBListener with
SBTarget.Launch/Attach.
One thing I noticed is:
If I set "stop_at_entry=True" for SBTarget.Launch(), I will get a stop
event of eStopReasonSignal at loader breakpoint. However
SBTarget.AttachXXX() will pause the target process without a stop event. Is
this expected? This may cause a bit state issue in our IDE since we rely on
the stop event from debugger to update UI in IDE. Is there any way to tell
lldb to emit a stop event during attach?


On Fri, Jan 29, 2016 at 11:22 AM, Jim Ingham <jingham at apple.com> wrote:

> 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> 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> 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> 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 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
>> >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>> >>>
>> > _______________________________________________
>> > lldb-dev mailing list
>> > lldb-dev at lists.llvm.org
>> > 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/8a5b96df/attachment-0001.html>


More information about the lldb-dev mailing list