Re: [lldb-dev] Understanding debugger launch events sequence

2016-01-29 Thread Jeffrey.fudan via lldb-dev
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  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
> )
> 
> hope that helps,
> pl
> 
> 
> 
> On 29 January 2016 at 03:53, Jeffrey Tan via lldb-dev
>  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, 0x7fff5fc0d2af
>> dyld`gdb_image_notifier(dyld_image_mode, unsigned int, dyld_image_info
>> const*) + 1
>>  * frame #0: 0x7fff5fc0d2af dyld`gdb_image_notifier(dyld_image_mode,
>> unsigned int, dyld_image_info const*) + 1
>>frame #1: 0x401d
>> 
>> 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_

Re: [lldb-dev] How to use the C++ API? No useful documentation?

2016-02-23 Thread Jeffrey.fudan via lldb-dev
This is a very useful read! I am also building a IDE debugger using lldb, and I 
found the initial attach/launch API and eventing system has a lot quirks. After 
getting to stopped state, querying info is relative trivial. Thanks again.

Sent from my iPad

> On Feb 23, 2016, at 2:40 PM, Greg Clayton via lldb-dev 
>  wrote:
> 
> I need to spend some time writing this up, but until then here is some info.
> 
> We created a python script that uses the LLDB public API to grab async events 
> so people can see how to do things:
> 
> svn cat 
> http://llvm.org/svn/llvm-project/lldb/trunk/examples/python/process_events.py
> 
> If you look in here you will see the correct way to do things.
> 
> I will answer you questions inlined into your email below and then add some 
> extra tips at the end:
> 
>> On Feb 20, 2016, at 3:04 PM, Paul Peet via lldb-dev 
>>  wrote:
>> 
>> Hello,
>> 
>> I am currently working on an IDE for C++ and I would like to integrate lldb 
>> as a debugger using the C++ API but it has been difficult for me to 
>> understand the architecture because there is no documentation available 
>> (except doxygen which isn't helpful at all).
>> I am at the point understanding the Event system? How are Events created?
> 
> You need to be able to listen for events from your debug session. In order to 
> do this, SBBroadcaster objects can broadcast events as SBEvent objects. You 
> need to listen for events using a SBListener. Each SBBroadcaster will 
> broadcast events where each different kind of event is represented by one bit 
> in a 32 bit uint32_t. 
> 
>> How can I use SBListener and SBBroadcaster? (What's the function of 
>> SBBroadvaster).
> 
> Yes you can. You might want to use a SBBroadcaster to send events to your 
> main event loop in the debugger:
> 
> using namespace lldb;
> SBBroadcaster gui_event_broadcaster("gui-events");
> 
> // Define the event bits we will use for gui_event_broadcaster
> enum
> {
>  eGUIEventBitLaunch   = (1u << 0),
>  eGUIEventBitKill = (1u << 1),
>  eGUIEventBitStepOver = (1u << 2),
>  eGUIEventBitStepOut  = (1u << 3),
>  eGUIEventBitStepInto = (1u << 4),
>  eGUIEventBitContinue = (1u << 5),
>  eGUIEventBitHalt = (1u << 6),
>  eGUIEventBitQuit = (1u << 7),
>  eGUIEventAll = UINT32_MAX
> };
> 
> SBListener run_loop_listener("run-loop-listener");
> // Listen for any event from gui_event_broadcaster by listening to all event 
> bits
> run_loop_listener.StartListeningForEvents(gui_event_broadcaster, 
> eGUIEventAll);
> 
> You can then run an event loop on a thread:
> 
> void
> RunLoop()
> {
>  SBEvent event;
>  bool done = false
>  while (!done)
>  {
>if (listener.WaitForEvent(UINT32_MAX, event))
>{
>  const uint32_t event_type = event.GetType();
>  if (event.BroadcasterMatchesRef(gui_event_broadcaster))
>  {
>switch (event_type)
>{
>case eGUIEventBitLaunch:
>case eGUIEventBitKill:
>case eGUIEventBitQuit:
>}
>  }
>}
>  }
> }
> 
> 
> Then on another thread, you can broadcast events. Lets say the user clicked 
> the "kill" button in your IDE, you could broadcast an event:
> 
> gui_event_broadcaster.BroadcastEventByType(eGUIEventBitKill);
> 
> Then the event loop would receive the event, as long as it is listening for 
> these events. So you can use SBBroadcaster and SBListener yourself, but many 
> objects (like SBTarget, SBProcess and SBThread) are already broadcasters and 
> will broadcast events to you and you can sign up to listen to the events they 
> send out. I would recommend starting with SBProcess, and you will see how to 
> listen to events by looking at the python code.
> 
> 
>> 
>> My current code looks something like this:
>> 
>> SBListener listener;
>> SBProcess process = target.Launch(listener, args, env, nullptr, nullptr,
>>  nullptr, "/home/cynecx/dev/helloWorld",
>>  0, true, error);
>> 
>> process.Continue();
>> 
>> StateType state = process.GetState(); // is stopped
>> 
>> SBEvent event;
>> 
>> while(true) {
>>  if(listener.WaitForEvent(0x, event)) {
>>// This branch is never hit
>>SBStream stream;
>>event.GetDescription(stream);
>>std::cout << stream.GetData() << std::endl;
>>  } else {
>>break;
>>  }
>> }
>> 
>> It would help developers (IDE) a lot if there might be some 
>> tutorials/documentation on how to use the API.
> 
> I agree. We will try to get this up on the web at some point in the near 
> future.
> 
> Some more pointers:
> 
> - When launching, use a SBLaunchInfo:
> 
> const char *argv[] = { "/bin/ls", "-l", "-A", "-F", nullptr };
> SBLaunchInfo launch_info(argv);
> launch_info.SetWorkingDirectory("/tmp");
> SBError error;
> SBProcess process = target.Launch (launch_info, error);
> 
> This will allow you to fill in a SBLaunchInfo from your IDE and possibly keep 
> it around for re-use on next launch.
> 
> - When attaching, use a SBAttachInfo. Same reason as launch 

Re: [lldb-dev] No stopping event during launch(stop_at_entry=True) on Linux?

2016-02-23 Thread Jeffrey.fudan via lldb-dev
Makes sense, will file a bug for it.

Sent from my iPad

> On Feb 23, 2016, at 5:10 PM, Jim Ingham  wrote:
> 
> That also is a bug.  If it is going to do a public stop, it has to send a 
> stop event.
> 
> Jim
> 
>> On Feb 23, 2016, at 2:52 PM, Jeffrey Tan  wrote:
>> 
>> I am not sure. From the output, it seems lldb does stop at the entry 
>> point(because you can issue "bt" command to dump the stack) in both 
>> platforms; the problem seems to be that it did not emit the stopped event 
>> for its stop on linux.  
>> 
>> On Tue, Feb 23, 2016 at 2:03 PM, Jim Ingham  wrote:
>> If the linux side is not obeying "stop_at_entry" then that is a bug.
>> 
>> Jim
>> 
>> 
>>> On Feb 23, 2016, at 1:49 PM, Jeffrey Tan via lldb-dev 
>>>  wrote:
>>> 
>>> Hi,
>>> 
>>> I have got lldb launch working fine on my macbook for sometime. But when I 
>>> try the same code on Linux, it failed to emit any stopping events during 
>>> initial launch.
>>> 
>>> When I run the reproduce code(listed at the end), I got the following 
>>> different results:
>>> 
>>> The key difference is that Macbook will emit a stopped event which caused 
>>> our IDE UI to enter break mode, while Linux violates this assumption. Is 
>>> this a bug?
>>> 
>>> ==Mac==
>>> lldb_pythonpath: 
>>> /Applications/Xcode.app/Contents/Developer/../SharedFrameworks/LLDB.framework/Resources/Python
>>> Launch result: success
>>>  Listening Thread ID: 4610625536
>>> dbg> Target event: ModulesLoaded
>>> Process event: StateChanged, Stopped
>>> Stop reason: 5
>>> dbg> bt
>>> * thread #1: tid = 0x101f01d, 0x7fff6401a000 dyld`_dyld_start, stop 
>>> reason = signal SIGSTOP
>>>  * frame #0: 0x7fff6401a000 dyld`_dyld_start
>>> ==Mac==
>>> 
>>> ==Linux==
>>> python linux_launch.py
>>> find_lldb: >> '/home/jeffreytan/project/llvm-bin/Debug+Asserts/lib/python2.7/site-packages/lldb/__init__.pyc'>
>>> Launch result: success
>>>  Listening Thread ID: 140316621375232
>>> dbg> bt
>>> * thread #1: tid = 2794520, 0x7f6165b7bb00, name = 'foo', stop reason = 
>>> signal SIGSTOP
>>>  * frame #0: 0x7f6165b7bb00
>>> ==Linux==
>>> 
>>> Repro main.py
>>> # Should be first for LLDB package to be added to search path.
>>> from find_lldb import lldb
>>> import sys
>>> import os
>>> import time
>>> from sys import stdin, stdout
>>> from event_thread import LLDBListenerThread
>>> import threading
>>> 
>>> 
>>> def interctive_loop(debugger):
>>>while (True):
>>>stdout.write('dbg> ')
>>>command = stdin.readline().rstrip()
>>>if len(command) == 0:
>>>continue
>>>if command == 'q':
>>>return
>>>debugger.HandleCommand(command)
>>> 
>>> def do_test():
>>>debugger = lldb.SBDebugger.Create()
>>>debugger.SetAsync(True)
>>>executable_path = 
>>> '~/Personal/compiler/CompilerConstruction/code/compiler'
>>>target = debugger.CreateTargetWithFileAndArch(executable_path, 
>>> lldb.LLDB_ARCH_DEFAULT)
>>> 
>>>listener = lldb.SBListener('Event Listener')
>>>error = lldb.SBError()
>>>process = target.Launch (listener,
>>> None,  # argv
>>> None,  # envp
>>> None,  # stdin_path
>>> None,  # stdout_path
>>> None,  # stderr_path
>>> None,  # working directory
>>> 0, # launch flags
>>> True, # Stop at entry
>>> error) # error
>>>print 'Launch result: %s' % str(error)
>>> 
>>>running_signal = threading.Event()
>>>stopped_signal = threading.Event()
>>>event_thread = LLDBListenerThread(debugger, running_signal, 
>>> stopped_signal)
>>>event_thread.start()
>>> 
>>>interctive_loop(debugger)
>>> 
>>>event_thread.should_quit = True
>>>event_thread.join()
>>> 
>>>lldb.SBDebugger.Destroy(debugger)
>>>return debugger
>>> 
>>> def main():
>>>debugger = do_test()
>>> 
>>> if __name__ == '__main__':
>>>main()
>>> 
>>> Event_thread
>>> class LLDBListenerThread(Thread):
>>>should_quit = False
>>> 
>>>def __init__(self, debugger, running_signal=None, stopped_sigal=None):
>>>  Thread.__init__(self)
>>>  self._running_signal = running_signal
>>>  self._stopped_sigal = stopped_sigal
>>>  process = debugger.GetSelectedTarget().process
>>>  self.listener = debugger.GetListener()
>>>  self._add_listener_to_process(process)
>>>  self._add_listener_to_target(process.target)
>>> 
>>> 
>>>def _add_listener_to_target(self, target):
>>># Listen for breakpoint/watchpoint events 
>>> (Added/Remo