stx/gdb/commands.py
author Jan Vrany <jan.vrany@fit.cvut.cz>
Thu, 09 Apr 2015 15:04:14 +0100
changeset 4 ca45a88235bd
parent 2 ef575a931434
permissions -rw-r--r--
Minor fixes in GDB scripts.

import gdb
import stx.support
import stx.util


class CFrameDecorator ( stx.support.Decorator ):
    """An abstract gdb.Frame decorator"""

    @staticmethod
    def decorate(frame):
    	function = frame.function()
    	if function == None:
	    return CFrameDecorator_jit(frame)
        if function.name == '__jInterpret':
            return CFrameDecorator_jInterpret(frame)
        else:
            c , s = stx.util.demangle(frame.name())
            if (c != None):
                if (s != None):
                    return CFrameDecorator_stcMethod(frame, c, s)
            return CFrameDecorator(frame)

    def __str__(self):
        kind = self.kind()
        if kind != None:
            kind = "%2s" % kind
        else:
            kind = '  '
        return "%3s 0x%8x %s ( %s)" % (
            kind ,
            self.pc(),
            self.name() ,
            self.args_string() )

    def older(self):
        older = self._obj.older()
        if older == None:
            return None
        # special case, because of longjmp(), parent frame-point might point
        # to clean area, filled by 0xa5a5a5a5 (malloc() does this)
        if older.pc() != 0xa5a5a5a5:
            return CFrameDecorator.decorate(older)
        else:
            return None

    def newer(self):
        return CFrameDecorator.decorate(self._obj.newer())

    def kind(self):
        """Returns 3 char identification of frame kind or None"""
        return None # generic frame

    def function_block(self):
        """Returns a top-level block (i.e., block for the function)"""
        b = self._obj.block()
        while b.function == None:
            b = b.superblock
        return b

    def args_string(self):
        """Returns a string representation of arguments"""
        s = ''
        for sym in self.function_block():
            if sym.is_argument:
                s = s + self.arg_string(sym) + ' '
        return s

    def arg_string(self, sym):
        """Given an argument symbol, returns its string representation"""
        val = self._obj.read_var(sym, self._obj.block())
        return "%s=%s" % ( sym.print_name , val )

class CFrameDecorator_jInterpret ( CFrameDecorator ):

    def kind(self):
        return "J-I"

class CFrameDecorator_jit ( CFrameDecorator ):

    def kind(self):
        return "?-J"

    def function_block(self):
    	return []

    def name(self):
    	return "???"


class CFrameDecorator_stcMethod ( CFrameDecorator ):
    def __init__(self, frame, className = None, selectorValue = None):
        CFrameDecorator.__init__(self, frame)
        c = className
        s = selectorValue
        if (c == None or s == None):
            c, s = stx.util.demangle(frame.name())
        self.klassName = c
        self.selectorValue = s

    def name(self):
        return "%s >> #%s" % ( self.klassName, self.selectorValue )


    def kind(self):
        return "S-C"

class Backtrace ( gdb.Command ):
    '''
    Prints a VM backtrace.

    Print additional information for well-known VM functions such
    as __interpret, __jinterpret, etc.
    '''

    def __init__ ( self ):
        super (Backtrace, self).__init__("btx", gdb.COMMAND_STACK)

    def invoke ( self , args , from_tty ):
        try:
            argv = gdb.string_to_argv(args)
            limit = None
            if len(argv) == 1:
                limit = int(argv[0])
            fno = 0
            frame = CFrameDecorator.decorate(gdb.newest_frame())
            framesel = gdb.selected_frame()
            while ( frame != None ) and ( limit == None or fno < limit ):
                if frame.target() == framesel:
                    star = '*'
                else:
                    star = ' '
                print "%s%3d %s" % (star, fno , frame )
                frame = frame.older()
                fno = fno +1
        except:
            import traceback
            import sys
            traceback.print_exc(file=sys.stdout)

Backtrace()