forked from qt-creator/qt-creator
		
	Broke with aa39916c41
It was missing a @ marker to separate mirrored messages from actual
data.
Change-Id: Ie142055181de4fada15060108a6ba2166591012e
Reviewed-by: hjk <hjk@theqtcompany.com>
		
	
		
			
				
	
	
		
			1759 lines
		
	
	
		
			66 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1759 lines
		
	
	
		
			66 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
############################################################################
 | 
						|
#
 | 
						|
# Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
 | 
						|
# Contact: http://www.qt-project.org/legal
 | 
						|
#
 | 
						|
# This file is part of Qt Creator.
 | 
						|
#
 | 
						|
# Commercial License Usage
 | 
						|
# Licensees holding valid commercial Qt licenses may use this file in
 | 
						|
# accordance with the commercial license agreement provided with the
 | 
						|
# Software or, alternatively, in accordance with the terms contained in
 | 
						|
# a written agreement between you and Digia.  For licensing terms and
 | 
						|
# conditions see http://www.qt.io/licensing.  For further information
 | 
						|
# use the contact form at http://www.qt.io/contact-us.
 | 
						|
#
 | 
						|
# GNU Lesser General Public License Usage
 | 
						|
# Alternatively, this file may be used under the terms of the GNU Lesser
 | 
						|
# General Public License version 2.1 or version 3 as published by the Free
 | 
						|
# Software Foundation and appearing in the file LICENSE.LGPLv21 and
 | 
						|
# LICENSE.LGPLv3 included in the packaging of this file.  Please review the
 | 
						|
# following information to ensure the GNU Lesser General Public License
 | 
						|
# requirements will be met: https://www.gnu.org/licenses/lgpl.html and
 | 
						|
# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
						|
#
 | 
						|
# In addition, as a special exception, Digia gives you certain additional
 | 
						|
# rights.  These rights are described in the Digia Qt LGPL Exception
 | 
						|
# version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 | 
						|
#
 | 
						|
#############################################################################
 | 
						|
 | 
						|
import atexit
 | 
						|
import inspect
 | 
						|
import os
 | 
						|
import platform
 | 
						|
import re
 | 
						|
import sys
 | 
						|
import subprocess
 | 
						|
import threading
 | 
						|
import lldb
 | 
						|
 | 
						|
currentDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
 | 
						|
sys.path.insert(1, currentDir)
 | 
						|
 | 
						|
from dumper import *
 | 
						|
 | 
						|
#######################################################################
 | 
						|
#
 | 
						|
# Helpers
 | 
						|
#
 | 
						|
#######################################################################
 | 
						|
 | 
						|
qqWatchpointOffset = 10000
 | 
						|
 | 
						|
lldb.theDumper = None
 | 
						|
 | 
						|
def warn(message):
 | 
						|
    print('\n\nWARNING="%s",\n' % message.encode("latin1").replace('"', "'"))
 | 
						|
 | 
						|
def showException(msg, exType, exValue, exTraceback):
 | 
						|
    warn("**** CAUGHT EXCEPTION: %s ****" % msg)
 | 
						|
    import traceback
 | 
						|
    lines = [line for line in traceback.format_exception(exType, exValue, exTraceback)]
 | 
						|
    warn('\n'.join(lines))
 | 
						|
 | 
						|
def fileName(file):
 | 
						|
    return str(file) if file.IsValid() else ''
 | 
						|
 | 
						|
 | 
						|
# Breakpoints. Keep synchronized with BreakpointType in breakpoint.h
 | 
						|
UnknownType = 0
 | 
						|
BreakpointByFileAndLine = 1
 | 
						|
BreakpointByFunction = 2
 | 
						|
BreakpointByAddress = 3
 | 
						|
BreakpointAtThrow = 4
 | 
						|
BreakpointAtCatch = 5
 | 
						|
BreakpointAtMain = 6
 | 
						|
BreakpointAtFork = 7
 | 
						|
BreakpointAtExec = 8
 | 
						|
BreakpointAtSysCall = 9
 | 
						|
WatchpointAtAddress = 10
 | 
						|
WatchpointAtExpression = 11
 | 
						|
BreakpointOnQmlSignalEmit = 12
 | 
						|
BreakpointAtJavaScriptThrow = 13
 | 
						|
 | 
						|
# See db.StateType
 | 
						|
stateNames = ["invalid", "unloaded", "connected", "attaching", "launching", "stopped",
 | 
						|
    "running", "stepping", "crashed", "detached", "exited", "suspended" ]
 | 
						|
 | 
						|
def loggingCallback(args):
 | 
						|
    s = args.strip()
 | 
						|
    s = s.replace('"', "'")
 | 
						|
    sys.stdout.write('log="%s"@\n' % s)
 | 
						|
 | 
						|
def check(exp):
 | 
						|
    if not exp:
 | 
						|
        raise RuntimeError("Check failed")
 | 
						|
 | 
						|
Value = lldb.SBValue
 | 
						|
 | 
						|
def impl_SBValue__add__(self, offset):
 | 
						|
    if self.GetType().IsPointerType():
 | 
						|
        if isinstance(offset, int) or isinstance(offset, long):
 | 
						|
            pass
 | 
						|
        else:
 | 
						|
            offset = offset.GetValueAsSigned()
 | 
						|
        itemsize = self.GetType().GetPointeeType().GetByteSize()
 | 
						|
        address = self.GetValueAsUnsigned() + offset * itemsize
 | 
						|
        address = address & 0xFFFFFFFFFFFFFFFF  # Force unsigned
 | 
						|
        return self.CreateValueFromAddress(None, address,
 | 
						|
                self.GetType().GetPointeeType()).AddressOf()
 | 
						|
 | 
						|
    raise RuntimeError("SBValue.__add__ not implemented: %s" % self.GetType())
 | 
						|
    return NotImplemented
 | 
						|
 | 
						|
def impl_SBValue__sub__(self, other):
 | 
						|
    if self.GetType().IsPointerType():
 | 
						|
        if isinstance(other, int) or isinstance(other, long):
 | 
						|
            address = self.GetValueAsUnsigned() - other
 | 
						|
            address = address & 0xFFFFFFFFFFFFFFFF  # Force unsigned
 | 
						|
            return self.CreateValueFromAddress(None, address, self.GetType())
 | 
						|
        if other.GetType().IsPointerType():
 | 
						|
            itemsize = self.GetType().GetPointeeType().GetByteSize()
 | 
						|
            return (self.GetValueAsUnsigned() - other.GetValueAsUnsigned()) / itemsize
 | 
						|
    raise RuntimeError("SBValue.__sub__ not implemented: %s" % self.GetType())
 | 
						|
    return NotImplemented
 | 
						|
 | 
						|
def impl_SBValue__le__(self, other):
 | 
						|
    if self.GetType().IsPointerType() and other.GetType().IsPointerType():
 | 
						|
        return int(self) <= int(other)
 | 
						|
    raise RuntimeError("SBValue.__le__ not implemented")
 | 
						|
    return NotImplemented
 | 
						|
 | 
						|
def impl_SBValue__int__(self):
 | 
						|
    return self.GetValueAsSigned()
 | 
						|
 | 
						|
def impl_SBValue__float__(self):
 | 
						|
    error = lldb.SBError()
 | 
						|
    if self.GetType().GetByteSize() == 4:
 | 
						|
        result = self.GetData().GetFloat(error, 0)
 | 
						|
    else:
 | 
						|
        result = self.GetData().GetDouble(error, 0)
 | 
						|
    if error.Success():
 | 
						|
        return result
 | 
						|
    return NotImplemented
 | 
						|
 | 
						|
def impl_SBValue__long__(self):
 | 
						|
    return int(self.GetValue(), 0)
 | 
						|
 | 
						|
def impl_SBValue__getitem__(value, index):
 | 
						|
    if isinstance(index, int):
 | 
						|
        type = value.GetType()
 | 
						|
        if type.IsPointerType():
 | 
						|
            innertype = value.Dereference().GetType()
 | 
						|
            address = value.GetValueAsUnsigned() + index * innertype.GetByteSize()
 | 
						|
            address = address & 0xFFFFFFFFFFFFFFFF  # Force unsigned
 | 
						|
            return value.CreateValueFromAddress(None, address, innertype)
 | 
						|
        return value.GetChildAtIndex(index)
 | 
						|
    return value.GetChildMemberWithName(index)
 | 
						|
 | 
						|
def impl_SBValue__deref(value):
 | 
						|
    result = value.Dereference()
 | 
						|
    if result.IsValid():
 | 
						|
        return result
 | 
						|
    exp = "*(class %s*)0x%x" % (value.GetType().GetPointeeType(), value.GetValueAsUnsigned())
 | 
						|
    return value.CreateValueFromExpression(None, exp)
 | 
						|
 | 
						|
lldb.SBValue.__add__ = impl_SBValue__add__
 | 
						|
lldb.SBValue.__sub__ = impl_SBValue__sub__
 | 
						|
lldb.SBValue.__le__ = impl_SBValue__le__
 | 
						|
 | 
						|
lldb.SBValue.__getitem__ = impl_SBValue__getitem__
 | 
						|
lldb.SBValue.__int__ = impl_SBValue__int__
 | 
						|
lldb.SBValue.__float__ = impl_SBValue__float__
 | 
						|
lldb.SBValue.__long__ = lambda self: long(self.GetValue(), 0)
 | 
						|
 | 
						|
lldb.SBValue.code = lambda self: self.GetTypeClass()
 | 
						|
lldb.SBValue.cast = lambda self, typeObj: self.Cast(typeObj)
 | 
						|
lldb.SBValue.dereference = impl_SBValue__deref
 | 
						|
lldb.SBValue.address = property(lambda self: self.GetLoadAddress())
 | 
						|
 | 
						|
lldb.SBType.pointer = lambda self: self.GetPointerType()
 | 
						|
lldb.SBType.target = lambda self: self.GetPointeeType()
 | 
						|
lldb.SBType.code = lambda self: self.GetTypeClass()
 | 
						|
lldb.SBType.sizeof = property(lambda self: self.GetByteSize())
 | 
						|
 | 
						|
 | 
						|
lldb.SBType.unqualified = \
 | 
						|
    lambda self: self.GetUnqualifiedType() if hasattr(self, 'GetUnqualifiedType') else self
 | 
						|
lldb.SBType.strip_typedefs = \
 | 
						|
    lambda self: self.GetCanonicalType() if hasattr(self, 'GetCanonicalType') else self
 | 
						|
 | 
						|
lldb.SBType.__orig__str__ = lldb.SBType.__str__
 | 
						|
lldb.SBType.__str__ = lldb.SBType.GetName
 | 
						|
 | 
						|
