diff options
Diffstat (limited to 'share/qtcreator/debugger/lldbbridge.py')
-rw-r--r-- | share/qtcreator/debugger/lldbbridge.py | 139 |
1 files changed, 85 insertions, 54 deletions
diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 3350318fbd..41d2ebf7f8 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -32,7 +32,7 @@ import threading import time import lldb import utils -from utils import DebuggerStartMode, BreakpointType, TypeCode +from utils import DebuggerStartMode, BreakpointType, TypeCode, LogChannel from contextlib import contextmanager @@ -40,6 +40,11 @@ sys.path.insert(1, os.path.dirname(os.path.abspath(inspect.getfile(inspect.curre # Simplify development of this module by reloading deps if 'dumper' in sys.modules: + if sys.version_info[0] >= 3: + if sys.version_info[1] > 3: + from importlib import reload + else: + def reload(m): print('Unsupported Python version - not reloading %s' % str(m)) reload(sys.modules['dumper']) from dumper import DumperBase, SubItem, Children, TopLevelItem @@ -108,7 +113,6 @@ class Dumper(DumperBase): self.process = None self.target = None self.eventState = lldb.eStateInvalid - self.runEngineAttempted = False self.executable_ = None self.symbolFile_ = None @@ -123,8 +127,15 @@ class Dumper(DumperBase): self.isInterrupting_ = False self.interpreterBreakpointResolvers = [] + DumperBase.warn = Dumper.warn_impl self.report('lldbversion=\"%s\"' % lldb.SBDebugger.GetVersionString()) - self.reportState('enginesetupok') + + @staticmethod + def warn_impl(message): + if message[-1:] == '\n': + message += '\n' + print('@\nbridgemessage={msg="%s",channel="%s"}\n@' + % (message.replace('"', '$'), LogChannel.AppError)) def fromNativeFrameValue(self, nativeValue): return self.fromNativeValue(nativeValue) @@ -843,6 +854,8 @@ class Dumper(DumperBase): return None def setupInferior(self, args): + """ Set up SBTarget instance """ + error = lldb.SBError() self.executable_ = args['executable'] @@ -880,6 +893,12 @@ class Dumper(DumperBase): if self.sysRoot_: self.debugger.SetCurrentPlatformSDKRoot(self.sysRoot_) + # There seems to be some kind of unexpected behavior, or bug in LLDB + # such that target.Attach(attachInfo, error) below does not create + # a valid process if this symbolFile here is valid. + if self.startMode_ == DebuggerStartMode.AttachExternal: + self.symbolFile_ = '' + self.target = self.debugger.CreateTarget( self.symbolFile_, None, self.platform_, True, error) @@ -888,18 +907,6 @@ class Dumper(DumperBase): self.reportState('enginerunfailed') return - if (self.startMode_ == DebuggerStartMode.AttachToRemoteServer - or self.startMode_ == DebuggerStartMode.AttachToRemoteProcess): - if self.platform_ != 'remote-ios': - # lldb-server expected on remote - remote_channel = 'connect://' + self.remoteChannel_ - connect_options = lldb.SBPlatformConnectOptions(remote_channel) - - res = self.target.GetPlatform().ConnectRemote(connect_options) - DumperBase.warn("CONNECT: %s %s %s" % (res, - self.target.GetPlatform().GetName(), - self.target.GetPlatform().IsConnected())) - broadcaster = self.target.GetBroadcaster() listener = self.debugger.GetListener() broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged) @@ -917,47 +924,59 @@ class Dumper(DumperBase): % (state, error, self.executable_), args) def runEngine(self, args): - if self.runEngineAttempted: - return - self.runEngineAttempted = True - self.prepare(args) - s = threading.Thread(target=self.loop, args=[]) - s.start() + """ Set up SBProcess instance """ - def prepare(self, args): error = lldb.SBError() - if self.attachPid_ > 0: - attachInfo = lldb.SBAttachInfo(self.attachPid_) - self.process = self.target.Attach(attachInfo, error) + if self.startMode_ == DebuggerStartMode.AttachExternal: + attach_info = lldb.SBAttachInfo(self.attachPid_) + self.process = self.target.Attach(attach_info, error) if not error.Success(): - self.reportState('inferiorrunfailed') - return - self.report('pid="%s"' % self.process.GetProcessID()) - # Even if it stops it seems that LLDB assumes it is running - # and later detects that it did stop after all, so it is be - # better to mirror that and wait for the spontaneous stop - if self.process and self.process.GetState() == lldb.eStateStopped: - # lldb stops the process after attaching. This happens before the - # eventloop starts. Relay the correct state back. + self.reportState('enginerunfailed') + else: + self.report('pid="%s"' % self.process.GetProcessID()) self.reportState('enginerunandinferiorstopok') + + elif (self.startMode_ == DebuggerStartMode.AttachToRemoteServer + and self.platform_ == 'remote-android'): + + connect_options = lldb.SBPlatformConnectOptions(self.remoteChannel_) + res = self.target.GetPlatform().ConnectRemote(connect_options) + + DumperBase.warn("CONNECT: %s %s platform: %s %s" % (res, + self.remoteChannel_, + self.target.GetPlatform().GetName(), + self.target.GetPlatform().IsConnected())) + if not res.Success(): + self.report(self.describeError(error)) + self.reportState('enginerunfailed') + return + + attach_info = lldb.SBAttachInfo(self.attachPid_) + self.process = self.target.Attach(attach_info, error) + if not error.Success(): + self.report(self.describeError(error)) + self.reportState('enginerunfailed') else: - self.reportState('enginerunandinferiorrunok') + self.report('pid="%s"' % self.process.GetProcessID()) + self.reportState('enginerunandinferiorstopok') + elif (self.startMode_ == DebuggerStartMode.AttachToRemoteServer or self.startMode_ == DebuggerStartMode.AttachToRemoteProcess): - if self.platform_ == 'remote-ios': self.process = self.target.ConnectRemote( self.debugger.GetListener(), self.remoteChannel_, None, error) else: - # lldb-server expected f = lldb.SBFileSpec() f.SetFilename(self.executable_) launchInfo = lldb.SBLaunchInfo(self.processArgs_) #launchInfo.SetWorkingDirectory(self.workingDirectory_) launchInfo.SetWorkingDirectory('/tmp') + if self.platform_ == 'remote-android': + launchInfo.SetWorkingDirectory('/data/local/tmp') + launchInfo.SetEnvironmentEntries(self.environment_, False) launchInfo.SetExecutableFile(f, True) DumperBase.warn("TARGET: %s" % self.target) @@ -995,6 +1014,9 @@ class Dumper(DumperBase): self.report('pid="%s"' % self.process.GetProcessID()) self.reportState('enginerunandinferiorrunok') + s = threading.Thread(target=self.loop, args=[]) + s.start() + def loop(self): event = lldb.SBEvent() #broadcaster = self.target.GetBroadcaster() @@ -1215,7 +1237,7 @@ class Dumper(DumperBase): with SubItem(self, '[statics]'): self.put('iname="%s",' % self.currentIName) self.putEmptyValue() - self.putNumChild(1) + self.putExpandable() if self.isExpanded(): with Children(self): statics = frame.GetVariables(False, False, True, False) @@ -1232,7 +1254,6 @@ class Dumper(DumperBase): else: with SubItem(self, "None"): self.putEmptyValue() - self.putNumChild(0) # FIXME: Implement shortcut for partial updates. #if isPartial: @@ -1262,23 +1283,29 @@ class Dumper(DumperBase): self.put('],partial="%d"' % isPartial) self.reportResult(self.output, args) + def fetchRegisters(self, args=None): - if self.process is None: - result = 'process="none"' - else: - frame = self.currentFrame() - if frame: - result = 'registers=[' - for group in frame.GetRegisters(): - for reg in group: - value = ''.join(["%02x" % x for x in reg.GetData().uint8s]) - result += '{name="%s"' % reg.GetName() - result += ',value="0x%s"' % value - result += ',size="%s"' % reg.GetByteSize() - result += ',type="%s"},' % reg.GetType() - result += ']' + if not self.process: + self.reportResult('process="none",registers=[]', args) + return + + frame = self.currentFrame() + if not frame or not frame.IsValid(): + self.reportResult('frame="none",registers=[]', args) + return + + result = 'registers=[' + for group in frame.GetRegisters(): + for reg in group: + value = ''.join(["%02x" % x for x in reg.GetData().uint8s]) + result += '{name="%s"' % reg.GetName() + result += ',value="0x%s"' % value + result += ',size="%s"' % reg.GetByteSize() + result += ',type="%s"},' % reg.GetType() + result += ']' self.reportResult(result, args) + def setRegister(self, args): name = args["name"] value = args["value"] @@ -1703,7 +1730,8 @@ class Dumper(DumperBase): def activateFrame(self, args): self.reportToken(args) - self.currentThread().SetSelectedFrame(args['index']) + frame = max(0, int(args['index'])) # Can be -1 in all-asm stacks + self.currentThread().SetSelectedFrame(frame) self.reportResult('', args) def selectThread(self, args): @@ -1727,6 +1755,9 @@ class Dumper(DumperBase): error = str(result.GetError()) self.report('success="%d",output="%s",error="%s"' % (success, output, error)) + def executeRoundtrip(self, args): + self.reportResult('', args) + def fetchDisassembler(self, args): functionName = args.get('function', '') flavor = args.get('flavor', '') |