diff --git a/IDAPython/goresym_rename.py b/IDAPython/goresym_rename.py index 9c7f53a..ea0d07e 100644 --- a/IDAPython/goresym_rename.py +++ b/IDAPython/goresym_rename.py @@ -18,6 +18,64 @@ def iterable(obj): else: return True +# https://gist.github.com/NyaMisty/693db2ce2e75c230f36b628fd7610852 +# 'Synchonize to idb' right click equivalent +def resync_local_types(): + def is_autosync(name, tif): + return idaapi.get_ordinal_from_idb_type(name, tif.get_decltype().to_bytes(1, 'little')) != -1 + + for ord in range(1, idaapi.get_ordinal_qty(None)): + t = idaapi.tinfo_t() + t.get_numbered_type(None, ord) + typename = t.get_type_name() + if typename.startswith('#'): + continue + + autosync = is_autosync(typename, t) + #print('Processing struct %d: %s%s' % (ord, typename, ' (autosync) ' if autosync else '')) + idaapi.import_type(None, -1, typename, idaapi.IMPTYPE_OVERRIDE) + if autosync: + continue + struc = idaapi.get_struc(idaapi.get_struc_id(typename)) + if not struc: + continue + struc.ordinal = -1 + idaapi.save_struc(struc, False) + +def import_primitives(): + type_map = { + "BUILTIN_STRING": "string", + "uint8_t": "uint8", + "uint16_t": "uint16", + "uint32_t": "uint32", + "uint64_t": "uint64", + "int8_t": "int8", + "int16_t": "int16", + "int32_t": "int32", + "double": "float64", + "float": "float32", + "complex64_t": "complex64", + "complex128_t": "complex128", + "void*": "uintptr", # should be uint64 or uint32 depending on ptr size, but this works too + "uint8": "byte", + "int32": "rune", + "int": "void*" # int in GO depends on architecture size + } + + ida_typeinf.idc_parse_types("struct BUILTIN_INTERFACE{void *tab;void *data;};", ida_typeinf.HTI_PAKDEF | ida_typeinf.HTI_DCL) + ida_typeinf.idc_parse_types("struct BUILTIN_STRING{char *ptr;size_t len;};", ida_typeinf.HTI_PAKDEF | ida_typeinf.HTI_DCL) + + ida_typeinf.idc_parse_types("struct complex64_t{float real;float imag;};", ida_typeinf.HTI_PAKDEF | ida_typeinf.HTI_DCL) + ida_typeinf.idc_parse_types("struct complex128_t{double real;double imag;};", ida_typeinf.HTI_PAKDEF | ida_typeinf.HTI_DCL) + + for ida_type, gotype in type_map.items(): + ida_typeinf.idc_parse_types(f"typedef {ida_type} {gotype};", ida_typeinf.HTI_PAKDEF | ida_typeinf.HTI_DCL) + +def forward_declare_structs(types): + for typ in types: + if typ['Kind'] == 'Struct': + ida_typeinf.idc_parse_types(f"struct {typ['CStr']};", ida_typeinf.HTI_PAKDEF | ida_typeinf.HTI_DCL) + hints = ida_kernwin.ask_file(0, "*.*", "GoReSym output file") with open(hints, "r", encoding="utf-8") as rp: buf = rp.read() @@ -40,13 +98,21 @@ def iterable(obj): idaapi.set_name(func['Start'], func['FullName'], idaapi.SN_NOWARN | idaapi.SN_NOCHECK | ida_name.SN_FORCE) if iterable(hints['Types']): - ## import all the types first (reverse order, so that child types imported first) + import_primitives() + + # we must do this to prevent IDA from creating an invalid struct of type int when we import things like typedef * . + # it would have made typedef struct int; without a forward declaration. That would then break importing the class later with redefinition error. + forward_declare_structs(hints['Types']) + for typ in hints['Types'][::-1]: if typ.get('CReconstructed'): - errors = ida_typeinf.idc_parse_types(typ['CReconstructed'] + ";", ida_typeinf.HTI_PAKDEF) + errors = ida_typeinf.idc_parse_types(typ['CReconstructed'] + ";", ida_typeinf.HTI_PAKDEF | ida_typeinf.HTI_DCL) if errors > 0: print(typ['CReconstructed'], "failed to import") - + + # just for precation + resync_local_types() + for typ in hints['Types']: print("Renaming %s to %s" % (hex(typ['VA']), typ['Str'])) idaapi.set_name(typ['VA'], typ['Str'], idaapi.SN_NOWARN | idaapi.SN_NOCHECK | ida_name.SN_FORCE)