def _create_class_structs__slices(classinfo, endmarkers=True): """Create the IDA structs for a C++ class.""" classname = classinfo.classname # Open or create the structs. sidf = idau.struct_open(classname + '::fields', create=True) sid = idau.struct_open(classname, create=True) if sid is None or sidf is None: _log(0, 'Could not create class structs for {}', classname) return None assert all(not idc.is_union(s) for s in (sidf, sid)) # Calculate the size of the ::fields struct. if classinfo.superclass: # If we have a superclass, our fields start after our superclass's fields end. fields_start = classinfo.superclass.class_size else: # If we don't have a superclass, our fields start after our vtable. fields_start = idau.WORD_SIZE fields_size = classinfo.class_size - fields_start # Add an ::end member to the fields struct if requested. if endmarkers: ret = idc.add_struc_member(sidf, classname + '::end', fields_size, idc.FF_UNK, -1, 0) if ret not in (0, idc.STRUC_ERROR_MEMBER_NAME, idc.STRUC_ERROR_MEMBER_OFFSET): # If that didn't work that's too bad, but continue anyway. _log(0, 'Could not create {}::end', classname) return sid, sidf, fields_start
def struct_open(name, create=False, union=None): """Get the SID of the IDA struct with the given name, optionally creating it.""" sid = ida_struct.get_struc_id(name) if sid == idc.BADADDR: if not create: return None sid = struct_create(name, union=bool(union)) elif union is not None: is_union = bool(idc.is_union(sid)) if union != is_union: return None return sid
def read_struct(ea, struct=None, sid=None, members=None, asobject=False): """Read a structure from the given address. This function reads the structure at the given address and converts it into a dictionary or accessor object. Arguments: ea: The linear address of the start of the structure. Options: sid: The structure ID of the structure type to read. struct: The name of the structure type to read. members: A list of the names of the member fields to read. If members is None, then all members are read. Default is None. asobject: If True, then the struct is returned as a Python object rather than a dict. One of sid and struct must be specified. """ # Handle sid/struct. if struct is not None: sid2 = ida_struct.get_struc_id(struct) if sid2 == idc.BADADDR: raise ValueError('Invalid struc name {}'.format(struct)) if sid is not None and sid2 != sid: raise ValueError('Invalid arguments: sid={}, struct={}'.format( sid, struct)) sid = sid2 else: if sid is None: raise ValueError('Invalid arguments: sid={}, struct={}'.format( sid, struct)) if ida_struct.get_struc_name(sid) is None: raise ValueError('Invalid struc id {}'.format(sid)) # Iterate through the members and add them to the struct. union = idc.is_union(sid) struct = {} for offset, name, size in idautils.StructMembers(sid): if members is not None and name not in members: continue _read_struct_member(struct, sid, union, ea, offset, name, size, asobject) if asobject: struct = objectview(struct, ea, ida_struct.get_struc_size(sid)) return struct
def _set_class_style(style): """Set the global class style.""" global _style_was_set, _create_class_structs, _populate_class_structs assert style in (CLASS_SLICES, CLASS_UNIONS) # Check the current style based on OSObject, a class that should always exist. sid = idau.struct_open('OSObject') want_union = style == CLASS_UNIONS if sid is None: # No global style has been set. idau.struct_create('OSObject', union=want_union) else: # A style already exists. Check that the requested style matches. is_union = bool(idc.is_union(sid)) if is_union != want_union: raise ValueError('Incompatible style {}', style) # Set the appropriate functions based on the style. if style == CLASS_SLICES: _create_class_structs = _create_class_structs__slices _populate_class_structs = _populate_class_structs__slices else: _create_class_structs = _create_class_structs__unions _populate_class_structs = _populate_class_structs__unions