def _isLoadableMember(self, attr, attrname, attrtype): """ Check if the member is loadable. A c_void_p cannot be load generically, You have to take care of that. (Pointers with valid address space value AND (pointee is a struct type OR pointee is a union type) ) OR struct type OR union type """ ctypes = self._mappings_.config.ctypes return ((bool(attr) and not ctypes.is_pointer_to_void_type(attrtype)))
def toString(cls): import ctypes fieldsStrings = [] for attrname, attrtyp in cls.getFields(): # model if ctypes.is_pointer_type(attrtyp) and not ctypes.is_pointer_to_void_type(attrtyp): fieldsStrings.append("(%s, ctypes.POINTER(%s) ),\n" % (attrname, attrtyp._type_.__name__)) else: # pointers not in the heap. fieldsStrings.append("(%s, %s ),\n" % (attrname, attrtyp.__name__)) fieldsString = "[ \n%s ]" % ("".join(fieldsStrings)) info = "size:%d" % (ctypes.sizeof(cls)) ctypes_def = """ class %s(ctypes.Structure): # %s _fields_ = %s """ % ( cls.__name__, info, fieldsString, ) return ctypes_def
def _attrToPyObject(self, attr, field, attrtype): import ctypes if ctypes.is_basic_type(attrtype): if ctypes.is_basic_ctype(type(attr)): obj = attr.value else: obj = attr elif ctypes.is_struct_type(attrtype) or ctypes.is_union_type(attrtype): attr._mappings_ = self.mappings obj = self.parse(attr) elif ctypes.is_array_of_basic_type(attrtype): # return a list of int, float, or a char[] to str obj = utils.ctypes_to_python_array(attr) elif ctypes.is_array_type(attrtype): # array of something else than int/byte obj = [] eltyp = type(attr[0]) for i in range(0, len(attr)): obj.append(self._attrToPyObject(attr[i], i, eltyp)) elif ctypes.is_cstring_type(attrtype): obj = self.mappings.getRef( ctypes.CString, utils.get_pointee_address( attr.ptr)) elif ctypes.is_function_type(attrtype): obj = repr(attr) elif ctypes.is_pointer_type(attrtype): # get the cached Value of the LP. _subtype = get_subtype(attrtype) _address = utils.get_pointee_address(attr) if _address == 0: # Null pointer obj = None elif ctypes.is_pointer_to_void_type(attrtype): # TODO: make a prototype for c_void_p loading # void types a rereturned as None obj = None elif ctypes.is_array_of_basic_type(attrtype): log.error('basic Type array - %s' % (field)) obj = 'BasicType array' else: # get the cached Value of the LP. _subtype = get_subtype(attrtype) cache = self.mappings.getRef(_subtype, _address) if cache is not None: # struct, union... obj = self._attrToPyObject(cache, field, _subtype) else: # you got here because your pointer is not loaded: # did you ignore it in expectedValues ? # is it in the middle of a struct ? # is that a linked list ? # is it a invalid instance ? log.debug('Pointer for field:%s %s/%s not in cache ' '0x%x' % (field, attrtype, get_subtype(attrtype), _address)) return (None, None) elif isinstance(attr, numbers.Number): # case for int, long. But needs to be after c_void_p pointers case obj = attr else: log.error('toPyObj default to return attr %s' % (type(attr))) obj = attr return obj
def _isValidAttr(self, attr, attrname, attrtype, mappings): """ Validation of a single member """ import ctypes # a) log.debug('valid: %s, %s' % (attrname, attrtype)) if ctypes.is_basic_type(attrtype): if attrname in self.expectedValues: if attr not in self.expectedValues[attrname]: log.debug( 'basicType: %s %s %s bad value not in self.expectedValues[attrname]:' % (attrname, attrtype, repr(attr))) return False log.debug( 'basicType: %s %s %s ok' % (attrname, attrtype, repr(attr))) return True # b) elif ctypes.is_struct_type(attrtype) or ctypes.is_union_type(attrtype): # do i need to load it first ? becaus it should be memcopied with # the super().. if not attr.isValid(mappings): log.debug( 'structType: %s %s %s isValid FALSE' % (attrname, attrtype, repr(attr))) return False log.debug( 'structType: %s %s %s isValid TRUE' % (attrname, attrtype, repr(attr))) return True # c) elif ctypes.is_array_of_basic_type(attrtype): if attrname in self.expectedValues: if attr not in self.expectedValues[attrname]: log.debug( 'basicArray: %s %s %s - bad value not in self.expectedValues[attrname]:' % (attrname, attrtype, type(attr))) return False log.debug( 'basicArray: %s is arraytype %s we decided it was valid', attrname, type(attr)) return True # d) elif ctypes.is_array_type(attrtype): log.debug('array: %s is arraytype %s recurse validate' % (attrname, repr(attr))) attrLen = len(attr) if attrLen == 0: return True elType = type(attr[0]) for i in range(0, attrLen): # FIXME BUG DOES NOT WORK - offsetof("%s[%d]") is called, # and %s exists, not %s[%d] if not self._isValidAttr(attr[i], "%s[%d]" % (attrname, i), elType, mappings): return False return True # e) elif ctypes.is_cstring_type(attrtype): myaddress = utils.get_pointee_address(attr.ptr) if attrname in self.expectedValues: # test if NULL is an option if not bool(myaddress): if not ((None in self.expectedValues[attrname]) or (0 in self.expectedValues[attrname])): log.debug('str: %s %s %s isNULL - NOT EXPECTED' % ( attrname, attrtype, repr(attr))) return False log.debug('str: %s %s %s isNULL - OK' % (attrname, attrtype, repr(attr))) # e.1) return True if (myaddress != 0 and not mappings.is_valid_address_value(myaddress)): log.debug('str: %s %s %s 0x%lx INVALID' % (attrname, attrtype, repr(attr), myaddress)) # e.2) return False log.debug('str: %s %s %s is at 0x%lx OK' % (attrname, attrtype, repr(attr), myaddress)) # e.3) return True # f) elif ctypes.is_pointer_type(attrtype): myaddress = utils.get_pointee_address(attr) if attrname in self.expectedValues: # test if NULL is an option log.debug('ctypes.is_pointer_type: bool(attr):%s attr:%s' % ( bool(attr), attr)) if not bool(myaddress): if not ((None in self.expectedValues[attrname]) or (0 in self.expectedValues[attrname])): log.debug('ptr: %s %s %s isNULL - NOT EXPECTED' % ( attrname, attrtype, repr(attr))) # f.1) expectedValues specifies NULL to be invalid return False log.debug('ptr: %s %s %s isNULL - OK' % (attrname, attrtype, repr(attr))) # f.2) expectedValues specifies NULL to be valid return True _attrType = None if (ctypes.is_pointer_to_void_type(attrtype) or ctypes.is_function_type(attrtype)): log.debug( 'Its a simple type. Checking mappings only. attr=%s' % (attr)) if (myaddress != 0 and not mappings.is_valid_address_value(myaddress)): log.debug('voidptr: %s %s %s 0x%lx INVALID simple pointer' % ( attrname, attrtype, repr(attr), myaddress)) # f.3) address must be valid, no type requirement return False else: # test valid address mapping _attrType = get_subtype(attrtype) if (myaddress != 0 and not mappings.is_valid_address(attr, _attrType)): log.debug('ptr: %s %s %s 0x%lx INVALID' % (attrname, attrtype, repr(attr), utils.get_pointee_address(attr))) # f.4) its a pointer, but not valid in our mappings for this # pointee type. return False log.debug('ptr: name:%s repr:%s address:0x%lx OK' % (attrname, repr(attr), utils.get_pointee_address(attr))) # f.5) null is accepted by default return True # g) log.error('What type are You ?: %s/%s' % (attrname, attrtype)) return True