import idaapi import idc from bap.utils import bap_comment, ida class Attributes(idaapi.Choose2): def __init__(self, comms): idaapi.Choose2.__init__(self, 'Select an attribute', [ ['name', 8], ['addr', 8], ['data', 64] ]) self.comms = [ [name, '{:#x}'.format(addr), ' '.join(data)] for (name, addr, data) in comms ] def OnClose(self): pass def OnGetSize(self): return len(self.comms) def OnGetLine(self, n): return self.comms[n] class BapComment(idaapi.plugin_t): flags = idaapi.PLUGIN_FIX help = 'propagate comments to IDA Views' comment = '' wanted_name = 'BAP: View BAP Attributes' wanted_hotkey = 'Shift-B' def __init__(self): self.comms = {} def init(self): ida.comment.register_handler(self.update) return idaapi.PLUGIN_KEEP def run(self, arg): comms = {} for addr in ida.addresses(): comm = idaapi.get_cmt(addr, 0) if comm: try: parsed = bap_comment.parse(comm) if parsed: for (name, data) in parsed.items(): comms[(addr, name)] = data except: idc.Message("BAP> failed to parse string {0}\n{1}". format(comm, str(sys.exc_info()[1]))) comms = [(name, addr, data) for ((addr, name), data) in comms.items()] attrs = Attributes(comms) choice = attrs.Show(modal=True) if choice >= 0: idc.Jump(comms[choice][1]) def term(self): pass def update(self, ea, key, value): """Add key=values to comm string at EA.""" cmt = idaapi.get_cmt(ea, 0) comm = cmt and bap_comment.parse(cmt) or {} values = comm.setdefault(key, []) if value and value != '()' and value not in values: values.append(value) idaapi.set_cmt(ea, bap_comment.dumps(comm), 0) def PLUGIN_ENTRY(): return BapComment()