def _populate_vtable_struct(sid, classinfo): """Populate the ::vtable struct.""" # For each ancestor from root down to us (inclusive), add our ::vmethods struct. for ci in classinfo.ancestors(inclusive=True): # Get the offset at which the ::vmethods for ci will be. offset = 0 if ci.superclass: offset = ci.superclass.vtable_nmethods * idau.WORD_SIZE # The size is ci's vtable length minus the offset. vmethods_size = ci.vtable_nmethods * idau.WORD_SIZE - offset # If the vmethods_size is 0, skip this entry. Otherwise we get weird # "struct->til conversion failed" errors. if vmethods_size == 0: continue # Get the sid for ci's ::vmethods. vmethods_sid = idau.struct_open(ci.classname + '::vmethods') if vmethods_sid is None: _log(0, 'Could not find {}::vmethods', ci.classname) return False # Add this ::vmethods slice to the ::vtable struct. ret = idau.struct_add_struct(sid, ci.classname, offset, vmethods_sid) if ret != 0: _log(0, 'Could not add {}::vmethods to {}::vtable', ci.classname, classinfo.classname) return False return True
def _populate_wrapper_struct__slices(sid, classinfo): """Fill in the members of the wrapper struct.""" # First add the vtable pointer. offset = 0 vtable_ptr_type = '{}::vtable *'.format(classinfo.classname) ret = idau.struct_add_ptr(sid, 'vtable', offset, type=vtable_ptr_type) if ret not in (0, idc.STRUC_ERROR_MEMBER_OFFSET): _log(0, 'Could not create {}.vtable: {}', classinfo.classname, ret) return False # Now add all the ::fields structs. offset += idau.WORD_SIZE for ci in classinfo.ancestors(inclusive=True): # Get the sid of the ::fields struct. fields_sid = idau.struct_open(ci.classname + '::fields') if fields_sid is None: _log(0, 'Could not find {}::fields', ci.classname) return False # If this is a 0-length struct (no fields), skip it. size = idc.GetStrucSize(fields_sid) if size == 0: continue # If this is already in the wrapper struct, skip it. This avoids weird # STRUC_ERROR_MEMBER_VARLAST errors. if idc.GetMemberOffset(sid, ci.classname) != -1: continue # Add the ::fields struct to the wrapper. ret = idau.struct_add_struct(sid, ci.classname, offset, fields_sid) if ret != 0: _log(0, 'Could not create {}.{}: {}', classinfo.classname, ci.classname, ret) return False offset += size return True
def _populate_wrapper_struct__unions(sid, classinfo): """Fill in the members of the wrapper struct.""" # First add the vtable pointer. vtable_ptr_type = '{}::vtable *'.format(classinfo.classname) ret = idau.struct_add_ptr(sid, 'vtable', -1, type=vtable_ptr_type) if ret not in (0, idc.STRUC_ERROR_MEMBER_NAME): _log(0, 'Could not create {}.vtable: {}', classinfo.classname, ret) return False # Now add all the ::fields structs. for ci in classinfo.ancestors(inclusive=True): # Get the sid of the ::fields struct. fields_sid = idau.struct_open(ci.classname + '::fields') if fields_sid is None: _log(0, 'Could not find {}::fields', ci.classname) return False # Add the ::fields struct to the wrapper. Ignore STRUC_ERROR_MEMBER_UNIVAR if the ::fields # struct has length 0. ret = idau.struct_add_struct(sid, ci.classname, -1, fields_sid) if ret not in (0, idc.STRUC_ERROR_MEMBER_NAME, idc.STRUC_ERROR_MEMBER_UNIVAR): _log(0, 'Could not create {}.{}: {}', classinfo.classname, ci.classname, ret) return False return True