stx/gdb/objects/__init__.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

class __instance ( object ):
    """
    Generic object representation. Instance of this class
    also implements gdb pretty-printing API and could therefore
    used as a pretty printer
    """

    def __init__(self, val):
        #stx.support.Decorator.__init__(self, val)
        #object.__setattr__(self, "_klass", None)
        self._obj = val
        self._klass = None

    def display_hint(self):
        '''
        Pretty printer API
        '''
        return None

    def to_string(self):
        '''
        Pretty printer API: Returns a human-readable represenation of the object.
        '''
        return self.display_string()

    def __repr__(self):
        return self.display_string()

    def display_string(self):
        try:
            value = self.display_value()
            klassName = '???'

            klass = self.klass
            if klass == None:
                klassName = '?None?'
            else:
                klassName = klass.name
            if (value == None):
                return "0x%08x (%s)" % ( self.address , klassName )
            else:
                return "0x%08x (%s %s)" % ( self.address , klassName , value )
        except:
            survStartPtr = long(gdb.parse_and_eval("__survStartPtr"))
            survEndPtr = long(gdb.parse_and_eval("__survEndPtr"))
            if (survStartPtr <= self.address and self.address <= survEndPtr):
                return "0x%08x (** survivor **)" % self.address
            return "0x%08x (** err **)" % self.address

    def display_value(self):
        '''
        Return a human-readable represenation of object's value, if sensible.
        FOr instance, for integer or string it may be its respective value
        '''
        return None

    @property
    def address(self):
        '''Return the address of the object in memory'''
        return long(self._obj);

    @property
    def klass(self):
        '''Return this object's class as an __instance value'''
        if (self._klass == None):
            self._klass = create(self._obj['o_class'])
        return self._klass

    @property
    def size(self):
        '''Return size of the objects in slots (excluding header)'''
        # Not really 64bit safe...
        return (self.size_b() - 12) / 4

    def size_b(self):
        '''Return size of the object in bytes, including header'''
        return self._obj['o_size']

    @property
    def flags(self):
        return self._obj['o_flags']


# Some flags defined in stc.h.
# !!! MAKE SURE they are in sync !!!

BYTEARRAY       = 1
WORDARRAY       = 2
LONGARRAY       = 3
POINTERARRAY    = 4
WKPOINTERARRAY  = 5
FLOATARRAY      = 6
DOUBLEARRAY     = 7
SWORDARRAY      = 8
SLONGARRAY      = 9
LONGLONGARRAY   = 10
SLONGLONGARRAY  = 11
#
# reserved:       13-15
#

ARRAYMASK       = 0x0F

BEHAVIOR_INSTS  = 0x0010
FLOAT_INSTS     = 0x0020
BLOCK_INSTS     = 0x0040
METHOD_INSTS    = 0x0080
CONTEXT_INSTS   = 0x0100
BCONTEXT_INSTS  = 0x0200
SYMBOL_INSTS    = 0x0400

NONOBJECT_INSTS = 0x0800
EXTERNALBYTES_INSTS = 0x1000
EXTFUNC_INSTS   = 0x010000



def create(val):
    import stx.gdb.objects.stx_libbasic
    addr = long(val)

    # Here we should care for free/non objects
    # by comparing address agains newspace
    # boundaries.
    # Well, later :-)

    if (addr == 0):
        return stx.gdb.objects.stx_libbasic.nil

    if ((addr & 1) == 1):
        return stx.gdb.objects.stx_libbasic.SmallInteger(val)
    flags = long(val['o_class']['i_instvars'][1])
    if ((flags & 1) == 1):
        flags = flags >> 1
    else:
        raise Exception("Memory corruption? Class flags are not SmallInteger.")

    if ((flags & BEHAVIOR_INSTS) != 0):
        # Care for anonymous classes
        size = (val['o_size'] - 12) / 4 # Not 64bit safe
        if (size == 5):
            return stx.gdb.objects.stx_libbasic.Behavior(val)
        if (size == 6):
            return stx.gdb.objects.stx_libbasic.ClassDescription(val)
        if (size >= 17):
            return stx.gdb.objects.stx_libbasic.Class(val)
        if (size >= 7):
            return stx.gdb.objects.stx_libbasic.Metaclass(val)

        raise Exception("Funny behaviour-like size (%s)" % size)

    if ((flags & SYMBOL_INSTS) != 0):
        return stx.gdb.objects.stx_libbasic.Symbol(val)

    return __instance(val)