A brief tl;dr code sample on how to map, rename and re-type variables programmatically in python.
edit: added code to set_lvar_type to allow usage of strings for types (took me ages to work that one out). now you can do things like:
mapping = [ 'accum', 'v7', 'v4', 'shift', 'v5', 'v6', 'ptr', 'v2', 'v3' ]
for n, x, y in chunk_tuple(mapping, 3):
if map_lvar(x, y, ea) and \
set_lvar_type(y, 'int32_t', ea) and \
rename_lvar(y, n, ea):
print("set {}".format(n))

just be aware that int
as a type won't work, but int32_t
will
see github for the rest of the code. don't expect this to work on IDA 6.x, though maybe it will. i've never tried.
import re
from itertools import islice
import ida_hexrays
import idaapi
import idautils
import idc
def map_lvar(src, dst, ea):
func = idaapi.get_func(ea)
if func:
ea = func.start_ea
vu = idaapi.open_pseudocode(ea, 0)
lvars1 = [n for n in vu.cfunc.lvars if n.name == src]
lvars2 = [n for n in vu.cfunc.lvars if n.name == dst]
if len(lvars1) == 1 and len(lvars2) == 1:
print("mapping {} to {}".format(lvars1[0].name, lvars2[0].name))
# we might need to change the lvar type?
vu.set_lvar_type(lvars1[0], lvars2[0].type())
vu.map_lvar(lvars1[0], lvars2[0])
else:
print("couldn't find one of the vars {} or {}".format(src, dst))
def set_lvar_type(src, t, ea):
if isinstance(t, str):
type_tuple = idaapi.get_named_type(None, t, 1)
tif = idaapi.tinfo_t()
tif.deserialize(None, type_tuple[1], type_tuple[2])
if tif:
t = tif
else:
print("couldn't convert {} into tinfo_t".format(t))
return False
func = idaapi.get_func(ea)
if func:
ea = func.start_ea
vu = idaapi.open_pseudocode(ea, 0)
if not vu:
return False
lvars = [n for n in vu.cfunc.lvars if n.name == src]
if len(lvars) == 1:
print("changing type of {} to {}".format(lvars[0].name, t))
return vu.set_lvar_type(lvars[0], t)
else:
print("couldn't find var {}".format(src))
return False
def rename_lvar(src, dst, ea):
def make_unique_name(name, taken):
if name not in taken:
return name
fmt = "%s_%%i" % name
for i in range(3, 1024):
tmpName = fmt % i
if tmpName not in taken:
return tmpName
return "i_give_up"
func = idaapi.get_func(ea)
if func:
ea = func.start_ea
vu = idaapi.open_pseudocode(ea, 0)
names = [n.name for n in vu.cfunc.lvars]
if dst in names:
dst = make_unique_name(dst, names)
lvars = [n for n in vu.cfunc.lvars if n.name == src]
if len(lvars) == 1:
print("renaming {} to {}".format(lvars[0].name, dst))
vu.rename_lvar(lvars[0], dst, 1)
# how to close the view without a widget object?
# idautils.close_pseudocode (nope)
# ida_kerwin.close_widget (nope)
else:
print("couldn't find var {}".format(src))