[lldb-dev] Understanding debugger launch events sequence

Pavel Labath via lldb-dev lldb-dev at lists.llvm.org
Fri Jan 29 02:59:31 PST 2016


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
>


More information about the lldb-dev mailing list