def apply(ea, st): '''Apply the structure ``st`` to the address at ``ea``.''' ea = interface.address.inside(ea) ti, fl = idaapi.opinfo_t(), database.type.flags(ea) res = idaapi.get_opinfo(ea, 0, fl, ti) ti.tid = st.id return idaapi.set_opinfo(ea, 0, fl | idaapi.struflag(), ti)
def apply(ea, st): """Apply the structure ``st`` to the address at ``ea``""" ti = idaapi.opinfo_t() res = idaapi.get_opinfo(ea, 0, idaapi.getFlags(ea), ti) ti.tid = st.id return idaapi.set_opinfo(ea, 0, idaapi.getFlags(ea) | idaapi.struflag(), ti)
def yatest_apply_struct(self): addrs = [] # -1: struct, n: union for k in range(-1, 4): # find an integer operand in any function addr = self.find_operand_addr() addrs.append(addr) # create struct sid = idc.AddStrucEx(-1, 'apply_struct_%x' % (k + 1), 0) self.assertNotEqual(sid, -1) ftype = idaapi.FF_BYTE | idaapi.FF_DATA # apply struct only if k == -1: # add struct fields for x in xrange(0, 0x60): self.assertEqual( idc.AddStrucMember(sid, 'field_%x' % x, -1, ftype, -1, 1), 0) path = idaapi.tid_array(1) path[0] = sid self.assertNotEqual( self.custom_op_stroff(addr, path.cast(), 1), idaapi.BADADDR) continue # create union uid = idc.AddStrucEx(-1, 'apply_union_%x' % (k + 1), 1) self.assertNotEqual(uid, -1) for x in xrange(1, 0x10): self.assertEqual( idc.AddStrucMember(uid, 'union_%x' % x, -1, ftype, -1, 1), 0) # add struct fields for x in xrange(0, 0x60): self.assertEqual( idc.AddStrucMember(sid, 'field_%x' % x, -1, idaapi.struflag(), uid, 1), 0) # apply selected union field fid = idc.GetMemberId(uid, k) self.assertNotEqual(fid, -1) path = idaapi.tid_array(2) path[0] = sid path[1] = fid self.assertNotEqual(self.custom_op_stroff(addr, path.cast(), 2), idaapi.BADADDR) yaunit.save('apply_struct', addrs)
def resolve(cls, type): """Return ida's (flag,typeid,size) given the type (type,size) or (type/instance) (int,4) -- a dword ([int,4],8) -- an array of 8 dwords (str,10) -- an ascii string of 10 characters (int,2) -- a word (chr,4) -- an array of 4 characters """ # FIXME: Array definitions seem awkward, I think they should look # like [type, length] and so an array of 4 words should be # [(int,2), 4] # return idaapi.FF_xxx, typeid, and size given a tuple (type,size) or just a type/instance type, nbytes = type if isinstance(type, tuple) else (type, None) # FIXME: this explicit checking of nbytes being None is sloppy size = 0 if nbytes is None else abs(nbytes) # structure -- structure_t if isinstance(type, structure_t): flag, typeid = idaapi.struflag(), type.id elif type is None: flag, typeid = idaapi.alignflag(), -1 elif isinstance(type, [].__class__): flag, typeid, nb = cls.resolve( tuple(type)) if len(type) > 1 else cls.resolve(*type) size = nb if nbytes is None else (size * nb) # FIXME # defined in typemap -- (type,size) else: table = cls.typemap[type] if type in (int, long, float, type): flag, typeid = table[None if nbytes is None else size] # FIXME else: flag, typeid = table[type] # automatically determine the size for the requested typeid if nbytes is None: opinfo = idaapi.opinfo_t() opinfo.tid = typeid size = idaapi.get_data_type_size(flag, opinfo) elif nbytes < 0: flag |= idaapi.signed_data_flag() return flag, typeid, size
def resolve(cls, pythonType): """Return ida's (flag,typeid,size) given the type (type,size) or (type/instance) (int,4) -- a dword [(int,4),8] -- an array of 8 dwords (str,10) -- an ascii string of 10 characters (int,2) -- a word [chr,4] -- an array of 4 characters """ sz, count = None, 1 # FIXME: figure out how to fix this recursive module dependency # figure out what format pythonType is in if isinstance(pythonType, ().__class__): (t, sz), count = pythonType, 1 table = cls.typemap[t] flag, typeid = table[abs(sz) if t in (int, long, float, type) else t] elif isinstance(pythonType, [].__class__): # an array, which requires us to recurse... res, count = pythonType flag, typeid, sz = cls.resolve(res) elif isinstance( pythonType, sys.modules.get('structure', __import__('structure')).structure_t): # it's a structure, pass it through. flag, typeid, sz = idaapi.struflag( ), pythonType.id, pythonType.size else: # default size that we can lookup in the typemap table table = cls.typemap[pythonType] flag, typeid = table[None] opinfo = idaapi.opinfo_t() opinfo.tid = typeid return flag, typeid, idaapi.get_data_elsize( idaapi.BADADDR, flag, opinfo) return flag | (idaapi.FF_SIGN if sz < 0 else 0), typeid, abs(sz) * count