# # Paste this def into the console, then run it, and then paste the output into the_types down below: # def dump_types(clip=True, void=True, verbose=False): def make_call_type(name, type): return f'{type.return_value} {name}({",".join(map(str,type.parameters))})' _print = print if not verbose: _print = lambda *a, **kw: None fun_dump = [] for f in bv.functions: adjustments = [] # for ref in f.caller_sites: for ref in sorted(f.call_sites,key=lambda ref:ref.address): # _print(f'{f = } {ref = }') adjustment = ref.function.get_call_type_adjustment(ref.address) if adjustment is not None: #adjustments.append((str(ref.hlil.dest), ref.function.name, str(adjustment))) dest = str(ref.hlil.dest) adjustments.append((dest, ref.function.name, make_call_type(dest, adjustment))) # _print(f'{adjustments = !r}') tag = f'{bv.arch.name}:{f.start:08X}' fun_dump.append(f'{tag!r}:(0x{f.start:08X},{bv.arch.name!r},"fun",({bv.get_sections_at(f.start)[0].name!r},{f.name!r},{str(f)!r},{str(f.clobbered_regs.regs)},{str(f.return_regs.regs)},{adjustments})),') _ = _print(fun_dump[-1]) _ = _print() for v in bv.data_vars: f = bv.get_data_var_at(v) if f.type.type_class == TypeClass.FunctionTypeClass: sections = bv.get_sections_at(f.address) if not sections: sec_name = '' else: sec_name = sections[0].name #t = f'{f.type.return_value} {f.name}({",".join(map(str,f.type.parameters))})' t = make_call_type(f.name, f.type) tag = f'{bv.arch.name}:{f.address:08X}' fun_dump.append(f'{tag!r}:(0x{f.address:08X},{bv.arch.name!r},"var",({sec_name!r},{f.name!r},{t!r})),') _ = _print(fun_dump[-1]) _ = _print() if clip: clipboard.text = '\n\t' + '\n\t'.join(fun_dump) if not void: return fun_dump the_types = { } bv.begin_undo_actions() for item in the_types.items(): tag, (address, arch_name, fun_var, rest) = item print(f'0x{address:08x}:{item[1]}') if arch_name != bv.arch.name: continue sec_name, name, type_str = rest[:3] the_type = bv.parse_type_string(type_str) if not the_type: log_warn(f'failed to parse function type for {name} found 0x{address:08x}: {type_str!r}') continue is_fun = fun_var == "fun" if not is_fun: v = None v = bv.get_data_var_at(address) if v and sec_name: s = bv.get_sections_at(v.address) if s and s[0].name != sec_name: v = None if not v: for symbol in bv.get_symbols_by_name(name): s = bv.get_sections_at(symbol.address) log_warn(f'0x{symbol.address:08x} {symbol.name} {symbol.type.name} {s}') if s and s[0].name != sec_name: continue if symbol.type in [SymbolType.FunctionSymbol, SymbolType.ExternalSymbol, SymbolType.ImportedFunctionSymbol, SymbolType.DataSymbol]: v = bv.get_data_var_at(symbol.address) if v: log_warn(f'0x{v.address:08X}:({bv.arch.name!r},"var",{v.name!r},{str(v.type)!r},[],[]),') break if v is not None: print(f'0x{v.address:08X}:({bv.arch.name!r},"var",{v.name!r},{str(v.type)!r},[],[]),') v.name = name v.type = the_type[0] v = bv.get_data_var_at(v.address) print(f'0x{v.address:08X}:({bv.arch.name!r},"var",{v.name!r},{str(v.type)!r},[],[]),') else: log_warn(f'no appropriate var {name} found at 0x{address:08x} or in section {sec_name}') continue clobbered_regs, return_regs, adjustments = rest[3:] f = bv.get_function_at(address) if not f or f.name != name: fs = bv.get_functions_by_name(name) if fs: f = fs[0] if not f: log_warn(f'no function {name} found at 0x{address:08x}') continue if the_type: f.set_user_type(the_type[0]) else: log_warn(f'failed to parse function type for {name} found 0x{address:08x}: {type_str!r}') continue if clobbered_regs: f.clobbered_regs = RegisterSet(clobbered_regs, 255) if return_regs: f.return_regs = RegisterSet(return_regs, 255) if f.name != name: f.name = name bv.update_analysis_and_wait() if adjustments: call_sites = sorted(f.call_sites,key=lambda ref:ref.address) for target, source, adjustment in adjustments: while call_sites: call_site = call_sites.pop(0) hlil = call_site.hlil if hlil.operation != HighLevelILOperation.HLIL_CALL: log_warn(f'0x{call_site.address:08x}: call site {hlil} is not HLIL_CALL') for op in hlil.operands: if hasattr(op, 'operation') and op.operation == HighLevelILOperation.HLIL_CALL: hlil = op break else: log_warn(f'0x{call_site.address:08x}: operand {op} is not HLIL_CALL') if hlil.operation != HighLevelILOperation.HLIL_CALL: log_warn(f'0x{call_site.address:08x}: call {hlil} is not a call') dest = str(hlil.dest) print(f'0x{call_site.address:08x}: call {dest!r} init: {(target,source,adjustment)}') if dest == target: f.set_call_type_adjustment(call_site.address, adjustment) #adjustment_type = bv.parse_type_string(adjustment) #if adjustment_type: # f.set_call_type_adjustment(call_site.address, adjustment) adjustment = f.get_call_type_adjustment(call_site.address) print(f'0x{call_site.address:08x}: call {str(call_site.hlil.dest)!r} set: {adjustment}') break for call_site in sorted(f.call_sites,key=lambda ref:ref.address): adjustment = f.get_call_type_adjustment(call_site.address) print(f'0x{call_site.address:08x}: call {str(call_site.hlil.dest)!r} final: {adjustment}') f = bv.get_function_at(f.start) print(f'0x{f.start:08X}:({f.name!r},{str(f)!r},{str(f.clobbered_regs.regs)},{str(f.return_regs.regs)}),') bv.commit_undo_actions()