class Dumper(DumperBase):
 | 
						|
    def __init__(self):
 | 
						|
        DumperBase.__init__(self)
 | 
						|
 | 
						|
        lldb.theDumper = self
 | 
						|
 | 
						|
        self.outputLock = threading.Lock()
 | 
						|
        self.debugger = lldb.SBDebugger.Create()
 | 
						|
        #self.debugger.SetLoggingCallback(loggingCallback)
 | 
						|
        #Same as: self.debugger.HandleCommand("log enable lldb dyld step")
 | 
						|
        #self.debugger.EnableLog("lldb", ["dyld", "step", "process", "state", "thread", "events",
 | 
						|
        #    "communication", "unwind", "commands"])
 | 
						|
        #self.debugger.EnableLog("lldb", ["all"])
 | 
						|
        self.debugger.Initialize()
 | 
						|
        self.debugger.HandleCommand("settings set auto-confirm on")
 | 
						|
 | 
						|
        # FIXME: warn("DISABLING DEFAULT FORMATTERS")
 | 
						|
        # It doesn't work at all with 179.5 and we have some bad
 | 
						|
        # interactonn in 3000
 | 
						|
        # if not hasattr(lldb.SBType, 'GetCanonicalType'): # "Test" for 179.5
 | 
						|
        self.debugger.HandleCommand('type category delete gnu-libstdc++')
 | 
						|
        self.debugger.HandleCommand('type category delete libcxx')
 | 
						|
        #for i in range(self.debugger.GetNumCategories()):
 | 
						|
        #    self.debugger.GetCategoryAtIndex(i).SetEnabled(False)
 | 
						|
 | 
						|
        self.isLldb = True
 | 
						|
        self.isGoodLldb = hasattr(lldb.SBValue, "SetPreferDynamicValue")
 | 
						|
        self.process = None
 | 
						|
        self.target = None
 | 
						|
        self.eventState = lldb.eStateInvalid
 | 
						|
        self.expandedINames = {}
 | 
						|
        self.passExceptions = False
 | 
						|
        self.useLldbDumpers = False
 | 
						|
        self.autoDerefPointers = True
 | 
						|
        self.useDynamicType = True
 | 
						|
        self.useFancy = True
 | 
						|
        self.formats = {}
 | 
						|
        self.typeformats = {}
 | 
						|
 | 
						|
        self.currentIName = None
 | 
						|
        self.currentValue = ReportItem()
 | 
						|
        self.currentType = ReportItem()
 | 
						|
        self.currentNumChild = None
 | 
						|
        self.currentMaxNumChild = None
 | 
						|
        self.currentPrintsAddress = None
 | 
						|
        self.currentChildType = None
 | 
						|
        self.currentChildNumChild = None
 | 
						|
        self.currentWatchers = {}
 | 
						|
 | 
						|
        self.executable_ = None
 | 
						|
        self.startMode_ = None
 | 
						|
        self.processArgs_ = None
 | 
						|
        self.attachPid_ = None
 | 
						|
 | 
						|
        self.charType_ = None
 | 
						|
        self.intType_ = None
 | 
						|
        self.int64Type_ = None
 | 
						|
        self.sizetType_ = None
 | 
						|
        self.charPtrType_ = None
 | 
						|
        self.voidPtrType_ = None
 | 
						|
        self.isShuttingDown_ = False
 | 
						|
        self.isInterrupting_ = False
 | 
						|
        self.dummyValue = None
 | 
						|
        self.breakpointsToCheck = set([])
 | 
						|
 | 
						|
    def enterSubItem(self, item):
 | 
						|
        if isinstance(item.name, lldb.SBValue):
 | 
						|
            # Avoid $$__synth__ suffix on Mac.
 | 
						|
            value = item.name
 | 
						|
            if self.isGoodLldb:
 | 
						|
                value.SetPreferSyntheticValue(False)
 | 
						|
            item.name = value.GetName()
 | 
						|
            if item.name is None:
 | 
						|
                self.anonNumber += 1
 | 
						|
                item.name = "#%d" % self.anonNumber
 | 
						|
        if not item.iname:
 | 
						|
            item.iname = "%s.%s" % (self.currentIName, item.name)
 | 
						|
        self.put('{')
 | 
						|
        #if not item.name is None:
 | 
						|
        if isinstance(item.name, str):
 | 
						|
            if item.name == '**&':
 | 
						|
                item.name = '*'
 | 
						|
            self.put('name="%s",' % item.name)
 | 
						|
        item.savedIName = self.currentIName
 | 
						|
        item.savedValue = self.currentValue
 | 
						|
        item.savedType = self.currentType
 | 
						|
        self.currentIName = item.iname
 | 
						|
        self.currentValue = ReportItem()
 | 
						|
        self.currentType = ReportItem()
 | 
						|
 | 
						|
    def exitSubItem(self, item, exType, exValue, exTraceBack):
 | 
						|
        if not exType is None:
 | 
						|
            if self.passExceptions:
 | 
						|
                showException("SUBITEM", exType, exValue, exTraceBack)
 | 
						|
            self.putNumChild(0)
 | 
						|
            self.putValue("<not accessible>")
 | 
						|
        try:
 | 
						|
            if self.currentType.value:
 | 
						|
                typeName = self.currentType.value
 | 
						|
                if len(typeName) > 0 and typeName != self.currentChildType:
 | 
						|
                    self.put('type="%s",' % typeName) # str(type.unqualified()) ?
 | 
						|
            if  self.currentValue.value is None:
 | 
						|
                self.put('value="<not accessible>",numchild="0",')
 | 
						|
            else:
 | 
						|
                if not self.currentValue.encoding is None:
 | 
						|
                    self.put('valueencoded="%s",' % self.currentValue.encoding)
 | 
						|
                if self.currentValue.elided:
 | 
						|
                    self.put('valueelided="%s",' % self.currentValue.elided)
 | 
						|
                self.put('value="%s",' % self.currentValue.value)
 | 
						|
        except:
 | 
						|
            pass
 | 
						|
        self.put('},')
 | 
						|
        self.currentIName = item.savedIName
 | 
						|
        self.currentValue = item.savedValue
 | 
						|
        self.currentType = item.savedType
 | 
						|
        return True
 | 
						|
 | 
						|
    def isSimpleType(self, typeobj):
 | 
						|
        typeClass = typeobj.GetTypeClass()
 | 
						|
        return typeClass == lldb.eTypeClassBuiltin
 | 
						|
 | 
						|
    def childWithName(self, value, name):
 | 
						|
        child = value.GetChildMemberWithName(name)
 | 
						|
        return child if child.IsValid() else None
 | 
						|
 | 
						|
    def simpleValue(self, value):
 | 
						|
        return str(value.value)
 | 
						|
 | 
						|
    def childAt(self, value, index):
 | 
						|
        return value.GetChildAtIndex(index)
 | 
						|
 | 
						|
    def fieldAt(self, type, index):
 | 
						|
        return type.GetFieldAtIndex(index)
 | 
						|
 | 
						|
    def pointerValue(self, value):
 | 
						|
        return value.GetValueAsUnsigned()
 | 
						|
 | 
						|
    def enumExpression(self, enumType, enumValue):
 | 
						|
        ns = self.qtNamespace()
 | 
						|
        return ns + "Qt::" + enumType + "(" \
 | 
						|
            + ns + "Qt::" + enumType + "::" + enumValue + ")"
 | 
						|
 | 
						|
    def callHelper(self, value, func, args):
 | 
						|
        # args is a tuple.
 | 
						|
        arg = ','.join(args)
 | 
						|
        #self.warn("CALL: %s -> %s(%s)" % (value, func, arg))
 | 
						|
        type = value.type.name
 | 
						|
        exp = "((%s*)%s)->%s(%s)" % (type, value.address, func, arg)
 | 
						|
        #self.warn("CALL: %s" % exp)
 | 
						|
        result = value.CreateValueFromExpression('', exp)
 | 
						|
        #self.warn("  -> %s" % result)
 | 
						|
        return result
 | 
						|
 | 
						|
    def makeValue(self, type, *args):
 | 
						|
        thread = self.currentThread()
 | 
						|
        frame = thread.GetFrameAtIndex(0)
 | 
						|
        inner = ','.join(args)
 | 
						|
        value = frame.EvaluateExpression(type + '{' + inner + '}')
 | 
						|
        #self.warn("  TYPE: %s" % value.type)
 | 
						|
        #self.warn("  ADDR: 0x%x" % value.address)
 | 
						|
        #self.warn("  VALUE: %s" % value)
 | 
						|
        return value
 | 
						|
 | 
						|
    def parseAndEvaluate(self, expr):
 | 
						|
        thread = self.currentThread()
 | 
						|
        frame = thread.GetFrameAtIndex(0)
 | 
						|
        return frame.EvaluateExpression(expr)
 | 
						|
 | 
						|
    def checkPointer(self, p, align = 1):
 | 
						|
        if not self.isNull(p):
 | 
						|
            p.Dereference()
 | 
						|
 | 
						|
    def isNull(self, p):
 | 
						|
        return p.GetValueAsUnsigned() == 0
 | 
						|
 | 
						|
    def directBaseClass(self, typeobj, index = 0):
 | 
						|
        result = typeobj.GetDirectBaseClassAtIndex(index).GetType()
 | 
						|
        return result if result.IsValid() else None
 | 
						|
 | 
						|
    def templateArgument(self, typeobj, index):
 | 
						|
        type = typeobj.GetTemplateArgumentType(index)
 | 
						|
        if type.IsValid():
 | 
						|
            return type
 | 
						|
        inner = self.extractTemplateArgument(typeobj.GetName(), index)
 | 
						|
        return self.lookupType(inner)
 | 
						|
 | 
						|
    def numericTemplateArgument(self, typeobj, index):
 | 
						|
        # There seems no API to extract the numeric value.
 | 
						|
        inner = self.extractTemplateArgument(typeobj.GetName(), index)
 | 
						|
        innerType = typeobj.GetTemplateArgumentType(index)
 | 
						|
        basicType = innerType.GetBasicType()
 | 
						|
        value = toInteger(inner)
 | 
						|
        # Clang writes 'int' and '0xfffffff' into the debug info
 | 
						|
        # LLDB manages to read a value of 0xfffffff...
 | 
						|
        if basicType == lldb.eBasicTypeInt and value >= 0x8000000:
 | 
						|
            value -= 0x100000000
 | 
						|
        return value
 | 
						|
 | 
						|
    def isReferenceType(self, typeobj):
 | 
						|
        return typeobj.IsReferenceType()
 | 
						|
 | 
						|
    def isStructType(self, typeobj):
 | 
						|
        return typeobj.GetTypeClass() in (lldb.eTypeClassStruct, lldb.eTypeClassClass)
 | 
						|
 | 
						|
    def isWindowsTarget(self):
 | 
						|
        return False
 | 
						|
 | 
						|
    def isQnxTarget(self):
 | 
						|
        return False
 | 
						|
 | 
						|
    def isArmArchitecture(self):
 | 
						|
        return False
 | 
						|
 | 
						|
    def qtVersionAndNamespace(self):
 | 
						|
        for func in self.target.FindFunctions('qVersion'):
 | 
						|
            name = func.GetSymbol().GetName()
 | 
						|
            if name.endswith('()'):
 | 
						|
                name = name[:-2]
 | 
						|
            if name.count(':') > 2:
 | 
						|
                continue
 | 
						|
 | 
						|
            qtNamespace = name[:name.find('qVersion')]
 | 
						|
            self.qtNamespace = lambda: qtNamespace
 | 
						|
 | 
						|
            options = lldb.SBExpressionOptions()
 | 
						|
            res = self.target.EvaluateExpression(name + '()', options)
 | 
						|
 | 
						|
            if not res.IsValid() or not res.GetType().IsPointerType():
 | 
						|
                exp = '((const char*())%s)()' % name
 | 
						|
                res = self.target.EvaluateExpression(exp, options)
 | 
						|
 | 
						|
            if not res.IsValid() or not res.GetType().IsPointerType():
 | 
						|
                exp = '((const char*())_Z8qVersionv)()'
 | 
						|
                res = self.target.EvaluateExpression(exp, options)
 | 
						|
 | 
						|
            if not res.IsValid() or not res.GetType().IsPointerType():
 | 
						|
                continue
 | 
						|
 | 
						|
            version = str(res)
 | 
						|
            if version.count('.') != 2:
 | 
						|
                continue
 | 
						|
 | 
						|
            version.replace("'", '"') # Both seem possible
 | 
						|
            version = version[version.find('"')+1:version.rfind('"')]
 | 
						|
 | 
						|
            (major, minor, patch) = version.split('.')
 | 
						|
            qtVersion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch)
 | 
						|
            self.qtVersion = lambda: qtVersion
 | 
						|
 | 
						|
            return (qtNamespace, qtVersion)
 | 
						|
 | 
						|
        return ('', 0x50200)
 | 
						|
 | 
						|
    def qtNamespace(self):
 | 
						|
        return self.qtVersionAndNamespace()[0]
 | 
						|
 | 
						|
    def qtVersion(self):
 | 
						|
        self.qtVersionAndNamespace()
 | 
						|
        return self.qtVersionAndNamespace()[1]
 | 
						|
 | 
						|
    def intSize(self):
 | 
						|
        return 4
 | 
						|
 | 
						|
    def intType(self):
 | 
						|
        if self.intType_ is None:
 | 
						|
             self.intType_ = self.target.FindFirstType('int')
 | 
						|
        return self.intType_
 | 
						|
 | 
						|
    def int64Type(self):
 | 
						|
        if self.int64Type_ is None:
 | 
						|
             self.int64Type_ = self.target.FindFirstType('long long int')
 | 
						|
        return self.int64Type_
 | 
						|
 | 
						|
    def charType(self):
 | 
						|
        if self.charType_ is None:
 | 
						|
             self.charType_ = self.target.FindFirstType('char')
 | 
						|
        return self.charType_
 | 
						|
 | 
						|
    def charPtrType(self):
 | 
						|
        if self.charPtrType_ is None:
 | 
						|
             self.charPtrType_ = self.charType().GetPointerType()
 | 
						|
        return self.charPtrType_
 | 
						|
 | 
						|
    def voidPtrType(self):
 | 
						|
        if self.voidPtrType_ is None:
 | 
						|
             self.voidPtrType_ = self.target.FindFirstType('void').GetPointerType()
 | 
						|
        return self.voidPtrType_
 | 
						|
 | 
						|
    def ptrSize(self):
 | 
						|
        return self.charPtrType().GetByteSize()
 | 
						|
 | 
						|
    def sizetType(self):
 | 
						|
        if self.sizetType_ is None:
 | 
						|
             self.sizetType_ = self.lookupType('size_t')
 | 
						|
        return self.sizetType_
 | 
						|
 | 
						|
    def addressOf(self, value):
 | 
						|
        return int(value.GetLoadAddress())
 | 
						|
 | 
						|
    def extractInt(self, address):
 | 
						|
        return int(self.createValue(address, self.intType()))
 | 
						|
 | 
						|
    def extractInt64(self, address):
 | 
						|
        return int(self.createValue(address, self.int64Type()))
 | 
						|
 | 
						|
    def extractByte(self, address):
 | 
						|
        return int(self.createValue(address, self.charType())) & 0xFF
 | 
						|
 | 
						|
    def handleCommand(self, command):
 | 
						|
        result = lldb.SBCommandReturnObject()
 | 
						|
        self.debugger.GetCommandInterpreter().HandleCommand(command, result)
 | 
						|
        success = result.Succeeded()
 | 
						|
        if success:
 | 
						|
            self.report('output="%s"' % result.GetOutput())
 | 
						|
        else:
 | 
						|
            self.report('error="%s"' % result.GetError())
 | 
						|
        self.reportData()
 | 
						|
 | 
						|
    def put(self, stuff):
 | 
						|
        sys.stdout.write(stuff)
 | 
						|
 | 
						|
    def isMovableType(self, type):
 | 
						|
        if type.GetTypeClass() in (lldb.eTypeClassBuiltin, lldb.eTypeClassPointer):
 | 
						|
            return True
 | 
						|
        return self.isKnownMovableType(self.stripNamespaceFromType(type.GetName()))
 | 
						|
 | 
						|
    def putNumChild(self, numchild):
 | 
						|
        #self.warn("NUM CHILD: '%s' '%s'" % (numchild, self.currentChildNumChild))
 | 
						|
        #if numchild != self.currentChildNumChild:
 | 
						|
        self.put('numchild="%s",' % numchild)
 | 
						|
 | 
						|
    def putPointerValue(self, value):
 | 
						|
        # Use a lower priority
 | 
						|
        if value is None:
 | 
						|
            self.putEmptyValue(-1)
 | 
						|
        else:
 | 
						|
            self.putValue("0x%x" % value.Dereference())
 | 
						|
 | 
						|
    def putSimpleValue(self, value, encoding = None, priority = 0):
 | 
						|
        self.putValue(value.GetValue(), encoding, priority)
 | 
						|
 | 
						|
    def simpleEncoding(self, typeobj):
 | 
						|
        code = typeobj.GetTypeClass()
 | 
						|
        size = typeobj.sizeof
 | 
						|
        if code == lldb.eTypeClassBuiltin:
 | 
						|
            name = str(typeobj)
 | 
						|
            if name == "float":
 | 
						|
                return Hex2EncodedFloat4
 | 
						|
            if name == "double":
 | 
						|
                return Hex2EncodedFloat8
 | 
						|
            if name.find("unsigned") >= 0:
 | 
						|
                if size == 1:
 | 
						|
                    return Hex2EncodedUInt1
 | 
						|
                if size == 2:
 | 
						|
                    return Hex2EncodedUInt2
 | 
						|
                if size == 4:
 | 
						|
                    return Hex2EncodedUInt4
 | 
						|
                if size == 8:
 | 
						|
                    return Hex2EncodedUInt8
 | 
						|
            else:
 | 
						|
                if size == 1:
 | 
						|
                    return Hex2EncodedInt1
 | 
						|
                if size == 2:
 | 
						|
                    return Hex2EncodedInt2
 | 
						|
                if size == 4:
 | 
						|
                    return Hex2EncodedInt4
 | 
						|
                if size == 8:
 | 
						|
                    return Hex2EncodedInt8
 | 
						|
        return None
 | 
						|
 | 
						|
    def createPointerValue(self, address, pointeeType):
 | 
						|
        addr = int(address) & 0xFFFFFFFFFFFFFFFF
 | 
						|
        return self.context.CreateValueFromAddress(None, addr, pointeeType).AddressOf()
 | 
						|
 | 
						|
    def createValue(self, address, referencedType):
 | 
						|
        addr = int(address) & 0xFFFFFFFFFFFFFFFF
 | 
						|
        return self.context.CreateValueFromAddress(None, addr, referencedType)
 | 
						|
 | 
						|
    def childRange(self):
 | 
						|
        if self.currentMaxNumChild is None:
 | 
						|
            return xrange(0, self.currentNumChild)
 | 
						|
        return xrange(min(self.currentMaxNumChild, self.currentNumChild))
 | 
						|
 | 
						|
    def canonicalTypeName(self, name):
 | 
						|
        return re.sub('\\bconst\\b', '', name).replace(' ', '')
 | 
						|
 | 
						|
    def lookupType(self, name):
 | 
						|
        #self.warn("LOOKUP TYPE NAME: %s" % name)
 | 
						|
        typeobj = self.target.FindFirstType(name)
 | 
						|
        if typeobj.IsValid():
 | 
						|
            return typeobj
 | 
						|
        typeobj = self.target.FindFirstType(name + '*')
 | 
						|
        if typeobj.IsValid():
 | 
						|
            return typeob.GetPointeeType()
 | 
						|
        typeobj = self.target.FindFirstType(name + '&')
 | 
						|
        if typeobj.IsValid():
 | 
						|
            return typeob.GetReferencedType()
 | 
						|
        if name.endswith('*'):
 | 
						|
            typeobj = self.target.FindFirstType(name[:-1].strip())
 | 
						|
            if typeobj.IsValid():
 | 
						|
                return typeobj.GetPointerType()
 | 
						|
        #self.warn("LOOKUP RESULT: %s" % typeobj.name)
 | 
						|
        #self.warn("LOOKUP VALID: %s" % typeobj.IsValid())
 | 
						|
        needle = self.canonicalTypeName(name)
 | 
						|
        #self.warn("NEEDLE: %s " % needle)
 | 
						|
        for i in xrange(self.target.GetNumModules()):
 | 
						|
            module = self.target.GetModuleAtIndex(i)
 | 
						|
            # SBModule.GetType is new somewhere after early 300.x
 | 
						|
            # So this may fail.
 | 
						|
            for t in module.GetTypes():
 | 
						|
                n = self.canonicalTypeName(t.GetName())
 | 
						|
                if n == needle:
 | 
						|
                    #self.warn("FOUND TYPE DIRECT 2: %s " % t)
 | 
						|
                    return t
 | 
						|
                if n == needle + '*':
 | 
						|
                    #self.warn("FOUND TYPE BY POINTER 2: %s " % t.GetPointeeType())
 | 
						|
                    return t.GetPointeeType()
 | 
						|
                if n == needle + '&':
 | 
						|
                    #self.warn("FOUND TYPE BY REFERENCE 2: %s " % t)
 | 
						|
                    return t.GetDereferencedType()
 | 
						|
        #self.warn("NOT FOUND: %s " % needle)
 | 
						|
        return None
 | 
						|
 | 
						|
    def setupInferior(self, args):
 | 
						|
        error = lldb.SBError()
 | 
						|
 | 
						|
        self.executable_ = args['executable']
 | 
						|
        self.startMode_ = args.get('startMode', 1)
 | 
						|
        self.breakOnMain_ = args.get('breakOnMain', 0)
 | 
						|
        self.useTerminal_ = args.get('useTerminal', 0)
 | 
						|
        self.processArgs_ = args.get('processArgs', [])
 | 
						|
        self.processArgs_ = map(lambda x: self.hexdecode(x), self.processArgs_)
 | 
						|
        self.attachPid_ = args.get('attachPid', 0)
 | 
						|
        self.sysRoot_ = args.get('sysRoot', '')
 | 
						|
        self.remoteChannel_ = args.get('remoteChannel', '')
 | 
						|
        self.platform_ = args.get('platform', '')
 | 
						|
 | 
						|
        self.ignoreStops = 1 if self.useTerminal_ else 0
 | 
						|
 | 
						|
        if self.platform_:
 | 
						|
            self.debugger.SetCurrentPlatform(self.platform_)
 | 
						|
        # sysroot has to be set *after* the platform
 | 
						|
        if self.sysRoot_:
 | 
						|
            self.debugger.SetCurrentPlatformSDKRoot(self.sysRoot_)
 | 
						|
 | 
						|
        if os.path.isfile(self.executable_):
 | 
						|
            self.target = self.debugger.CreateTarget(self.executable_, None, None, True, error)
 | 
						|
        else:
 | 
						|
            self.target = self.debugger.CreateTarget(None, None, None, True, error)
 | 
						|
 | 
						|
        if self.target.IsValid():
 | 
						|
            self.handleBreakpoints(args)
 | 
						|
 | 
						|
        state = "inferiorsetupok" if self.target.IsValid() else "inferiorsetupfailed"
 | 
						|
        self.report('state="%s",msg="%s",exe="%s"' % (state, error, self.executable_))
 | 
						|
 | 
						|
    def runEngine(self, _):
 | 
						|
        self.prepare()
 | 
						|
        s = threading.Thread(target=self.loop, args=[])
 | 
						|
        s.start()
 | 
						|
 | 
						|
    def prepare(self):
 | 
						|
        error = lldb.SBError()
 | 
						|
        listener = self.debugger.GetListener()
 | 
						|
 | 
						|
        if self.attachPid_ > 0:
 | 
						|
            attachInfo = lldb.SBAttachInfo(self.attachPid_)
 | 
						|
            self.process = self.target.Attach(attachInfo, 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.
 | 
						|
            self.reportState("enginerunandinferiorrunok")
 | 
						|
        elif self.startMode_ == AttachToRemoteServer or self.startMode_ == AttachToRemoteProcess:
 | 
						|
            self.process = self.target.ConnectRemote(
 | 
						|
                self.debugger.GetListener(),
 | 
						|
                self.remoteChannel_, None, error)
 | 
						|
            if not error.Success():
 | 
						|
                self.reportError(error)
 | 
						|
                self.reportState("enginerunfailed")
 | 
						|
                return
 | 
						|
            # 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.
 | 
						|
            self.reportState("enginerunandinferiorrunok")
 | 
						|
        else:
 | 
						|
            launchInfo = lldb.SBLaunchInfo(self.processArgs_)
 | 
						|
            launchInfo.SetWorkingDirectory(os.getcwd())
 | 
						|
            environmentList = [key + "=" + value for key,value in os.environ.items()]
 | 
						|
            launchInfo.SetEnvironmentEntries(environmentList, False)
 | 
						|
            if self.breakOnMain_:
 | 
						|
                self.createBreakpointAtMain()
 | 
						|
            self.process = self.target.Launch(launchInfo, error)
 | 
						|
            if not error.Success():
 | 
						|
                self.reportError(error)
 | 
						|
                self.reportState("enginerunfailed")
 | 
						|
                return
 | 
						|
            self.report('pid="%s"' % self.process.GetProcessID())
 | 
						|
            self.reportState("enginerunandinferiorrunok")
 | 
						|
 | 
						|
    def loop(self):
 | 
						|
        event = lldb.SBEvent()
 | 
						|
        listener = self.debugger.GetListener()
 | 
						|
        while True:
 | 
						|
            if listener.WaitForEvent(10000000, event):
 | 
						|
                self.handleEvent(event)
 | 
						|
            else:
 | 
						|
                warn('TIMEOUT')
 | 
						|
 | 
						|
    def describeError(self, error):
 | 
						|
        desc = lldb.SBStream()
 | 
						|
        error.GetDescription(desc)
 | 
						|
        result = 'error={type="%s"' % error.GetType()
 | 
						|
        result += ',code="%s"' % error.GetError()
 | 
						|
        result += ',desc="%s"}' % desc.GetData()
 | 
						|
        return result
 | 
						|
 | 
						|
    def reportError(self, error):
 | 
						|
        self.report(self.describeError(error))
 | 
						|
        if error.GetType():
 | 
						|
            self.reportStatus(error.GetCString())
 | 
						|
 | 
						|
    def currentThread(self):
 | 
						|
        return None if self.process is None else self.process.GetSelectedThread()
 | 
						|
 | 
						|
    def currentFrame(self):
 | 
						|
        thread = self.currentThread()
 | 
						|
        return None if thread is None else thread.GetSelectedFrame()
 | 
						|
 | 
						|
    def reportLocation(self):
 | 
						|
        thread = self.currentThread()
 | 
						|
        frame = thread.GetSelectedFrame()
 | 
						|
        file = fileName(frame.line_entry.file)
 | 
						|
        line = frame.line_entry.line
 | 
						|
        self.report('location={file="%s",line="%s",addr="%s"}'
 | 
						|
            % (file, line, frame.pc))
 | 
						|
 | 
						|
    def firstStoppedThread(self):
 | 
						|
        for i in xrange(0, self.process.GetNumThreads()):
 | 
						|
            thread = self.process.GetThreadAtIndex(i)
 | 
						|
            reason = thread.GetStopReason()
 | 
						|
            if (reason == lldb.eStopReasonBreakpoint or
 | 
						|
                    reason == lldb.eStopReasonException or
 | 
						|
                    reason == lldb.eStopReasonPlanComplete or
 | 
						|
                    reason == lldb.eStopReasonSignal or
 | 
						|
                    reason == lldb.eStopReasonWatchpoint):
 | 
						|
                return thread
 | 
						|
        return None
 | 
						|
 | 
						|
    def reportThreads(self):
 | 
						|
        reasons = ['None', 'Trace', 'Breakpoint', 'Watchpoint', 'Signal', 'Exception',
 | 
						|
            'Exec', 'PlanComplete']
 | 
						|
        result = 'threads={threads=['
 | 
						|
        for i in xrange(0, self.process.GetNumThreads()):
 | 
						|
            thread = self.process.GetThreadAtIndex(i)
 | 
						|
            stopReason = thread.GetStopReason()
 | 
						|
            result += '{id="%d"' % thread.GetThreadID()
 | 
						|
            result += ',index="%s"' % i
 | 
						|
            result += ',details="%s"' % thread.GetQueueName()
 | 
						|
            result += ',stop-reason="%s"' % stopReason
 | 
						|
            if stopReason >= 0 and stopReason < len(reasons):
 | 
						|
                result += ',state="%s"' % reasons[stopReason]
 | 
						|
            result += ',name="%s"' % thread.GetName()
 | 
						|
            result += ',frame={'
 | 
						|
            frame = thread.GetFrameAtIndex(0)
 | 
						|
            result += 'pc="0x%x"' % frame.pc
 | 
						|
            result += ',addr="0x%x"' % frame.pc
 | 
						|
            result += ',fp="0x%x"' % frame.fp
 | 
						|
            result += ',func="%s"' % frame.GetFunctionName()
 | 
						|
            result += ',line="%s"' % frame.line_entry.line
 | 
						|
            result += ',fullname="%s"' % fileName(frame.line_entry.file)
 | 
						|
            result += ',file="%s"' % fileName(frame.line_entry.file)
 | 
						|
            result += '}},'
 | 
						|
 | 
						|
        result += '],current-thread-id="%s"},' % self.currentThread().id
 | 
						|
        self.report(result)
 | 
						|
 | 
						|
    def reportChangedBreakpoints(self):
 | 
						|
        for i in xrange(0, self.target.GetNumBreakpoints()):
 | 
						|
            bp = self.target.GetBreakpointAtIndex(i)
 | 
						|
            if bp.GetID() in self.breakpointsToCheck:
 | 
						|
                if bp.GetNumLocations():
 | 
						|
                    self.breakpointsToCheck.remove(bp.GetID())
 | 
						|
                    self.report('breakpoint-changed={%s}' % self.describeBreakpoint(bp))
 | 
						|
 | 
						|
    def firstUsableFrame(self, thread):
 | 
						|
        for i in xrange(10):
 | 
						|
            frame = thread.GetFrameAtIndex(i)
 | 
						|
            lineEntry = frame.GetLineEntry()
 | 
						|
            line = lineEntry.GetLine()
 | 
						|
            if line != 0:
 | 
						|
                return i
 | 
						|
        return None
 | 
						|
 | 
						|
    def reportStack(self, args = {}):
 | 
						|
        if not self.process:
 | 
						|
            self.report('msg="No process"')
 | 
						|
            return
 | 
						|
        thread = self.currentThread()
 | 
						|
        limit = args.get('stacklimit', -1)
 | 
						|
        if not thread:
 | 
						|
            self.report('msg="No thread"')
 | 
						|
            return
 | 
						|
 | 
						|
        (n, isLimited) = (limit, True) if limit > 0 else (thread.GetNumFrames(), False)
 | 
						|
 | 
						|
        result = 'stack={current-thread="%s"' % thread.GetThreadID()
 | 
						|
        result += ',frames=['
 | 
						|
        for i in xrange(n):
 | 
						|
            frame = thread.GetFrameAtIndex(i)
 | 
						|
            if not frame.IsValid():
 | 
						|
                isLimited = False
 | 
						|
                break
 | 
						|
            lineEntry = frame.GetLineEntry()
 | 
						|
            line = lineEntry.GetLine()
 | 
						|
            result += '{pc="0x%x"' % frame.GetPC()
 | 
						|
            result += ',level="%d"' % frame.idx
 | 
						|
            result += ',addr="0x%x"' % frame.GetPCAddress().GetLoadAddress(self.target)
 | 
						|
            result += ',func="%s"' % frame.GetFunctionName()
 | 
						|
            result += ',line="%d"' % line
 | 
						|
            result += ',fullname="%s"' % fileName(lineEntry.file)
 | 
						|
            result += ',file="%s"},' % fileName(lineEntry.file)
 | 
						|
        result += ']'
 | 
						|
        result += ',hasmore="%d"' % isLimited
 | 
						|
        result += ',limit="%d"' % limit
 | 
						|
        result += '}'
 | 
						|
        self.report(result)
 | 
						|
 | 
						|
    def reportStackPosition(self):
 | 
						|
        thread = self.currentThread()
 | 
						|
        if not thread:
 | 
						|
            self.report('msg="No thread"')
 | 
						|
            return
 | 
						|
        frame = thread.GetSelectedFrame()
 | 
						|
        if frame:
 | 
						|
            self.report('stack-position={id="%s"}' % frame.GetFrameID())
 | 
						|
        else:
 | 
						|
            self.report('stack-position={id="-1"}')
 | 
						|
 | 
						|
    def reportStackTop(self):
 | 
						|
        self.report('stack-top={}')
 | 
						|
 | 
						|
    def extractBlob(self, base, size):
 | 
						|
        if size == 0:
 | 
						|
            return Blob("")
 | 
						|
        base = int(base) & 0xFFFFFFFFFFFFFFFF
 | 
						|
        size = int(size) & 0xFFFFFFFF
 | 
						|
        error = lldb.SBError()
 | 
						|
        return Blob(self.process.ReadMemory(base, size, error))
 | 
						|
 | 
						|
    def toBlob(self, value):
 | 
						|
        data = value.GetData()
 | 
						|
        size = int(data.GetByteSize())
 | 
						|
        buf = bytearray(struct.pack('x' * size))
 | 
						|
        error = lldb.SBError()
 | 
						|
        #data.ReadRawData(error, 0, buf)
 | 
						|
        for i in range(size):
 | 
						|
            buf[i] = data.GetUnsignedInt8(error, i)
 | 
						|
        return Blob(bytes(buf))
 | 
						|
 | 
						|
    def mangleName(self, typeName):
 | 
						|
        return '_ZN%sE' % ''.join(map(lambda x: "%d%s" % (len(x), x), typeName.split('::')))
 | 
						|
 | 
						|
    def findStaticMetaObject(self, typeName):
 | 
						|
        symbolName = self.mangleName(typeName + '::staticMetaObject')
 | 
						|
        return self.target.FindFirstGlobalVariable(symbolName)
 | 
						|
 | 
						|
    def findSymbol(self, symbolName):
 | 
						|
        return self.target.FindFirstGlobalVariable(symbolName)
 | 
						|
 | 
						|
    def stripNamespaceFromType(self, typeName):
 | 
						|
        #type = self.stripClassTag(typeName)
 | 
						|
        type = typeName
 | 
						|
        ns = self.qtNamespace()
 | 
						|
        if len(ns) > 0 and type.startswith(ns):
 | 
						|
            type = type[len(ns):]
 | 
						|
        pos = type.find("<")
 | 
						|
        # FIXME: make it recognize  foo<A>::bar<B>::iterator?
 | 
						|
        while pos != -1:
 | 
						|
            pos1 = type.rfind(">", pos)
 | 
						|
            type = type[0:pos] + type[pos1+1:]
 | 
						|
            pos = type.find("<")
 | 
						|
        if type.startswith("const "):
 | 
						|
            type = type[6:]
 | 
						|
        if type.startswith("volatile "):
 | 
						|
            type = type[9:]
 | 
						|
        return type
 | 
						|
 | 
						|
    def putSubItem(self, component, value, tryDynamic=True):
 | 
						|
        if not value.IsValid():
 | 
						|
            warn("INVALID SUBITEM: %s" % value.GetName())
 | 
						|
            return
 | 
						|
        with SubItem(self, component):
 | 
						|
            self.putItem(value, tryDynamic)
 | 
						|
 | 
						|
    def putAddress(self, addr):
 | 
						|
        #if int(addr) == 0xffffffffffffffff:
 | 
						|
        #    raise RuntimeError("Illegal address")
 | 
						|
        if self.currentPrintsAddress and not addr is None:
 | 
						|
            self.put('addr="0x%x",' % int(addr))
 | 
						|
 | 
						|
    def isFunctionType(self, typeobj):
 | 
						|
        if self.isGoodLldb:
 | 
						|
            return typeobj.IsFunctionType()
 | 
						|
        #warn("TYPE: %s" % typeobj)
 | 
						|
        return False
 | 
						|
 | 
						|
    def putItem(self, value, tryDynamic=True):
 | 
						|
        typeName = value.GetType().GetUnqualifiedType().GetName()
 | 
						|
        if self.isGoodLldb:
 | 
						|
            value.SetPreferDynamicValue(tryDynamic)
 | 
						|
        typeClass = value.GetType().GetTypeClass()
 | 
						|
 | 
						|
        if tryDynamic:
 | 
						|
            self.putAddress(value.GetLoadAddress())
 | 
						|
 | 
						|
        # Handle build-in LLDB visualizers if wanted.
 | 
						|
        if False and self.useLldbDumpers and value.GetTypeSynthetic().IsValid():
 | 
						|
            # FIXME: print "official" summary?
 | 
						|
            summary = value.GetTypeSummary()
 | 
						|
            if summary.IsValid():
 | 
						|
                warn("DATA: %s" % summary.GetData())
 | 
						|
            if self.isGoodLldb:
 | 
						|
                value.SetPreferSyntheticValue(False)
 | 
						|
            provider = value.GetTypeSynthetic()
 | 
						|
            data = provider.GetData()
 | 
						|
            formatter = eval(data)(value, {})
 | 
						|
            formatter.update()
 | 
						|
            numchild = formatter.num_children()
 | 
						|
            self.put('iname="%s",' % self.currentIName)
 | 
						|
            self.putType(typeName)
 | 
						|
            self.put('numchild="%s",' % numchild)
 | 
						|
            self.put('addr="0x%x",' % value.GetLoadAddress())
 | 
						|
            self.putItemCount(numchild)
 | 
						|
            if self.currentIName in self.expandedINames:
 | 
						|
                with Children(self):
 | 
						|
                    for i in xrange(numchild):
 | 
						|
                        child = formatter.get_child_at_index(i)
 | 
						|
                        with SubItem(self, i):
 | 
						|
                            self.putItem(child)
 | 
						|
            return
 | 
						|
 | 
						|
        # Typedefs
 | 
						|
        if typeClass == lldb.eTypeClassTypedef:
 | 
						|
            if typeName in self.qqDumpers:
 | 
						|
                self.putType(typeName)
 | 
						|
                self.context = value
 | 
						|
                self.qqDumpers[typeName](self, value)
 | 
						|
                return
 | 
						|
            realType = value.GetType()
 | 
						|
            if hasattr(realType, 'GetCanonicalType'):
 | 
						|
                baseType = realType.GetCanonicalType()
 | 
						|
                if baseType != realType:
 | 
						|
                    baseValue = value.Cast(baseType.unqualified())
 | 
						|
                    self.putItem(baseValue)
 | 
						|
                    self.putBetterType(realType)
 | 
						|
                    return
 | 
						|
 | 
						|
        # Our turf now.
 | 
						|
        if self.isGoodLldb:
 | 
						|
            value.SetPreferSyntheticValue(False)
 | 
						|
 | 
						|
        # Arrays
 | 
						|
        if typeClass == lldb.eTypeClassArray:
 | 
						|
            self.putCStyleArray(value)
 | 
						|
            return
 | 
						|
 | 
						|
        # Vectors like char __attribute__ ((vector_size (8)))
 | 
						|
        if typeClass == lldb.eTypeClassVector:
 | 
						|
            self.putCStyleArray(value)
 | 
						|
            return
 | 
						|
 | 
						|
        # References
 | 
						|
        if value.GetType().IsReferenceType():
 | 
						|
            type = value.GetType().GetDereferencedType().unqualified()
 | 
						|
            addr = value.GetValueAsUnsigned()
 | 
						|
            #warn("FROM: %s" % value)
 | 
						|
            #warn("ADDR: 0x%x" % addr)
 | 
						|
            #warn("TYPE: %s" % type)
 | 
						|
            # Works:
 | 
						|
            #item = self.currentThread().GetSelectedFrame().EvaluateExpression(
 | 
						|
            #    "(%s*)0x%x" % (type, addr)).Dereference()
 | 
						|
            # Works:
 | 
						|
            item = value.CreateValueFromExpression(None,
 | 
						|
                "(%s*)0x%x" % (type, addr), lldb.SBExpressionOptions()).Dereference()
 | 
						|
            # Does not work:
 | 
						|
            #item = value.CreateValueFromAddress(None, addr, type)
 | 
						|
            # Does not work:
 | 
						|
            #item = value.Cast(type.GetPointerType()).Dereference()
 | 
						|
            #warn("TOOO: %s" % item)
 | 
						|
            self.putItem(item)
 | 
						|
            self.putBetterType(value.GetTypeName())
 | 
						|
            return
 | 
						|
 | 
						|
        # Pointers
 | 
						|
        if value.GetType().IsPointerType():
 | 
						|
            self.putFormattedPointer(value)
 | 
						|
            return
 | 
						|
 | 
						|
        #warn("VALUE: %s" % value)
 | 
						|
        #warn("FANCY: %s" % self.useFancy)
 | 
						|
        if self.useFancy:
 | 
						|
            stripped = self.stripNamespaceFromType(typeName).replace("::", "__")
 | 
						|
            #warn("STRIPPED: %s" % stripped)
 | 
						|
            #warn("DUMPABLE: %s" % (stripped in self.qqDumpers))
 | 
						|
            if stripped in self.qqDumpers:
 | 
						|
                self.putType(typeName)
 | 
						|
                self.context = value
 | 
						|
                self.qqDumpers[stripped](self, value)
 | 
						|
                return
 | 
						|
 | 
						|
        # Normal value
 | 
						|
        #numchild = 1 if value.MightHaveChildren() else 0
 | 
						|
        numchild = value.GetNumChildren()
 | 
						|
        self.putType(typeName)
 | 
						|
        self.putEmptyValue(-1)
 | 
						|
        staticMetaObject = self.extractStaticMetaObject(value.GetType())
 | 
						|
        if staticMetaObject:
 | 
						|
            self.context = value
 | 
						|
            self.putQObjectNameValue(value)
 | 
						|
        else:
 | 
						|
            v = value.GetValue()
 | 
						|
            if v:
 | 
						|
                self.putValue(v)
 | 
						|
 | 
						|
        self.put('numchild="%s",' % numchild)
 | 
						|
 | 
						|
        if self.currentIName in self.expandedINames:
 | 
						|
            with Children(self):
 | 
						|
                self.putFields(value)
 | 
						|
                if staticMetaObject:
 | 
						|
                    self.putQObjectGuts(value, staticMetaObject)
 | 
						|
 | 
						|
    def warn(self, msg):
 | 
						|
        self.put('{name="%s",value="",type="",numchild="0"},' % msg)
 | 
						|
 | 
						|
    def putFields(self, value):
 | 
						|
        # Suppress printing of 'name' field for arrays.
 | 
						|
        if value.GetType().GetTypeClass() == lldb.eTypeClassArray:
 | 
						|
            for i in xrange(value.GetNumChildren()):
 | 
						|
                child = value.GetChildAtIndex(i)
 | 
						|
                with UnnamedSubItem(self, str(i)):
 | 
						|
                    self.putItem(child)
 | 
						|
            return
 | 
						|
 | 
						|
        n = value.GetNumChildren()
 | 
						|
        m = value.GetType().GetNumberOfDirectBaseClasses()
 | 
						|
        if n > 10000:
 | 
						|
            n = 10000
 | 
						|
        # seems to happen in the 'inheritance' autotest
 | 
						|
        if m > n:
 | 
						|
            m = n
 | 
						|
        for i in xrange(m):
 | 
						|
            child = value.GetChildAtIndex(i)
 | 
						|
            with UnnamedSubItem(self, "@%d" % (i + 1)):
 | 
						|
                self.put('iname="%s",' % self.currentIName)
 | 
						|
                self.put('name="[%s]",' % child.name)
 | 
						|
                self.putItem(child)
 | 
						|
        for i in xrange(m, n):
 | 
						|
        #for i in range(n):
 | 
						|
            child = value.GetChildAtIndex(i)
 | 
						|
            # Only needed in the QVariant4 test.
 | 
						|
            if int(child.GetLoadAddress()) == 0xffffffffffffffff:
 | 
						|
                typeClass = child.GetType().GetTypeClass()
 | 
						|
                if typeClass != lldb.eTypeClassBuiltin:
 | 
						|
                    field = value.GetType().GetFieldAtIndex(i)
 | 
						|
                    addr = value.GetLoadAddress() + field.GetOffsetInBytes()
 | 
						|
                    child = value.CreateValueFromAddress(child.GetName(), addr, child.GetType())
 | 
						|
            if child.IsValid():  # FIXME: Anon members?
 | 
						|
                with SubItem(self, child):
 | 
						|
                    self.putItem(child)
 | 
						|
 | 
						|
    def reportVariables(self, args = None):
 | 
						|
        with self.outputLock:
 | 
						|
            sys.stdout.write("@\n")
 | 
						|
            self.reportVariablesHelper(args)
 | 
						|
            sys.stdout.write("@\n")
 | 
						|
 | 
						|
    def reportVariablesHelper(self, _ = None):
 | 
						|
        frame = self.currentFrame()
 | 
						|
        if frame is None:
 | 
						|
            return
 | 
						|
        self.currentIName = 'local'
 | 
						|
        self.put('data=[')
 | 
						|
        self.anonNumber = 0
 | 
						|
        shadowed = {}
 | 
						|
        ids = {} # Filter out duplicates entries at the same address.
 | 
						|
        values = list(frame.GetVariables(True, True, False, False))
 | 
						|
 | 
						|
        values.reverse() # To get shadowed vars numbered backwards.
 | 
						|
        for value in values:
 | 
						|
            if not value.IsValid():
 | 
						|
                continue
 | 
						|
            name = value.GetName()
 | 
						|
            id = "%s:0x%x" % (name, value.GetLoadAddress())
 | 
						|
            if id in ids:
 | 
						|
                continue
 | 
						|
            ids[id] = True
 | 
						|
            #if self.dummyValue is None:
 | 
						|
            #    self.dummyValue = value
 | 
						|
            if name is None:
 | 
						|
                warn("NO NAME FOR VALUE: %s" % value)
 | 
						|
                continue
 | 
						|
            if name in shadowed:
 | 
						|
                level = shadowed[name]
 | 
						|
                shadowed[name] = level + 1
 | 
						|
                name += "@%s" % level
 | 
						|
            else:
 | 
						|
                shadowed[name] = 1
 | 
						|
 | 
						|
            if name == "argv" and value.GetType().GetName() == "char **":
 | 
						|
                self.putSpecialArgv(value)
 | 
						|
            else:
 | 
						|
                with SubItem(self, name):
 | 
						|
                    self.put('iname="%s",' % self.currentIName)
 | 
						|
                    self.putItem(value)
 | 
						|
 | 
						|
        with SubItem(self, '[statics]'):
 | 
						|
            self.put('iname="%s",' % self.currentIName)
 | 
						|
            self.putEmptyValue()
 | 
						|
            self.putNumChild(1)
 | 
						|
            if self.isExpanded():
 | 
						|
                with Children(self):
 | 
						|
                    statics = frame.GetVariables(False, False, True, False)
 | 
						|
                    if len(statics):
 | 
						|
                        for i in xrange(len(statics)):
 | 
						|
                            staticVar = statics[i]
 | 
						|
                            typename = staticVar.GetType().GetName()
 | 
						|
                            name = staticVar.GetName()
 | 
						|
                            with SubItem(self, i):
 | 
						|
                                self.put('name="%s",' % name)
 | 
						|
                                self.put('iname="%s",' % self.currentIName)
 | 
						|
                                self.putItem(staticVar)
 | 
						|
                    else:
 | 
						|
                        with SubItem(self, "None"):
 | 
						|
                            self.putEmptyValue()
 | 
						|
                            self.putNumChild(0)
 | 
						|
 | 
						|
        # 'watchers':[{'id':'watch.0','exp':'23'},...]
 | 
						|
        #if not self.dummyValue is None:
 | 
						|
        for watcher in self.currentWatchers:
 | 
						|
            iname = watcher['iname']
 | 
						|
            # could be 'watch.0' or 'tooltip.deadbead'
 | 
						|
            (base, component) = iname.split('.')
 | 
						|
            exp = self.hexdecode(watcher['exp'])
 | 
						|
            self.handleWatch(exp, exp, iname)
 | 
						|
 | 
						|
        self.put(']')
 | 
						|
 | 
						|
    def reportData(self, _ = None):
 | 
						|
        if self.process is None:
 | 
						|
            self.report('process="none"')
 | 
						|
        else:
 | 
						|
            state = self.process.GetState()
 | 
						|
            if state == lldb.eStateStopped:
 | 
						|
                self.reportStackPosition()
 | 
						|
                self.reportThreads()
 | 
						|
                self.reportVariables()
 | 
						|
 | 
						|
    def reportRegisters(self, _ = None):
 | 
						|
        if self.process is None:
 | 
						|
            self.report('process="none"')
 | 
						|
        else:
 | 
						|
            frame = self.currentFrame()
 | 
						|
            if frame:
 | 
						|
                result = 'registers=['
 | 
						|
                for group in frame.GetRegisters():
 | 
						|
                    for reg in group:
 | 
						|
                        result += '{name="%s"' % reg.GetName()
 | 
						|
                        result += ',value="%s"' % reg.GetValue()
 | 
						|
                        result += ',size="%s"' % reg.GetByteSize()
 | 
						|
                        result += ',type="%s"},' % reg.GetType()
 | 
						|
                result += ']'
 | 
						|
                self.report(result)
 | 
						|
 | 
						|
    def report(self, stuff):
 | 
						|
        with self.outputLock:
 | 
						|
            sys.stdout.write("@\n" + stuff + "@\n")
 | 
						|
 | 
						|
    def reportStatus(self, msg):
 | 
						|
        self.report('statusmessage="%s"' % msg)
 | 
						|
 | 
						|
    def interruptInferior(self, _ = None):
 | 
						|
        if self.process is None:
 | 
						|
            self.reportStatus("No process to interrupt.")
 | 
						|
            return
 | 
						|
        self.isInterrupting_ = True
 | 
						|
        error = self.process.Stop()
 | 
						|
        self.reportError(error)
 | 
						|
 | 
						|
    def detachInferior(self, _ = None):
 | 
						|
        if self.process is None:
 | 
						|
            self.reportStatus("No process to detach from.")
 | 
						|
        else:
 | 
						|
            error = self.process.Detach()
 | 
						|
            self.reportError(error)
 | 
						|
            self.reportData()
 | 
						|
 | 
						|
    def continueInferior(self, _ = None):
 | 
						|
        if self.process is None:
 | 
						|
            self.reportStatus("No process to continue.")
 | 
						|
        else:
 | 
						|
            error = self.process.Continue()
 | 
						|
            self.reportError(error)
 | 
						|
            # Happens when attaching to GDBserver.
 | 
						|
            if not error.Success():
 | 
						|
                self.reportState("inferiorill")
 | 
						|
 | 
						|
    def quitDebugger(self, _ = None):
 | 
						|
        self.reportState("inferiorshutdownrequested")
 | 
						|
        self.process.Kill()
 | 
						|
 | 
						|
    def handleEvent(self, event):
 | 
						|
        out = lldb.SBStream()
 | 
						|
        event.GetDescription(out)
 | 
						|
        #warn("EVENT: %s" % event)
 | 
						|
        eventType = event.GetType()
 | 
						|
        msg = lldb.SBEvent.GetCStringFromEvent(event)
 | 
						|
        flavor = event.GetDataFlavor()
 | 
						|
        state = lldb.SBProcess.GetStateFromEvent(event)
 | 
						|
        self.report('event={type="%s",data="%s",msg="%s",flavor="%s",state="%s"}'
 | 
						|
            % (eventType, out.GetData(), msg, flavor, state))
 | 
						|
        if state != self.eventState:
 | 
						|
            self.eventState = state
 | 
						|
            if state == lldb.eStateExited:
 | 
						|
                if self.isShuttingDown_:
 | 
						|
                    self.reportState("inferiorshutdownok")
 | 
						|
                else:
 | 
						|
                    self.reportState("inferiorexited")
 | 
						|
                self.report('exited={status="%s",desc="%s"}'
 | 
						|
                    % (self.process.GetExitStatus(), self.process.GetExitDescription()))
 | 
						|
            elif state == lldb.eStateStopped:
 | 
						|
                if self.isInterrupting_:
 | 
						|
                    self.isInterrupting_ = False
 | 
						|
                    self.reportState("inferiorstopok")
 | 
						|
                elif self.ignoreStops > 0:
 | 
						|
                    self.ignoreStops -= 1
 | 
						|
                    self.process.Continue()
 | 
						|
                else:
 | 
						|
                    self.reportState("stopped")
 | 
						|
            else:
 | 
						|
                self.reportState(stateNames[state])
 | 
						|
        if eventType == lldb.SBProcess.eBroadcastBitStateChanged: # 1
 | 
						|
            state = self.process.GetState()
 | 
						|
            if state == lldb.eStateStopped:
 | 
						|
                stoppedThread = self.firstStoppedThread()
 | 
						|
                if stoppedThread:
 | 
						|
                    self.process.SetSelectedThread(stoppedThread)
 | 
						|
                self.reportStackTop()
 | 
						|
                self.reportThreads()
 | 
						|
                self.reportLocation()
 | 
						|
                self.reportChangedBreakpoints()
 | 
						|
        elif eventType == lldb.SBProcess.eBroadcastBitInterrupt: # 2
 | 
						|
            pass
 | 
						|
        elif eventType == lldb.SBProcess.eBroadcastBitSTDOUT:
 | 
						|
            # FIXME: Size?
 | 
						|
            msg = self.process.GetSTDOUT(1024)
 | 
						|
            self.report('output={channel="stdout",data="%s"}'
 | 
						|
                % self.hexencode(msg))
 | 
						|
        elif eventType == lldb.SBProcess.eBroadcastBitSTDERR:
 | 
						|
            msg = self.process.GetSTDERR(1024)
 | 
						|
            self.report('output={channel="stderr",data="%s"}'
 | 
						|
                % self.hexencode(msg))
 | 
						|
        elif eventType == lldb.SBProcess.eBroadcastBitProfileData:
 | 
						|
            pass
 | 
						|
 | 
						|
    def reportState(self, state):
 | 
						|
        self.report('state="%s"' % state)
 | 
						|
 | 
						|
    def describeBreakpoint(self, bp):
 | 
						|
        isWatch = isinstance(bp, lldb.SBWatchpoint)
 | 
						|
        if isWatch:
 | 
						|
            result  = 'lldbid="%s"' % (qqWatchpointOffset + bp.GetID())
 | 
						|
        else:
 | 
						|
            result  = 'lldbid="%s"' % bp.GetID()
 | 
						|
        if not bp.IsValid():
 | 
						|
            return
 | 
						|
        result += ',hitcount="%s"' % bp.GetHitCount()
 | 
						|
        if hasattr(bp, 'GetThreadID'):
 | 
						|
            result += ',threadid="%s"' % bp.GetThreadID()
 | 
						|
        if hasattr(bp, 'IsOneShot'):
 | 
						|
            result += ',oneshot="%s"' % (1 if bp.IsOneShot() else 0)
 | 
						|
        if hasattr(bp, 'GetCondition'):
 | 
						|
            cond = bp.GetCondition()
 | 
						|
            result += ',condition="%s"' % self.hexencode("" if cond is None else cond)
 | 
						|
        result += ',enabled="%s"' % (1 if bp.IsEnabled() else 0)
 | 
						|
        result += ',valid="%s"' % (1 if bp.IsValid() else 0)
 | 
						|
        result += ',ignorecount="%s"' % bp.GetIgnoreCount()
 | 
						|
        result += ',locations=['
 | 
						|
        lineEntry = None
 | 
						|
        if hasattr(bp, 'GetNumLocations'):
 | 
						|
            for i in xrange(bp.GetNumLocations()):
 | 
						|
                loc = bp.GetLocationAtIndex(i)
 | 
						|
                addr = loc.GetAddress()
 | 
						|
                lineEntry = addr.GetLineEntry()
 | 
						|
                result += '{locid="%s"' % loc.GetID()
 | 
						|
                result += ',func="%s"' % addr.GetFunction().GetName()
 | 
						|
                result += ',enabled="%s"' % (1 if loc.IsEnabled() else 0)
 | 
						|
                result += ',resolved="%s"' % (1 if loc.IsResolved() else 0)
 | 
						|
                result += ',valid="%s"' % (1 if loc.IsValid() else 0)
 | 
						|
                result += ',ignorecount="%s"' % loc.GetIgnoreCount()
 | 
						|
                result += ',file="%s"' % lineEntry.GetFileSpec()
 | 
						|
                result += ',line="%s"' % lineEntry.GetLine()
 | 
						|
                result += ',addr="%s"},' % loc.GetLoadAddress()
 | 
						|
        result += ']'
 | 
						|
        if lineEntry is not None:
 | 
						|
            result += ',file="%s"' % lineEntry.GetFileSpec()
 | 
						|
            result += ',line="%s"' % lineEntry.GetLine()
 | 
						|
        return result
 | 
						|
 | 
						|
    def createBreakpointAtMain(self):
 | 
						|
        return self.target.BreakpointCreateByName(
 | 
						|
            "main", self.target.GetExecutable().GetFilename())
 | 
						|
 | 
						|
    def addBreakpoint(self, args):
 | 
						|
        bpType = args["type"]
 | 
						|
        if bpType == BreakpointByFileAndLine:
 | 
						|
            bp = self.target.BreakpointCreateByLocation(
 | 
						|
                str(args["file"]), int(args["line"]))
 | 
						|
        elif bpType == BreakpointByFunction:
 | 
						|
            bp = self.target.BreakpointCreateByName(args["function"])
 | 
						|
        elif bpType == BreakpointByAddress:
 | 
						|
            bp = self.target.BreakpointCreateByAddress(args["address"])
 | 
						|
        elif bpType == BreakpointAtMain:
 | 
						|
            bp = self.createBreakpointAtMain()
 | 
						|
        elif bpType == BreakpointByFunction:
 | 
						|
            bp = self.target.BreakpointCreateByName(args["function"])
 | 
						|
        elif bpType == BreakpointAtThrow:
 | 
						|
            bp = self.target.BreakpointCreateForException(
 | 
						|
                lldb.eLanguageTypeC_plus_plus, False, True)
 | 
						|
        elif bpType == BreakpointAtCatch:
 | 
						|
            bp = self.target.BreakpointCreateForException(
 | 
						|
                lldb.eLanguageTypeC_plus_plus, True, False)
 | 
						|
        elif bpType == WatchpointAtAddress:
 | 
						|
            error = lldb.SBError()
 | 
						|
            bp = self.target.WatchAddress(args["address"], 4, False, True, error)
 | 
						|
            #warn("BPNEW: %s" % bp)
 | 
						|
            self.reportError(error)
 | 
						|
        elif bpType == WatchpointAtExpression:
 | 
						|
            # FIXME: Top level-only for now.
 | 
						|
            try:
 | 
						|
                frame = self.currentFrame()
 | 
						|
                value = frame.FindVariable(args["expression"])
 | 
						|
                error = lldb.SBError()
 | 
						|
                bp = self.target.WatchAddress(value.GetLoadAddress(),
 | 
						|
                    value.GetByteSize(), False, True, error)
 | 
						|
            except:
 | 
						|
                return self.target.BreakpointCreateByName(None)
 | 
						|
        else:
 | 
						|
            # This leaves the unhandled breakpoint in a (harmless)
 | 
						|
            # "pending" state.
 | 
						|
            return self.target.BreakpointCreateByName(None)
 | 
						|
        bp.SetIgnoreCount(int(args["ignorecount"]))
 | 
						|
        if hasattr(bp, 'SetCondition'):
 | 
						|
            bp.SetCondition(self.hexdecode(args["condition"]))
 | 
						|
        bp.SetEnabled(int(args["enabled"]))
 | 
						|
        if hasattr(bp, 'SetOneShot'):
 | 
						|
            bp.SetOneShot(int(args["oneshot"]))
 | 
						|
        self.breakpointsToCheck.add(bp.GetID())
 | 
						|
        return bp
 | 
						|
 | 
						|
    def changeBreakpoint(self, args):
 | 
						|
        id = int(args["lldbid"])
 | 
						|
        if id > qqWatchpointOffset:
 | 
						|
            bp = self.target.FindWatchpointByID(id)
 | 
						|
        else:
 | 
						|
            bp = self.target.FindBreakpointByID(id)
 | 
						|
        bp.SetIgnoreCount(int(args["ignorecount"]))
 | 
						|
        bp.SetCondition(self.hexdecode(args["condition"]))
 | 
						|
        bp.SetEnabled(int(args["enabled"]))
 | 
						|
        if hasattr(bp, 'SetOneShot'):
 | 
						|
            bp.SetOneShot(int(args["oneshot"]))
 | 
						|
        return bp
 | 
						|
 | 
						|
    def removeBreakpoint(self, args):
 | 
						|
        id = int(args['lldbid'])
 | 
						|
        if id > qqWatchpointOffset:
 | 
						|
            return self.target.DeleteWatchpoint(id - qqWatchpointOffset)
 | 
						|
        return self.target.BreakpointDelete(id)
 | 
						|
 | 
						|
    def handleBreakpoints(self, args):
 | 
						|
        # This seems to be only needed on Linux.
 | 
						|
        needStop = False
 | 
						|
        if self.process and platform.system() == "Linux":
 | 
						|
            needStop = self.process.GetState() != lldb.eStateStopped
 | 
						|
        if needStop:
 | 
						|
            error = self.process.Stop()
 | 
						|
 | 
						|
        for bp in args['bkpts']:
 | 
						|
            operation = bp['operation']
 | 
						|
            modelId = bp['modelid']
 | 
						|
 | 
						|
            if operation == 'add':
 | 
						|
                bpNew = self.addBreakpoint(bp)
 | 
						|
                self.report('breakpoint-added={%s,modelid="%s"}'
 | 
						|
                    % (self.describeBreakpoint(bpNew), modelId))
 | 
						|
 | 
						|
            elif operation == 'change':
 | 
						|
                bpNew = self.changeBreakpoint(bp)
 | 
						|
                self.report('breakpoint-changed={%s,modelid="%s"}'
 | 
						|
                    % (self.describeBreakpoint(bpNew), modelId))
 | 
						|
 | 
						|
            elif operation == 'remove':
 | 
						|
                bpDead = self.removeBreakpoint(bp)
 | 
						|
                self.report('breakpoint-removed={modelid="%s"}' % modelId)
 | 
						|
 | 
						|
        if needStop:
 | 
						|
            error = self.process.Continue()
 | 
						|
 | 
						|
 | 
						|
    def listModules(self, args):
 | 
						|
        result = 'modules=['
 | 
						|
        for i in xrange(self.target.GetNumModules()):
 | 
						|
            module = self.target.GetModuleAtIndex(i)
 | 
						|
            result += '{file="%s"' % module.file.fullpath
 | 
						|
            result += ',name="%s"' % module.file.basename
 | 
						|
            result += ',addrsize="%s"' % module.addr_size
 | 
						|
            result += ',triple="%s"' % module.triple
 | 
						|
            #result += ',sections={'
 | 
						|
            #for section in module.sections:
 | 
						|
            #    result += '[name="%s"' % section.name
 | 
						|
            #    result += ',addr="%s"' % section.addr
 | 
						|
            #    result += ',size="%s"],' % section.size
 | 
						|
            #result += '}'
 | 
						|
            result += '},'
 | 
						|
        result += ']'
 | 
						|
        self.report(result)
 | 
						|
 | 
						|
    def listSymbols(self, args):
 | 
						|
        moduleName = args['module']
 | 
						|
        #file = lldb.SBFileSpec(moduleName)
 | 
						|
        #module = self.target.FindModule(file)
 | 
						|
        for i in xrange(self.target.GetNumModules()):
 | 
						|
            module = self.target.GetModuleAtIndex(i)
 | 
						|
            if module.file.fullpath == moduleName:
 | 
						|
                break
 | 
						|
        result = 'symbols={module="%s"' % moduleName
 | 
						|
        result += ',valid="%s"' % module.IsValid()
 | 
						|
        result += ',sections="%s"' % module.GetNumSections()
 | 
						|
        result += ',symbols=['
 | 
						|
        for symbol in module.symbols:
 | 
						|
            startAddress = symbol.GetStartAddress().GetLoadAddress(self.target)
 | 
						|
            endAddress = symbol.GetEndAddress().GetLoadAddress(self.target)
 | 
						|
            result += '{type="%s"' % symbol.GetType()
 | 
						|
            result += ',name="%s"' % symbol.GetName()
 | 
						|
            result += ',address="0x%x"' % startAddress
 | 
						|
            result += ',demangled="%s"' % symbol.GetMangledName()
 | 
						|
            result += ',size="%s"' % (endAddress - startAddress)
 | 
						|
            result += '},'
 | 
						|
        result += ']}'
 | 
						|
        self.report(result)
 | 
						|
 | 
						|
    def executeNext(self, _ = None):
 | 
						|
        self.currentThread().StepOver()
 | 
						|
 | 
						|
    def executeNextI(self, _ = None):
 | 
						|
        self.currentThread().StepInstruction(lldb.eOnlyThisThread)
 | 
						|
 | 
						|
    def executeStep(self, _ = None):
 | 
						|
        self.currentThread().StepInto()
 | 
						|
 | 
						|
    def shutdownInferior(self, _ = None):
 | 
						|
        self.isShuttingDown_ = True
 | 
						|
        if self.process is None:
 | 
						|
            self.reportState("inferiorshutdownok")
 | 
						|
        else:
 | 
						|
            state = self.process.GetState()
 | 
						|
            if state == lldb.eStateStopped:
 | 
						|
                self.process.Kill()
 | 
						|
            self.reportState("inferiorshutdownok")
 | 
						|
 | 
						|
    def quit(self, _ = None):
 | 
						|
        self.reportState("engineshutdownok")
 | 
						|
        self.process.Kill()
 | 
						|
 | 
						|
    def executeStepI(self, _ = None):
 | 
						|
        self.currentThread().StepInstruction(lldb.eOnlyThisThread)
 | 
						|
 | 
						|
    def executeStepOut(self, _ = None):
 | 
						|
        self.currentThread().StepOut()
 | 
						|
 | 
						|
    def executeRunToLocation(self, args):
 | 
						|
        addr = args.get('address', 0)
 | 
						|
        if addr:
 | 
						|
            error = self.currentThread().RunToAddress(addr)
 | 
						|
        else:
 | 
						|
            frame = self.currentFrame()
 | 
						|
            file = args['file']
 | 
						|
            line = int(args['line'])
 | 
						|
            error = self.currentThread().StepOverUntil(frame, lldb.SBFileSpec(file), line)
 | 
						|
        if error.GetType():
 | 
						|
            self.reportState("running")
 | 
						|
            self.reportState("stopped")
 | 
						|
            self.reportError(error)
 | 
						|
            self.reportLocation()
 | 
						|
        else:
 | 
						|
            self.reportData()
 | 
						|
 | 
						|
    def executeJumpToLocation(self, args):
 | 
						|
        frame = self.currentFrame()
 | 
						|
        self.reportState("stopped")
 | 
						|
        if not frame:
 | 
						|
            self.reportStatus("No frame available.")
 | 
						|
            self.reportLocation()
 | 
						|
            return
 | 
						|
        addr = args.get('address', 0)
 | 
						|
        if addr:
 | 
						|
            bp = self.target.BreakpointCreateByAddress(addr)
 | 
						|
        else:
 | 
						|
            bp = self.target.BreakpointCreateByLocation(
 | 
						|
                        str(args['file']), int(args['line']))
 | 
						|
        if bp.GetNumLocations() == 0:
 | 
						|
            self.target.BreakpointDelete(bp.GetID())
 | 
						|
            self.reportStatus("No target location found.")
 | 
						|
            self.reportLocation()
 | 
						|
            return
 | 
						|
        loc = bp.GetLocationAtIndex(0)
 | 
						|
        self.target.BreakpointDelete(bp.GetID())
 | 
						|
        frame.SetPC(loc.GetLoadAddress())
 | 
						|
        self.reportData()
 | 
						|
 | 
						|
    def breakList(self):
 | 
						|
        result = lldb.SBCommandReturnObject()
 | 
						|
        self.debugger.GetCommandInterpreter().HandleCommand("break list", result)
 | 
						|
        self.report('success="%d",output="%s",error="%s"'
 | 
						|
            % (result.Succeeded(), result.GetOutput(), result.GetError()))
 | 
						|
 | 
						|
    def activateFrame(self, args):
 | 
						|
        thread = args['thread']
 | 
						|
        self.currentThread().SetSelectedFrame(args['index'])
 | 
						|
        state = self.process.GetState()
 | 
						|
        if state == lldb.eStateStopped:
 | 
						|
            self.reportStackPosition()
 | 
						|
 | 
						|
    def selectThread(self, args):
 | 
						|
        self.process.SetSelectedThreadByID(args['id'])
 | 
						|
        self.reportData()
 | 
						|
 | 
						|
    def requestModuleSymbols(self, frame):
 | 
						|
        self.handleCommand("target module list " + frame)
 | 
						|
 | 
						|
    def createFullBacktrace(self, _ = None):
 | 
						|
        command = "thread backtrace all"
 | 
						|
        result = lldb.SBCommandReturnObject()
 | 
						|
        self.debugger.GetCommandInterpreter().HandleCommand(command, result)
 | 
						|
        self.report('full-backtrace="%s"' % self.hexencode(result.GetOutput()))
 | 
						|
 | 
						|
    def executeDebuggerCommand(self, args):
 | 
						|
        result = lldb.SBCommandReturnObject()
 | 
						|
        command = args['command']
 | 
						|
        self.debugger.GetCommandInterpreter().HandleCommand(command, result)
 | 
						|
        success = result.Succeeded()
 | 
						|
        output = result.GetOutput()
 | 
						|
        error = str(result.GetError())
 | 
						|
        self.report('success="%d",output="%s",error="%s"' % (success, output, error))
 | 
						|
 | 
						|
    def addExtraDumper(self, args):
 | 
						|
        self.addDumperModule(args['path'])
 | 
						|
        self.report('ok')
 | 
						|
 | 
						|
    def updateData(self, args):
 | 
						|
        if 'expanded' in args:
 | 
						|
            self.expandedINames = set(args['expanded'].split(','))
 | 
						|
        if 'autoderef' in args:
 | 
						|
            self.autoDerefPointers = int(args['autoderef'])
 | 
						|
        if 'dyntype' in args:
 | 
						|
            self.useDynamicType = int(args['dyntype'])
 | 
						|
        if 'fancy' in args:
 | 
						|
            self.useFancy = int(args['fancy'])
 | 
						|
        if 'passexceptions' in args:
 | 
						|
            self.passExceptions = int(args['passexceptions'])
 | 
						|
        if 'watchers' in args:
 | 
						|
            self.currentWatchers = args['watchers']
 | 
						|
        if 'typeformats' in args:
 | 
						|
            for f in args['typeformats'].split(','):
 | 
						|
                pos = f.find("=")
 | 
						|
                if pos != -1:
 | 
						|
                    typeName = self.hexdecode(f[0:pos])
 | 
						|
                    self.typeformats[typeName] = int(f[pos+1:])
 | 
						|
        if 'formats' in args:
 | 
						|
            for f in args['formats'].split(','):
 | 
						|
                pos = f.find("=")
 | 
						|
                if pos != -1:
 | 
						|
                    self.formats[f[0:pos]] = int(f[pos+1:])
 | 
						|
        self.reportVariables(args)
 | 
						|
 | 
						|
    def disassemble(self, args):
 | 
						|
        functionName = args.get('function', '')
 | 
						|
        flavor = args.get('flavor', '')
 | 
						|
        function = None
 | 
						|
        if len(functionName):
 | 
						|
            functions = self.target.FindFunctions(functionName).functions
 | 
						|
            if len(functions):
 | 
						|
                function = functions[0]
 | 
						|
        if function:
 | 
						|
            base = function.GetStartAddress().GetLoadAddress(self.target)
 | 
						|
            instructions = function.GetInstructions(self.target)
 | 
						|
        else:
 | 
						|
            base = args.get('address', 0)
 | 
						|
            addr = lldb.SBAddress(base, self.target)
 | 
						|
            instructions = self.target.ReadInstructions(addr, 100)
 | 
						|
 | 
						|
        result = 'disassembly={cookie="%s",' % args['cookie']
 | 
						|
        result += ',lines=['
 | 
						|
        for insn in instructions:
 | 
						|
            comment = insn.GetComment(self.target)
 | 
						|
            addr = insn.GetAddress().GetLoadAddress(self.target)
 | 
						|
            result += '{address="%s"' % addr
 | 
						|
            result += ',inst="%s %s"' % (insn.GetMnemonic(self.target),
 | 
						|
                insn.GetOperands(self.target))
 | 
						|
            result += ',func_name="%s"' % functionName
 | 
						|
            if comment:
 | 
						|
                result += ',comment="%s"' % comment
 | 
						|
            result += ',offset="%s"},' % (addr - base)
 | 
						|
        self.report(result + ']')
 | 
						|
 | 
						|
    def loadDumperFiles(self, _ = None):
 | 
						|
        result = self.findDumperFunctions()
 | 
						|
        self.report(result)
 | 
						|
 | 
						|
    def fetchMemory(self, args):
 | 
						|
        address = args['address']
 | 
						|
        length = args['length']
 | 
						|
        error = lldb.SBError()
 | 
						|
        contents = self.process.ReadMemory(address, length, error)
 | 
						|
        result = 'memory={cookie="%s",' % args['cookie']
 | 
						|
        result += ',address="%s",' % address
 | 
						|
        result += self.describeError(error)
 | 
						|
        result += ',contents="%s"}' % self.hexencode(contents)
 | 
						|
        self.report(result)
 | 
						|
 | 
						|
    def findValueByExpression(self, exp):
 | 
						|
        # FIXME: Top level-only for now.
 | 
						|
        frame = self.currentFrame()
 | 
						|
        value = frame.FindVariable(exp)
 | 
						|
        return value
 | 
						|
 | 
						|
    def assignValue(self, args):
 | 
						|
        error = lldb.SBError()
 | 
						|
        exp = self.hexdecode(args['exp'])
 | 
						|
        value = self.hexdecode(args['value'])
 | 
						|
        lhs = self.findValueByExpression(exp)
 | 
						|
        lhs.SetValueFromCString(value, error)
 | 
						|
        self.reportError(error)
 | 
						|
        self.reportVariables()
 | 
						|
 | 
						|
def convertHash(args):
 | 
						|
    if sys.version_info[0] == 3:
 | 
						|
        return args
 | 
						|
    if isinstance(args, str):
 | 
						|
        return args
 | 
						|
    if isinstance(args, unicode):
 | 
						|
        return args.encode('utf8')
 | 
						|
    cargs = {}
 | 
						|
    for arg in args:
 | 
						|
        rhs = args[arg]
 | 
						|
        if type(rhs) == type([]):
 | 
						|
            rhs = [convertHash(i) for i in rhs]
 | 
						|
        elif type(rhs) == type({}):
 | 
						|
            rhs = convertHash(rhs)
 | 
						|
        else:
 | 
						|
            try:
 | 
						|
                rhs = rhs.encode('utf8')
 | 
						|
            except:
 | 
						|
                pass
 | 
						|
        cargs[arg.encode('utf8')] = rhs
 | 
						|
    return cargs
 | 
						|
 | 
						|
 | 
						|
# Used in dumper auto test.
 | 
						|
# Usage: python lldbbridge.py /path/to/testbinary comma-separated-inames
 | 
						|
class Tester(Dumper):
 | 
						|
    def __init__(self, binary, expandedINames):
 | 
						|
        Dumper.__init__(self)
 | 
						|
        lldb.theDumper = self
 | 
						|
 | 
						|
        self.expandedINames = set(expandedINames)
 | 
						|
        self.passExceptions = True
 | 
						|
 | 
						|
        self.loadDumperFiles()
 | 
						|
        error = lldb.SBError()
 | 
						|
        self.target = self.debugger.CreateTarget(binary, None, None, True, error)
 | 
						|
 | 
						|
        if error.GetType():
 | 
						|
            warn("ERROR: %s" % error)
 | 
						|
            return
 | 
						|
 | 
						|
        s = threading.Thread(target=self.testLoop, args=[])
 | 
						|
        s.start()
 | 
						|
        s.join(30)
 | 
						|
 | 
						|
    def testLoop(self):
 | 
						|
        # Disable intermediate reporting.
 | 
						|
        savedReport = self.report
 | 
						|
        self.report = lambda stuff: 0
 | 
						|
 | 
						|
        error = lldb.SBError()
 | 
						|
        launchInfo = lldb.SBLaunchInfo([])
 | 
						|
        launchInfo.SetWorkingDirectory(os.getcwd())
 | 
						|
        environmentList = [key + "=" + value for key,value in os.environ.items()]
 | 
						|
        launchInfo.SetEnvironmentEntries(environmentList, False)
 | 
						|
 | 
						|
        self.process = self.target.Launch(launchInfo, error)
 | 
						|
        if error.GetType():
 | 
						|
            warn("ERROR: %s" % error)
 | 
						|
 | 
						|
        event = lldb.SBEvent()
 | 
						|
        listener = self.debugger.GetListener()
 | 
						|
        while True:
 | 
						|
            state = self.process.GetState()
 | 
						|
            if listener.WaitForEvent(100, event):
 | 
						|
                #warn("EVENT: %s" % event)
 | 
						|
                out = lldb.SBStream()
 | 
						|
                event.GetDescription(out)
 | 
						|
                msg = lldb.SBEvent.GetCStringFromEvent(event)
 | 
						|
                flavor = event.GetDataFlavor()
 | 
						|
                state = lldb.SBProcess.GetStateFromEvent(event)
 | 
						|
                #warn('event={type="%s",data="%s",msg="%s",flavor="%s",state="%s"}'
 | 
						|
                #    % (event.GetType(), out.GetData(), msg, flavor, state))
 | 
						|
                state = lldb.SBProcess.GetStateFromEvent(event)
 | 
						|
                if state == lldb.eStateExited: # 10
 | 
						|
                    break
 | 
						|
                if state == lldb.eStateStopped: # 5
 | 
						|
                    stoppedThread = self.firstStoppedThread()
 | 
						|
                    if stoppedThread is None:
 | 
						|
                        warn("NO STOPPED THREAD FOUND")
 | 
						|
                        for i in xrange(0, self.process.GetNumThreads()):
 | 
						|
                            thread = self.process.GetThreadAtIndex(i)
 | 
						|
                            reason = thread.GetStopReason()
 | 
						|
                            warn("THREAD: %s REASON: %s" % (thread, reason))
 | 
						|
                        continue
 | 
						|
 | 
						|
                    try:
 | 
						|
                        frame = stoppedThread.GetFrameAtIndex(0)
 | 
						|
                        break
 | 
						|
                    except:
 | 
						|
                        warn("NO FRAME FOUND FOR THREAD %s" % stoppedThread)
 | 
						|
            else:
 | 
						|
                warn('TIMEOUT')
 | 
						|
 | 
						|
 | 
						|
        stoppedThread = self.firstStoppedThread()
 | 
						|
        if not stoppedThread:
 | 
						|
            warn("Cannot determined stopped thread")
 | 
						|
            return
 | 
						|
 | 
						|
        # This seems highly fragile and depending on the "No-ops" in the
 | 
						|
        # event handling above.
 | 
						|
        self.process.SetSelectedThread(stoppedThread)
 | 
						|
 | 
						|
        frame = stoppedThread.GetFrameAtIndex(0)
 | 
						|
        #file = fileName(frame.line_entry.file)
 | 
						|
        #line = frame.line_entry.line
 | 
						|
        #warn('LOCATION={file="%s",line="%s",addr="%s"}'
 | 
						|
        #    % (file, line, frame.pc))
 | 
						|
        self.report = savedReport
 | 
						|
        self.reportVariables()
 | 
						|
        self.report("@NS@%s@" % self.qtNamespace())
 | 
						|
        #self.report("ENV=%s" % os.environ.items())
 | 
						|
        #self.report("DUMPER=%s" % self.qqDumpers)
 | 
						|
        lldb.SBDebugger.Destroy(self.debugger)
 |