forked from qt-creator/qt-creator
		
	While debugging Symbian C++ applications stepping into functions has not been working due to a typo in the python file Change-Id: I76710fe3f599303059f773030e57d778164bcebb Reviewed-by: Eike Ziller <eike.ziller@nokia.com>
		
			
				
	
	
		
			342 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			342 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
 | 
						|
cdbLoaded = False
 | 
						|
lldbLoaded = False
 | 
						|
gdbLoaded = False
 | 
						|
 | 
						|
try:
 | 
						|
    #import cdb_bridge
 | 
						|
    cdbLoaded = True
 | 
						|
 | 
						|
except:
 | 
						|
    pass
 | 
						|
 | 
						|
try:
 | 
						|
    #import lldb_bridge
 | 
						|
    lldbLoaded = True
 | 
						|
 | 
						|
except:
 | 
						|
    pass
 | 
						|
 | 
						|
 | 
						|
try:
 | 
						|
    import gdb
 | 
						|
    gdbLoaded = True
 | 
						|
 | 
						|
    #######################################################################
 | 
						|
    #
 | 
						|
    # Infrastructure
 | 
						|
    #
 | 
						|
    #######################################################################
 | 
						|
 | 
						|
    def registerCommand(name, func):
 | 
						|
 | 
						|
        class Command(gdb.Command):
 | 
						|
            def __init__(self):
 | 
						|
                super(Command, self).__init__(name, gdb.COMMAND_OBSCURE)
 | 
						|
            def invoke(self, args, from_tty):
 | 
						|
                output = func(args)
 | 
						|
                try:
 | 
						|
                    print(output)
 | 
						|
                except:
 | 
						|
                    out = ""
 | 
						|
                    for c in output:
 | 
						|
                        cc = ord(c)
 | 
						|
                        if cc > 127:
 | 
						|
                            out += "\\\\%d" % cc
 | 
						|
                        elif cc < 0:
 | 
						|
                            out += "\\\\%d" % (cc + 256)
 | 
						|
                        else:
 | 
						|
                            out += c
 | 
						|
                    print(out)
 | 
						|
 | 
						|
 | 
						|
 | 
						|
        Command()
 | 
						|
 | 
						|
 | 
						|
    def isGoodGdb():
 | 
						|
        #return gdb.VERSION.startswith("6.8.50.2009") \
 | 
						|
        #   and gdb.VERSION != "6.8.50.20090630-cvs"
 | 
						|
        return 'parse_and_eval' in __builtin__.dir(gdb)
 | 
						|
 | 
						|
 | 
						|
    def parseAndEvaluate(exp):
 | 
						|
        if isGoodGdb():
 | 
						|
            return gdb.parse_and_eval(exp)
 | 
						|
        # Work around non-existing gdb.parse_and_eval as in released 7.0
 | 
						|
        gdb.execute("set logging redirect on")
 | 
						|
        gdb.execute("set logging on")
 | 
						|
        try:
 | 
						|
            gdb.execute("print %s" % exp)
 | 
						|
        except:
 | 
						|
            gdb.execute("set logging off")
 | 
						|
            gdb.execute("set logging redirect off")
 | 
						|
            return None
 | 
						|
        gdb.execute("set logging off")
 | 
						|
        gdb.execute("set logging redirect off")
 | 
						|
        return gdb.history(0)
 | 
						|
 | 
						|
 | 
						|
    def listOfLocals(varList):
 | 
						|
        frame = gdb.selected_frame()
 | 
						|
        try:
 | 
						|
            frame = gdb.selected_frame()
 | 
						|
            #warn("FRAME %s: " % frame)
 | 
						|
        except RuntimeError, error:
 | 
						|
            warn("FRAME NOT ACCESSIBLE: %s" % error)
 | 
						|
            return []
 | 
						|
        except:
 | 
						|
            warn("FRAME NOT ACCESSIBLE FOR UNKNOWN REASONS")
 | 
						|
            return []
 | 
						|
 | 
						|
        # New in 7.2
 | 
						|
        hasBlock = 'block' in __builtin__.dir(frame)
 | 
						|
 | 
						|
        items = []
 | 
						|
        #warn("HAS BLOCK: %s" % hasBlock)
 | 
						|
        if hasBlock and isGoodGdb():
 | 
						|
            #warn("IS GOOD: %s " % varList)
 | 
						|
            try:
 | 
						|
                block = frame.block()
 | 
						|
                #warn("BLOCK: %s " % block)
 | 
						|
            except RuntimeError, error:
 | 
						|
                warn("BLOCK IN FRAME NOT ACCESSIBLE: %s" % error)
 | 
						|
                return items
 | 
						|
            except:
 | 
						|
                warn("BLOCK NOT ACCESSIBLE FOR UNKNOWN REASONS")
 | 
						|
                return items
 | 
						|
 | 
						|
            shadowed = {}
 | 
						|
            while True:
 | 
						|
                if block is None:
 | 
						|
                    warn("UNEXPECTED 'None' BLOCK")
 | 
						|
                    break
 | 
						|
                for symbol in block:
 | 
						|
                    name = symbol.print_name
 | 
						|
 | 
						|
                    if name == "__in_chrg":
 | 
						|
                        continue
 | 
						|
 | 
						|
                    # "NotImplementedError: Symbol type not yet supported in
 | 
						|
                    # Python scripts."
 | 
						|
                    #warn("SYMBOL %s: " % symbol.value)
 | 
						|
                    #warn("SYMBOL %s  (%s): " % (symbol, name))
 | 
						|
                    if name in shadowed:
 | 
						|
                        level = shadowed[name]
 | 
						|
                        name1 = "%s@%s" % (name, level)
 | 
						|
                        shadowed[name] = level + 1
 | 
						|
                    else:
 | 
						|
                        name1 = name
 | 
						|
                        shadowed[name] = 1
 | 
						|
                    #warn("SYMBOL %s  (%s, %s)): " % (symbol, name, symbol.name))
 | 
						|
                    item = LocalItem()
 | 
						|
                    item.iname = "local." + name1
 | 
						|
                    item.name = name1
 | 
						|
                    try:
 | 
						|
                        item.value = frame.read_var(name, block)  # this is a gdb value
 | 
						|
                    except:
 | 
						|
                        try:
 | 
						|
                            item.value = frame.read_var(name)  # this is a gdb value
 | 
						|
                        except:
 | 
						|
                            # RuntimeError: happens for
 | 
						|
                            #     void foo() { std::string s; std::wstring w; }
 | 
						|
                            # ValueError: happens for (as of 2010/11/4)
 | 
						|
                            #     a local struct as found e.g. in
 | 
						|
                            #     gcc sources in gcc.c, int execute()
 | 
						|
                            continue
 | 
						|
                    #warn("ITEM %s: " % item.value)
 | 
						|
                    items.append(item)
 | 
						|
                # The outermost block in a function has the function member
 | 
						|
                # FIXME: check whether this is guaranteed.
 | 
						|
                if not block.function is None:
 | 
						|
                    break
 | 
						|
 | 
						|
                block = block.superblock
 | 
						|
        else:
 | 
						|
            # Assuming gdb 7.0 release or 6.8-symbianelf.
 | 
						|
            filename, file = createTempFile()
 | 
						|
            #warn("VARLIST: %s " % varList)
 | 
						|
            #warn("FILENAME: %s " % filename)
 | 
						|
            gdb.execute("set logging off")
 | 
						|
            gdb.execute("set logging redirect off")
 | 
						|
            gdb.execute("set logging file %s" % filename)
 | 
						|
            gdb.execute("set logging redirect on")
 | 
						|
            gdb.execute("set logging on")
 | 
						|
            try:
 | 
						|
                gdb.execute("info args")
 | 
						|
                # We cannot use "info locals" as at least 6.8-symbianelf
 | 
						|
                # aborts as soon as we hit unreadable memory.
 | 
						|
                # gdb.execute("interpreter mi '-stack-list-locals 0'")
 | 
						|
                # results in &"Recursive internal problem.\n", so we have
 | 
						|
                # the frontend pass us the list of locals.
 | 
						|
 | 
						|
                # There are two cases, either varList is empty, so we have
 | 
						|
                # to fetch the list here, or it is not empty with the
 | 
						|
                # first entry being a dummy.
 | 
						|
                if len(varList) == 0:
 | 
						|
                    gdb.execute("info locals")
 | 
						|
                else:
 | 
						|
                    varList = varList[1:]
 | 
						|
            except:
 | 
						|
                pass
 | 
						|
            gdb.execute("set logging off")
 | 
						|
            gdb.execute("set logging redirect off")
 | 
						|
 | 
						|
            try:
 | 
						|
                temp = open(filename, "r")
 | 
						|
                for line in temp:
 | 
						|
                    if len(line) == 0 or line.startswith(" "):
 | 
						|
                        continue
 | 
						|
                    # The function parameters
 | 
						|
                    pos = line.find(" = ")
 | 
						|
                    if pos < 0:
 | 
						|
                        continue
 | 
						|
                    varList.append(line[0:pos])
 | 
						|
                temp.close()
 | 
						|
            except:
 | 
						|
                pass
 | 
						|
            removeTempFile(filename, file)
 | 
						|
            #warn("VARLIST: %s " % varList)
 | 
						|
            for name in varList:
 | 
						|
                #warn("NAME %s " % name)
 | 
						|
                item = LocalItem()
 | 
						|
                item.iname = "local." + name
 | 
						|
                item.name = name
 | 
						|
                try:
 | 
						|
                    item.value = frame.read_var(name)  # this is a gdb value
 | 
						|
                except RuntimeError:
 | 
						|
                    pass
 | 
						|
                    #continue
 | 
						|
                except:
 | 
						|
                    # Something breaking the list, like intermediate gdb warnings
 | 
						|
                    # like 'Warning: can't find linker symbol for virtual table for
 | 
						|
                    # `std::less<char const*>' value\n\nwarning:  found
 | 
						|
                    # `myns::QHashData::shared_null' instead [...]
 | 
						|
                    # that break subsequent parsing. Chicken out and take the
 | 
						|
                    # next "usable" line.
 | 
						|
                    continue
 | 
						|
                items.append(item)
 | 
						|
 | 
						|
        return items
 | 
						|
 | 
						|
 | 
						|
    def catchCliOutput(command):
 | 
						|
        try:
 | 
						|
            return gdb.execute(command, to_string=True).split("\n")
 | 
						|
        except:
 | 
						|
            pass
 | 
						|
        filename, file = createTempFile()
 | 
						|
        gdb.execute("set logging off")
 | 
						|
        gdb.execute("set logging redirect off")
 | 
						|
        gdb.execute("set logging file %s" % filename)
 | 
						|
        gdb.execute("set logging redirect on")
 | 
						|
        gdb.execute("set logging on")
 | 
						|
        msg = ""
 | 
						|
        try:
 | 
						|
            gdb.execute(command)
 | 
						|
        except RuntimeError, error:
 | 
						|
            # For the first phase of core file loading this yield
 | 
						|
            # "No symbol table is loaded.  Use the \"file\" command."
 | 
						|
            msg = str(error)
 | 
						|
        except:
 | 
						|
            msg = "Unknown error"
 | 
						|
        gdb.execute("set logging off")
 | 
						|
        gdb.execute("set logging redirect off")
 | 
						|
        if len(msg):
 | 
						|
            # Having that might confuse result handlers in the gdbengine.
 | 
						|
            #warn("CLI ERROR: %s " % msg)
 | 
						|
            return "CLI ERROR: %s " % msg
 | 
						|
        temp = open(filename, "r")
 | 
						|
        lines = []
 | 
						|
        for line in temp:
 | 
						|
            lines.append(line)
 | 
						|
        temp.close()
 | 
						|
        removeTempFile(filename, file)
 | 
						|
        return lines
 | 
						|
 | 
						|
    #######################################################################
 | 
						|
    #
 | 
						|
    # Types
 | 
						|
    #
 | 
						|
    #######################################################################
 | 
						|
 | 
						|
    PointerCode = gdb.TYPE_CODE_PTR
 | 
						|
    ArrayCode = gdb.TYPE_CODE_ARRAY
 | 
						|
    StructCode = gdb.TYPE_CODE_STRUCT
 | 
						|
    UnionCode = gdb.TYPE_CODE_UNION
 | 
						|
    EnumCode = gdb.TYPE_CODE_ENUM
 | 
						|
    FlagsCode = gdb.TYPE_CODE_FLAGS
 | 
						|
    FunctionCode = gdb.TYPE_CODE_FUNC
 | 
						|
    IntCode = gdb.TYPE_CODE_INT
 | 
						|
    FloatCode = gdb.TYPE_CODE_FLT # Parts of GDB assume that this means complex.
 | 
						|
    VoidCode = gdb.TYPE_CODE_VOID
 | 
						|
    #SetCode = gdb.TYPE_CODE_SET
 | 
						|
    RangeCode = gdb.TYPE_CODE_RANGE
 | 
						|
    StringCode = gdb.TYPE_CODE_STRING
 | 
						|
    #BitStringCode = gdb.TYPE_CODE_BITSTRING
 | 
						|
    #ErrorTypeCode = gdb.TYPE_CODE_ERROR
 | 
						|
    MethodCode = gdb.TYPE_CODE_METHOD
 | 
						|
    #MethodPointerCode = gdb.TYPE_CODE_METHODPTR
 | 
						|
    #MemberPointerCode = gdb.TYPE_CODE_MEMBERPTR
 | 
						|
    ReferenceCode = gdb.TYPE_CODE_REF
 | 
						|
    CharCode = gdb.TYPE_CODE_CHAR
 | 
						|
    BoolCode = gdb.TYPE_CODE_BOOL
 | 
						|
    ComplexCode = gdb.TYPE_CODE_COMPLEX # Fortran ?
 | 
						|
    TypedefCode = gdb.TYPE_CODE_TYPEDEF
 | 
						|
    NamespaceCode = gdb.TYPE_CODE_NAMESPACE
 | 
						|
    #Code = gdb.TYPE_CODE_DECFLOAT # Decimal floating point.
 | 
						|
    #Code = gdb.TYPE_CODE_MODULE # Fortran
 | 
						|
    #Code = gdb.TYPE_CODE_INTERNAL_FUNCTION
 | 
						|
 | 
						|
    #######################################################################
 | 
						|
    #
 | 
						|
    # Step Command
 | 
						|
    #
 | 
						|
    #######################################################################
 | 
						|
 | 
						|
    def sal(args):
 | 
						|
        (cmd, addr) = args.split(",")
 | 
						|
        lines = catchCliOutput("info line *" + addr)
 | 
						|
        fromAddr = "0x0"
 | 
						|
        toAddr = "0x0"
 | 
						|
        for line in lines:
 | 
						|
            pos0from = line.find(" starts at address") + 19
 | 
						|
            pos1from = line.find(" ", pos0from)
 | 
						|
            pos0to = line.find(" ends at", pos1from) + 9
 | 
						|
            pos1to = line.find(" ", pos0to)
 | 
						|
            if pos1to > 0:
 | 
						|
                fromAddr = line[pos0from : pos1from]
 | 
						|
                toAddr = line[pos0to : pos1to]
 | 
						|
        gdb.execute("maint packet sal%s,%s,%s" % (cmd,fromAddr, toAddr))
 | 
						|
 | 
						|
    registerCommand("sal", sal)
 | 
						|
 | 
						|
 | 
						|
    #######################################################################
 | 
						|
    #
 | 
						|
    # Convenience
 | 
						|
    #
 | 
						|
    #######################################################################
 | 
						|
 | 
						|
    # Just convienience for 'python print ...'
 | 
						|
    class PPCommand(gdb.Command):
 | 
						|
        def __init__(self):
 | 
						|
            super(PPCommand, self).__init__("pp", gdb.COMMAND_OBSCURE)
 | 
						|
        def invoke(self, args, from_tty):
 | 
						|
            print(eval(args))
 | 
						|
 | 
						|
    registerCommand("pp", pp)
 | 
						|
        
 | 
						|
    # Just convienience for 'python print gdb.parse_and_eval(...)'
 | 
						|
    class PPPCommand(gdb.Command):
 | 
						|
        def __init__(self):
 | 
						|
            super(PPPCommand, self).__init__("ppp", gdb.COMMAND_OBSCURE)
 | 
						|
        def invoke(self, args, from_tty):
 | 
						|
            print(gdb.parse_and_eval(args))
 | 
						|
 | 
						|
    PPPCommand()
 | 
						|
 | 
						|
except:
 | 
						|
    pass
 | 
						|
 |