Skip to content

Commit

Permalink
Import types into IDA
Browse files Browse the repository at this point in the history
  • Loading branch information
stevemk14ebr committed Oct 12, 2023
1 parent 5764f92 commit 41c8b47
Showing 1 changed file with 69 additions and 3 deletions.
72 changes: 69 additions & 3 deletions IDAPython/goresym_rename.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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 <class>* <newname>.
# it would have made typedef struct <class> 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)
Expand Down

0 comments on commit 41c8b47

Please sign in to comment.