Linkage issue?

Afternoon,

I'm trying to run some lldb python code outside of Xcode and I'm running into an issue..

So I used PYTHONPATH to point to the lldv module within Xcode.app (This is on Mountain Lion) and I can import lldv, etc just fine from the command line but when I try to use breakpoints or some other code I've seen others use I run into swig issues, for example:

bp1 = target.BreakpointCreateByName('override')

bp1

<lldb.SBBreakpoint; proxy of <Swig Object of type 'lldb::SBBreakpoint *' at 0x10d80dc30> >

bp1.isValid()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/Resources/Python/lldb/__init__.py", line 1119, in <lambda>
    __getattr__ = lambda self, name: _swig_getattr(self, SBBreakpoint, name)
  File "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/Resources/Python/lldb/__init__.py", line 78, in _swig_getattr
    raise AttributeError(name)
AttributeError: isValid

I can create various variables, etc… but I notice it seems like I'm missing a few odds and ends.. I would guess that this is a linkage issue but am a little stumped as to why it seems I'm getting most of the functionality I expect.

Thanks for any help you can give.

- Jared

The correct name is 'IsValid' (capital 'I'). :wink:

Regards,

  Filipe

Thanks…

Just noticed that… need more sleep :wink:

- Jared

Since I'm on a roll, might as well ask another..

I can't seem to restart my process via process.Continue().. here's the code:

def exercise( execfile, args, cmd ):
    dbg = lldb.SBDebugger.Create()
    target = dbg.CreateTarget( execfile )
    bp1 = target.BreakpointCreateByName('override')
    bp1.SetEnabled(True)

    if not bp1.IsValid():
        print "Breakpoint is not valid"
        return None

    ci = dbg.GetCommandInterpreter()
    res = lldb.SBCommandReturnObject()

    process = target.LaunchSimple( args,None,os.getcwd() )
    process = target.GetProcess()

    while process.GetState() == lldb.eStateStopped:
        ci.HandleCommand( cmd, res )
        print res
        print "\n"
        err = process.Continue()
        print err

    print "Done"
    return res

When I run, the cmd (a backtrace) runs just fine but the process.Continue() fails:

Status: Success
Output Message:
* thread #1: tid = 0x1d07, 0x000000010ac75db7 simple2`override(int) + 7 at simple.cxx:45, stop reason = breakpoint 1.1
    frame #0: 0x000000010ac75db7 simple2`override(int) + 7 at simple.cxx:45
    frame #1: 0x000000010ac75d13 simple2`check(int) + 19 at simple.cxx:29
    frame #2: 0x000000010ac75cbe simple2`main + 46 at simple.cxx:18
    frame #3: 0x00007fff912077e1 libdyld.dylib`start + 1

error: Resume request failed - process still running.

Do I need to do something to the break point to allow the process to continue?? The code I see under the testing directories seems to not do anything in particular…

Thanks for any help,

- Jared

By default the debugger runs in async event mode where you would need to wait for process events, and then wait for a process state changed event.

If you just want to run and have say a "process.Continue()" send the continue _and_ wait for the response, then you can enable synchronous mode:

To do this, add this just after you create your debugger:

  dbg.SetAsync (False)

If you don't, and you want to wait for events using the broadcasters. Once you set async to False, as shown above, you will get the behavior you want. The problem is, if your program gets stuck running, there is no way to interrupt it when running in sync mode.

If you want to see how to listen for events, you can search for "SBListener" in any python files in the LLDB sources. One exmaple in particular is in:

lldb/test/python_api/event/TestEvents.py

When running in async mode, you request the debugger does something, but then you need to wait for events. This allows you to correctly handle your events:

    process = target.LaunchSimple(args, None, os.getcwd())
    if process:

        listener = lldb.SBListener("event_listener")
        # sign up for process state change events
        process.GetBroadcaster().AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)

        done = False
        while not done:
            event_wait_timeout_seconds = 3
            event = lldb::SBEvent()
            if listener.WaitForEvent (event_wait_timeout_seconds, event):
                state = lldb.SBProcess.GetStateFromEvent (event)
                if state == lldb.eStateStopped:
                    ci.HandleCommand( cmd, res )
                    print res
                    print "\n"
                    process.Continue()
                elif state == lldb.eStateExited:
                    print "process exited"
                    done = True
                elif state == lldb.eStateCrashed:
                    print "process crashed"
                    done = True
                elif state == lldb.eStateDetached:
                    print "process detached"
                    done = True
                elif state == lldb.eStateRunning:
                    # process is running, don't say anything, we will always get one of these after resuming
                elif state == lldb.eStateUnloaded:
                    print "process unloaded, this shouldn't happen"
                    done = True
                elif state == lldb.eStateConnected or state == lldb.eStateAttaching or state == lldb.eStateLaunching:
                    # You will see these as your process gets connected/attached/launced
            else:
                # 3 second timeout with an event, what to do???
                process.Stop() # interrupt the process
                process.Kill() # kill the process

Greg,

Thanks so much for the explanation! That was tremendously helpful!

- Jared

I just added an example to show the current usage of this:

lldb/examples/python/process_events.py