diff options
| author | Camille Mougey <commial@gmail.com> | 2017-03-14 08:27:13 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-03-14 08:27:13 +0100 |
| commit | 67117bf808b8348a103f91ca64749d46de3f2db5 (patch) | |
| tree | 0317a4ba83bd3fe0cc21a89855139271d04af318 | |
| parent | 5ee794990ff30ca18909dd3815eda26ac267cbf4 (diff) | |
| parent | f1a2d7456c8a7482939d43ac5c1d6b829db4cdaf (diff) | |
| download | miasm-67117bf808b8348a103f91ca64749d46de3f2db5.tar.gz miasm-67117bf808b8348a103f91ca64749d46de3f2db5.zip | |
Merge pull request #497 from serpilliere/rename_symb
Rename symb
76 files changed, 2672 insertions, 2595 deletions
diff --git a/example/asm/shellcode.py b/example/asm/shellcode.py index 3ff11489..bacb65fb 100755 --- a/example/asm/shellcode.py +++ b/example/asm/shellcode.py @@ -5,7 +5,7 @@ from pdb import pm from elfesteem import pe_init from elfesteem.strpatchwork import StrPatchwork -from miasm2.core import parse_asm, asmbloc +from miasm2.core import parse_asm, asmblock from miasm2.analysis.machine import Machine from miasm2.core.interval import interval @@ -64,7 +64,7 @@ else: with open(args.source) as fstream: source = fstream.read() -blocs, symbol_pool = parse_asm.parse_txt(machine.mn, attrib, source) +blocks, symbol_pool = parse_asm.parse_txt(machine.mn, attrib, source) # Fix shellcode addrs symbol_pool.set_offset(symbol_pool.getby_name("main"), addr_main) @@ -73,14 +73,14 @@ if args.PE: symbol_pool.set_offset(symbol_pool.getby_name_create("MessageBoxA"), pe.DirImport.get_funcvirt('USER32.dll', 'MessageBoxA')) -# Print and graph firsts blocs before patching it -for bloc in blocs: - print bloc -open("graph.dot", "w").write(blocs.dot()) +# Print and graph firsts blocks before patching it +for block in blocks: + print block +open("graph.dot", "w").write(blocks.dot()) # Apply patches -patches = asmbloc.asm_resolve_final(machine.mn, - blocs, +patches = asmblock.asm_resolve_final(machine.mn, + blocks, symbol_pool, dst_interval) if args.encrypt: diff --git a/example/asm/simple.py b/example/asm/simple.py index d7623908..62d2ff80 100644 --- a/example/asm/simple.py +++ b/example/asm/simple.py @@ -2,11 +2,11 @@ from pdb import pm from pprint import pprint from miasm2.arch.x86.arch import mn_x86 -from miasm2.core import parse_asm, asmbloc +from miasm2.core import parse_asm, asmblock # Assemble code -blocs, symbol_pool = parse_asm.parse_txt(mn_x86, 32, ''' +blocks, symbol_pool = parse_asm.parse_txt(mn_x86, 32, ''' main: MOV EAX, 1 MOV EBX, 2 @@ -25,11 +25,11 @@ loop: symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0) # Spread information and resolve instructions offset -patches = asmbloc.asm_resolve_final(mn_x86, blocs, symbol_pool) +patches = asmblock.asm_resolve_final(mn_x86, blocks, symbol_pool) -# Show resolved blocs -for bloc in blocs: - print bloc +# Show resolved blocks +for block in blocks: + print block # Print offset -> bytes pprint(patches) diff --git a/example/disasm/callback.py b/example/disasm/callback.py index 4a7507dd..06159138 100644 --- a/example/disasm/callback.py +++ b/example/disasm/callback.py @@ -1,5 +1,5 @@ from miasm2.core.bin_stream import bin_stream_str -from miasm2.core.asmbloc import asm_label, asm_constraint, expr_is_label +from miasm2.core.asmblock import AsmLabel, AsmConstraint, expr_is_label from miasm2.arch.x86.disasm import dis_x86_32, cb_x86_funcs @@ -34,7 +34,7 @@ def cb_x86_callpop(cur_bloc, symbol_pool, *args, **kwargs): # Update next blocks to process in the disassembly engine cur_bloc.bto.clear() - cur_bloc.add_cst(dst.name.offset, asm_constraint.c_next, symbol_pool) + cur_bloc.add_cst(dst.name.offset, AsmConstraint.c_next, symbol_pool) # Prepare a tiny shellcode diff --git a/example/disasm/full.py b/example/disasm/full.py index f15b59eb..e768e21c 100644 --- a/example/disasm/full.py +++ b/example/disasm/full.py @@ -4,7 +4,7 @@ from argparse import ArgumentParser from pdb import pm from miasm2.analysis.binary import Container -from miasm2.core.asmbloc import log_asmbloc, asm_label, AsmCFG +from miasm2.core.asmblock import log_asmblock, AsmLabel, AsmCFG from miasm2.expression.expression import ExprId from miasm2.core.interval import interval from miasm2.analysis.machine import Machine @@ -56,7 +56,7 @@ parser.add_argument('-c', "--rawbinary", default=False, action="store_true", args = parser.parse_args() if args.verbose: - log_asmbloc.setLevel(logging.DEBUG) + log_asmblock.setLevel(logging.DEBUG) log.info('Load binary') if args.rawbinary: @@ -108,7 +108,7 @@ for ad in addrs: done = set() all_funcs = set() -all_funcs_blocs = {} +all_funcs_blocks = {} done_interval = interval() @@ -121,27 +121,27 @@ while not finish and todo: if ad in done: continue done.add(ad) - ab = mdis.dis_multibloc(ad) + allblocks = mdis.dis_multibloc(ad) log.info('func ok %.16x (%d)' % (ad, len(all_funcs))) all_funcs.add(ad) - all_funcs_blocs[ad] = ab - for b in ab: - for l in b.lines: + all_funcs_blocks[ad] = allblocks + for block in allblocks: + for l in block.lines: done_interval += interval([(l.offset, l.offset + l.l)]) if args.funcswatchdog is not None: args.funcswatchdog -= 1 if args.recurfunctions: - for b in ab: - i = b.get_subcall_instr() - if not i: + for block in allblocks: + instr = block.get_subcall_instr() + if not isntr: continue - for d in i.getdstflow(mdis.symbol_pool): - if not (isinstance(d, ExprId) and isinstance(d.name, asm_label)): + for dest in instr.getdstflow(mdis.symbol_pool): + if not (isinstance(dest, ExprId) and isinstance(dest.name, AsmLabel)): continue - todo.append((mdis, i, d.name.offset)) + todo.append((mdis, instr, dest.name.offset)) if args.funcswatchdog is not None and args.funcswatchdog <= 0: finish = True @@ -155,13 +155,13 @@ while not finish and todo: # Generate dotty graph -all_blocs = AsmCFG() -for blocs in all_funcs_blocs.values(): - all_blocs += blocs +all_blocks = AsmCFG() +for blocks in all_funcs_blocks.values(): + all_blocks += blocks log.info('generate graph file') -open('graph_execflow.dot', 'w').write(all_blocs.dot(offset=True)) +open('graph_execflow.dot', 'w').write(all_blocks.dot(offset=True)) log.info('generate intervals') @@ -188,23 +188,23 @@ if args.gen_ir: ir_arch = ir(mdis.symbol_pool) ir_arch_a = ira(mdis.symbol_pool) - ir_arch.blocs = {} - ir_arch_a.blocs = {} - for ad, all_bloc in all_funcs_blocs.items(): + ir_arch.blocks = {} + ir_arch_a.blocks = {} + for ad, all_block in all_funcs_blocks.items(): log.info("generating IR... %x" % ad) - for b in all_bloc: - ir_arch_a.add_bloc(b) - ir_arch.add_bloc(b) + for block in all_block: + ir_arch_a.add_bloc(block) + ir_arch.add_bloc(block) - log.info("Print blocs (without analyse)") - for label, bloc in ir_arch.blocs.iteritems(): - print bloc + log.info("Print blocks (without analyse)") + for label, block in ir_arch.blocks.iteritems(): + print block log.info("Gen Graph... %x" % ad) - log.info("Print blocs (with analyse)") - for label, bloc in ir_arch_a.blocs.iteritems(): - print bloc + log.info("Print blocks (with analyse)") + for label, block in ir_arch_a.blocks.iteritems(): + print block if args.simplify: ir_arch_a.dead_simp() diff --git a/example/expression/access_c.py b/example/expression/access_c.py index 1df51b00..eabc3770 100644 --- a/example/expression/access_c.py +++ b/example/expression/access_c.py @@ -58,7 +58,7 @@ ExprCompose(var1, 0) => var1 def find_call(ira): """Returns (irb, index) which call""" - for irb in ira.blocs.values(): + for irb in ira.blocks.values(): out = set() if len(irb.irs) < 2: continue diff --git a/example/expression/asm_to_ir.py b/example/expression/asm_to_ir.py index 2f8999a4..b28f8a81 100644 --- a/example/expression/asm_to_ir.py +++ b/example/expression/asm_to_ir.py @@ -3,12 +3,12 @@ from pdb import pm from miasm2.arch.x86.arch import mn_x86 from miasm2.core import parse_asm from miasm2.expression.expression import * -from miasm2.core import asmbloc +from miasm2.core import asmblock from miasm2.arch.x86.ira import ir_a_x86_32 # First, asm code -blocs, symbol_pool = parse_asm.parse_txt(mn_x86, 32, ''' +blocks, symbol_pool = parse_asm.parse_txt(mn_x86, 32, ''' main: MOV EAX, 1 MOV EBX, 2 @@ -25,24 +25,24 @@ loop: symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0) -for b in blocs: - print b +for block in blocks: + print block print "symbols:" print symbol_pool -patches = asmbloc.asm_resolve_final(mn_x86, blocs, symbol_pool) +patches = asmblock.asm_resolve_final(mn_x86, blocks, symbol_pool) # Translate to IR ir_arch = ir_a_x86_32(symbol_pool) -for b in blocs: - print 'add bloc' - print b - ir_arch.add_bloc(b) +for block in blocks: + print 'add block' + print block + ir_arch.add_bloc(block) # Display IR -for lbl, b in ir_arch.blocs.items(): - print b +for lbl, irblock in ir_arch.blocks.items(): + print irblock # Dead propagation open('graph.dot', 'w').write(ir_arch.graph.dot()) @@ -51,6 +51,6 @@ ir_arch.dead_simp() open('graph2.dot', 'w').write(ir_arch.graph.dot()) # Display new IR -print 'new ir blocs' -for lbl, b in ir_arch.blocs.items(): - print b +print 'new ir blocks' +for lbl, irblock in ir_arch.blocks.items(): + print irblock diff --git a/example/expression/get_read_write.py b/example/expression/get_read_write.py index cb9e0900..f4dde4b5 100644 --- a/example/expression/get_read_write.py +++ b/example/expression/get_read_write.py @@ -16,7 +16,7 @@ l.offset, l.l = 0, 15 ir_arch.add_instr(l) print '*' * 80 -for lbl, b in ir_arch.blocs.items(): +for lbl, b in ir_arch.blocks.items(): print b for irs in b.irs: o_r, o_w = get_rw(irs) diff --git a/example/expression/graph_dataflow.py b/example/expression/graph_dataflow.py index 64801e52..bd767165 100644 --- a/example/expression/graph_dataflow.py +++ b/example/expression/graph_dataflow.py @@ -7,7 +7,7 @@ from miasm2.arch.x86.ira import ir_a_x86_32 from miasm2.arch.x86.disasm import dis_x86_32 from miasm2.analysis.data_analysis import intra_bloc_flow_raw, inter_bloc_flow from miasm2.core.graph import DiGraph -from miasm2.ir.symbexec import symbexec +from miasm2.ir.symbexec import SymbolicExecutionEngine parser = ArgumentParser("Simple expression use for generating dataflow graph") @@ -49,12 +49,12 @@ def get_modified_symbols(sb): return out -def intra_bloc_flow_symb(ir_arch, flow_graph, irbloc): +def intra_bloc_flow_symb(ir_arch, flow_graph, irblock): symbols_init = ir_arch.arch.regs.regs_init.copy() - sb = symbexec(ir_arch, symbols_init) - sb.emulbloc(irbloc) + sb = SymbolicExecutionEngine(ir_arch, symbols_init) + sb.emulbloc(irblock) print '*' * 40 - print irbloc + print irblock in_nodes = {} out_nodes = {} @@ -68,7 +68,7 @@ def intra_bloc_flow_symb(ir_arch, flow_graph, irbloc): all_mems.update(get_expr_mem(n)) for n in all_mems: - node_n_w = get_node_name(irbloc.label, 0, n) + node_n_w = get_node_name(irblock.label, 0, n) if not n == src: continue o_r = n.arg.get_r(mem_read=False, cst_read=True) @@ -76,7 +76,7 @@ def intra_bloc_flow_symb(ir_arch, flow_graph, irbloc): if n_r in current_nodes: node_n_r = current_nodes[n_r] else: - node_n_r = get_node_name(irbloc.label, i, n_r) + node_n_r = get_node_name(irblock.label, i, n_r) if not n_r in in_nodes: in_nodes[n_r] = node_n_r flow_graph.add_uniq_edge(node_n_r, node_n_w) @@ -89,20 +89,20 @@ def intra_bloc_flow_symb(ir_arch, flow_graph, irbloc): if n_r in current_nodes: node_n_r = current_nodes[n_r] else: - node_n_r = get_node_name(irbloc.label, 0, n_r) + node_n_r = get_node_name(irblock.label, 0, n_r) if not n_r in in_nodes: in_nodes[n_r] = node_n_r flow_graph.add_node(node_n_r) for n_w in nodes_w: - node_n_w = get_node_name(irbloc.label, 1, n_w) + node_n_w = get_node_name(irblock.label, 1, n_w) out_nodes[n_w] = node_n_w flow_graph.add_node(node_n_w) flow_graph.add_uniq_edge(node_n_r, node_n_w) - irbloc.in_nodes = in_nodes - irbloc.out_nodes = out_nodes + irblock.in_nodes = in_nodes + irblock.out_nodes = out_nodes def node2str(self, node): @@ -110,31 +110,31 @@ def node2str(self, node): return out -def gen_bloc_data_flow_graph(ir_arch, ad, block_flow_cb): - for irbloc in ir_arch.blocs.values(): - print irbloc +def gen_block_data_flow_graph(ir_arch, ad, block_flow_cb): + for irblock in ir_arch.blocks.values(): + print irblock ir_arch.dead_simp() - irbloc_0 = None - for irbloc in ir_arch.blocs.values(): - if irbloc.label.offset == ad: - irbloc_0 = irbloc + irblock_0 = None + for irblock in ir_arch.blocks.values(): + if irblock.label.offset == ad: + irblock_0 = irblock break - assert(irbloc_0 is not None) + assert(irblock_0 is not None) flow_graph = DiGraph() flow_graph.node2str = lambda n: node2str(flow_graph, n) - for irbloc in ir_arch.blocs.values(): - block_flow_cb(ir_arch, flow_graph, irbloc) + for irblock in ir_arch.blocks.values(): + block_flow_cb(ir_arch, flow_graph, irblock) - for irbloc in ir_arch.blocs.values(): - print irbloc - print 'IN', [str(x) for x in irbloc.in_nodes] - print 'OUT', [str(x) for x in irbloc.out_nodes] + for irblock in ir_arch.blocks.values(): + print irblock + print 'IN', [str(x) for x in irblock.in_nodes] + print 'OUT', [str(x) for x in irblock.out_nodes] - print '*' * 20, 'interbloc', '*' * 20 - inter_bloc_flow(ir_arch, flow_graph, irbloc_0.label) + print '*' * 20, 'interblock', '*' * 20 + inter_bloc_flow(ir_arch, flow_graph, irblock_0.label) # from graph_qt import graph_qt # graph_qt(flow_graph) @@ -154,13 +154,13 @@ print 'ok' print 'generating dataflow graph for:' ir_arch = ir_a_x86_32(mdis.symbol_pool) -blocs = ab -for bloc in blocs: - print bloc - ir_arch.add_bloc(bloc) -for irbloc in ir_arch.blocs.values(): - print irbloc - if irbloc.label.offset != 0: +blocks = ab +for block in blocks: + print block + ir_arch.add_bloc(block) +for irblock in ir_arch.blocks.values(): + print irblock + if irblock.label.offset != 0: continue @@ -169,7 +169,7 @@ if args.symb: else: block_flow_cb = intra_bloc_flow_raw -gen_bloc_data_flow_graph(ir_arch, ad, block_flow_cb) +gen_block_data_flow_graph(ir_arch, ad, block_flow_cb) print '*' * 40 print """ diff --git a/example/expression/solve_condition_stp.py b/example/expression/solve_condition_stp.py index 2a3b42fd..03d652cf 100644 --- a/example/expression/solve_condition_stp.py +++ b/example/expression/solve_condition_stp.py @@ -9,9 +9,9 @@ from miasm2.arch.x86.arch import * from miasm2.arch.x86.regs import * from miasm2.arch.x86.sem import * from miasm2.core.bin_stream import bin_stream_str -from miasm2.core import asmbloc +from miasm2.core import asmblock from miasm2.expression.expression import get_rw -from miasm2.ir.symbexec import symbexec +from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.expression.simplifications import expr_simp from miasm2.expression import stp from miasm2.core import parse_asm @@ -35,18 +35,18 @@ if not args: sys.exit(0) -def get_bloc(ir_arch, mdis, ad): - if isinstance(ad, asmbloc.asm_label): +def get_block(ir_arch, mdis, ad): + if isinstance(ad, asmblock.AsmLabel): l = ad else: l = mdis.symbol_pool.getby_offset_create(ad) - if not l in ir_arch.blocs: + if not l in ir_arch.blocks: ad = l.offset b = mdis.dis_bloc(ad) ir_arch.add_bloc(b) b = ir_arch.get_bloc(l) if b is None: - raise LookupError('no bloc found at that address: %s' % l) + raise LookupError('no block found at that address: %s' % l) return b @@ -58,15 +58,15 @@ def emul_symb(ir_arch, mdis, states_todo, states_done): print 'skip', ad continue states_done.add((ad, symbols, conds)) - sb = symbexec(ir_arch, {}) + sb = SymbolicExecutionEngine(ir_arch, {}) sb.symbols = symbols.copy() if ir_arch.pc in sb.symbols: del(sb.symbols[ir_arch.pc]) - b = get_bloc(ir_arch, mdis, ad) + b = get_block(ir_arch, mdis, ad) - print 'run bloc' + print 'run block' print b - # print blocs[ad] + # print blocks[ad] ad = sb.emulbloc(b) print 'final state' sb.dump_id() @@ -87,8 +87,8 @@ def emul_symb(ir_arch, mdis, states_todo, states_done): p2[ad.cond] = ExprInt(1, ad.cond.size) ad1 = expr_simp(sb.eval_expr(ad.replace_expr(c1), {})) ad2 = expr_simp(sb.eval_expr(ad.replace_expr(c2), {})) - if not (isinstance(ad1, ExprInt) or (isinstance(ad1, ExprId) and isinstance(ad1.name, asmbloc.asm_label)) and - isinstance(ad2, ExprInt) or (isinstance(ad2, ExprId) and isinstance(ad2.name, asmbloc.asm_label))): + if not (isinstance(ad1, ExprInt) or (isinstance(ad1, ExprId) and isinstance(ad1.name, asmblock.AsmLabel)) and + isinstance(ad2, ExprInt) or (isinstance(ad2, ExprId) and isinstance(ad2.name, asmblock.AsmLabel))): print str(ad1), str(ad2) raise ValueError("zarb condition") conds1 = list(conds) + c1.items() @@ -106,7 +106,7 @@ def emul_symb(ir_arch, mdis, states_todo, states_done): elif isinstance(ad, ExprInt): ad = int(ad.arg) states_todo.add((ad, sb.symbols.copy(), tuple(conds))) - elif isinstance(ad, ExprId) and isinstance(ad.name, asmbloc.asm_label): + elif isinstance(ad, ExprId) and isinstance(ad.name, asmblock.AsmLabel): if isinstance(ad, ExprId): ad = ad.name states_todo.add((ad, sb.symbols.copy(), tuple(conds))) @@ -159,33 +159,33 @@ if __name__ == '__main__': ir_arch = ir_x86_32(mdis.symbol_pool) - sb = symbexec(ir_arch, symbols_init) + sb = SymbolicExecutionEngine(ir_arch, symbols_init) - blocs, symbol_pool = parse_asm.parse_txt(mn_x86, 32, ''' + blocks, symbol_pool = parse_asm.parse_txt(mn_x86, 32, ''' PUSH argv PUSH argc PUSH ret_addr ''') - b = list(blocs)[0] + b = list(blocks)[0] print b # add fake address and len to parsed instructions - for i, l in enumerate(b.lines): - l.offset, l.l = i, 1 + for i, line in enumerate(b.lines): + line.offset, line.l = i, 1 ir_arch.add_bloc(b) - irb = get_bloc(ir_arch, mdis, 0) + irb = get_block(ir_arch, mdis, 0) sb.emulbloc(irb) sb.dump_mem() - # reset ir_arch blocs - ir_arch.blocs = {} + # reset ir_arch blocks + ir_arch.blocks = {} states_todo = set() states_done = set() states_todo.add((uint32(ad), sb.symbols, ())) - # emul blocs, propagate states + # emul blocks, propagate states emul_symb(ir_arch, mdis, states_todo, states_done) all_info = [] @@ -201,7 +201,7 @@ if __name__ == '__main__': all_cases = set() - sb = symbexec(ir_arch, symbols_init) + sb = SymbolicExecutionEngine(ir_arch, symbols_init) for ad, reqs_cond in all_info: all_ids = set() for k, v in reqs_cond: diff --git a/example/ida/depgraph.py b/example/ida/depgraph.py index 002075ee..faec2857 100644 --- a/example/ida/depgraph.py +++ b/example/ida/depgraph.py @@ -2,7 +2,7 @@ import os import tempfile from miasm2.core.bin_stream_ida import bin_stream_ida -from miasm2.core.asmbloc import * +from miasm2.core.asmblock import * from miasm2.expression import expression as m2_expr from miasm2.expression.simplifications import expr_simp @@ -21,12 +21,12 @@ class depGraphSettingsForm(Form): self.stk_unalias_force = False self.address = ScreenEA() - cur_bloc = list(ira.getby_offset(self.address))[0] - for line_nb, l in enumerate(cur_bloc.lines): + cur_block = list(ira.getby_offset(self.address))[0] + for line_nb, l in enumerate(cur_block.lines): if l.offset == self.address: break - cur_label = str(cur_bloc.label) - labels = sorted(map(str, ira.blocs.keys())) + cur_label = str(cur_block.label) + labels = sorted(map(str, ira.blocks.keys())) regs = sorted(ir_arch.arch.regs.all_regs_ids_byname.keys()) regs += self.stk_args.keys() reg_default = regs[0] @@ -82,7 +82,7 @@ Method to use: @property def label(self): value = self.cbBBL.value - for real_label in self.ira.blocs: + for real_label in self.ira.blocks: if str(real_label) == value: return real_label raise ValueError("Bad label") @@ -96,13 +96,13 @@ Method to use: elif mode == 1: return value + 1 else: - return len(self.ira.blocs[self.label].irs) + return len(self.ira.blocks[self.label].irs) @property def elements(self): value = self.cbReg.value if value in self.stk_args: - line = self.ira.blocs[self.label].lines[self.line_nb] + line = self.ira.blocks[self.label].lines[self.line_nb] arg_num = self.stk_args[value] stk_high = m2_expr.ExprInt(GetSpd(line.offset), ir_arch.sp.size) stk_off = m2_expr.ExprInt(self.ira.sp.size/8 * arg_num, ir_arch.sp.size) @@ -151,11 +151,11 @@ for ad, name in Names(): # Get the current function addr = ScreenEA() func = idaapi.get_func(addr) -blocs = mdis.dis_multibloc(func.startEA) +blocks = mdis.dis_multibloc(func.startEA) # Generate IR -for bloc in blocs: - ir_arch.add_bloc(bloc) +for block in blocks: + ir_arch.add_bloc(block) # Get settings settings = depGraphSettingsForm(ir_arch) @@ -163,7 +163,7 @@ settings.Execute() label, elements, line_nb = settings.label, settings.elements, settings.line_nb # Simplify affectations -for irb in ir_arch.blocs.values(): +for irb in ir_arch.blocks.values(): fix_stack = irb.label.offset is not None and settings.unalias_stack for i, assignblk in enumerate(irb.irs): if fix_stack: @@ -215,7 +215,7 @@ def treat_element(): for node in graph.relevant_nodes: try: - offset = ir_arch.blocs[node.label].lines[node.line_nb].offset + offset = ir_arch.blocks[node.label].lines[node.line_nb].offset except IndexError: print "Unable to highlight %s" % node continue diff --git a/example/ida/graph_ir.py b/example/ida/graph_ir.py index 188c8fa6..3aac0281 100644 --- a/example/ida/graph_ir.py +++ b/example/ida/graph_ir.py @@ -5,7 +5,7 @@ import tempfile from idaapi import GraphViewer from miasm2.core.bin_stream_ida import bin_stream_ida -from miasm2.core.asmbloc import * +from miasm2.core.asmblock import * from miasm2.expression.simplifications import expr_simp from miasm2.expression.expression import * from miasm2.analysis.data_analysis import inter_bloc_flow, \ @@ -48,11 +48,11 @@ class GraphMiasmIR(GraphViewer): print 'refresh' self.Clear() addr_id = {} - for irbloc in self.ir_arch.blocs.values(): + for irbloc in self.ir_arch.blocks.values(): id_irbloc = self.AddNode(color_irbloc(irbloc)) addr_id[irbloc] = id_irbloc - for irbloc in self.ir_arch.blocs.values(): + for irbloc in self.ir_arch.blocks.values(): if not irbloc: continue dst = ir_arch.dst_trackback(irbloc) @@ -61,9 +61,9 @@ class GraphMiasmIR(GraphViewer): continue d = d.name - if not d in self.ir_arch.blocs: + if not d in self.ir_arch.blocks: continue - b = self.ir_arch.blocs[d] + b = self.ir_arch.blocks[d] node1 = addr_id[irbloc] node2 = addr_id[b] self.AddEdge(node1, node2) @@ -125,15 +125,15 @@ open('asm_flow.dot', 'w').write(ab.dot()) print "generating IR... %x" % ad -for b in ab: +for block in ab: print 'ADD' - print b - ir_arch.add_bloc(b) + print block + ir_arch.add_bloc(block) print "IR ok... %x" % ad -for irb in ir_arch.blocs.values(): +for irb in ir_arch.blocks.values(): for assignblk in irb.irs: for dst, src in assignblk.items(): del(assignblk[dst]) @@ -201,7 +201,7 @@ def gen_bloc_data_flow_graph(ir_arch, in_str, ad): # arch, attrib, pool_bin, bl # ir_arch.dead_simp() irbloc_0 = None - for irbloc in ir_arch.blocs.values(): + for irbloc in ir_arch.blocks.values(): if irbloc.label.offset == ad: irbloc_0 = irbloc break @@ -212,11 +212,11 @@ def gen_bloc_data_flow_graph(ir_arch, in_str, ad): # arch, attrib, pool_bin, bl bloc2w = {} - for irbloc in ir_arch.blocs.values(): + for irbloc in ir_arch.blocks.values(): intra_bloc_flow_symbexec(ir_arch, flow_graph, irbloc) # intra_bloc_flow_symb(ir_arch, flow_graph, irbloc) - for irbloc in ir_arch.blocs.values(): + for irbloc in ir_arch.blocks.values(): print irbloc print 'IN', [str(x) for x in irbloc.in_nodes] print 'OUT', [str(x) for x in irbloc.out_nodes] diff --git a/example/ida/symbol_exec.py b/example/ida/symbol_exec.py index 751f9a58..70e1cfc1 100644 --- a/example/ida/symbol_exec.py +++ b/example/ida/symbol_exec.py @@ -75,7 +75,7 @@ class symbolicexec_t(idaapi.simplecustviewer_t): def symbolic_exec(): - from miasm2.ir.symbexec import symbexec + from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.core.bin_stream_ida import bin_stream_ida from utils import guess_machine @@ -87,13 +87,13 @@ def symbolic_exec(): start, end = SelStart(), SelEnd() mdis.dont_dis = [end] - blocs = mdis.dis_multibloc(start) + blocks = mdis.dis_multibloc(start) ira = machine.ira() - for bloc in blocs: - ira.add_bloc(bloc) + for block in blocks: + ira.add_bloc(block) print "Run symbolic execution..." - sb = symbexec(ira, machine.mn.regs.regs_init) + sb = SymbolicExecutionEngine(ira, machine.mn.regs.regs_init) sb.emul_ir_blocks(start) modified = {} diff --git a/example/symbol_exec/single_instr.py b/example/symbol_exec/single_instr.py index 365a17ec..3e418e5a 100644 --- a/example/symbol_exec/single_instr.py +++ b/example/symbol_exec/single_instr.py @@ -1,6 +1,6 @@ # Minimalist Symbol Exec example from miasm2.core.bin_stream import bin_stream_str -from miasm2.ir.symbexec import symbexec +from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.analysis.machine import Machine START_ADDR = 0 @@ -23,7 +23,7 @@ ira.add_bloc(asm_block) # Instanciate a Symbolic Execution engine with default value for registers ## EAX = EAX_init, ... symbols_init = ira.arch.regs.regs_init -symb = symbexec(ira, symbols_init) +symb = SymbolicExecutionEngine(ira, symbols_init) # Emulate one IR basic block ## Emulation of several basic blocks can be done through .emul_ir_blocks diff --git a/miasm2/analysis/binary.py b/miasm2/analysis/binary.py index d47ca884..4ff9dac0 100644 --- a/miasm2/analysis/binary.py +++ b/miasm2/analysis/binary.py @@ -2,7 +2,7 @@ import logging from miasm2.core.bin_stream import bin_stream_str, bin_stream_elf, bin_stream_pe from miasm2.jitter.csts import PAGE_READ -from miasm2.core.asmbloc import asm_symbol_pool +from miasm2.core.asmblock import AsmSymbolPool log = logging.getLogger("binary") @@ -94,7 +94,7 @@ class Container(object): self._bin_stream = None self._entry_point = None self._arch = None - self._symbol_pool = asm_symbol_pool() + self._symbol_pool = AsmSymbolPool() # Launch parsing self.parse(*args, **kwargs) @@ -121,7 +121,7 @@ class Container(object): @property def symbol_pool(self): - "asm_symbol_pool instance preloaded with container symbols (if any)" + "AsmSymbolPool instance preloaded with container symbols (if any)" return self._symbol_pool diff --git a/miasm2/analysis/data_analysis.py b/miasm2/analysis/data_analysis.py index 9fee22af..c67c4509 100644 --- a/miasm2/analysis/data_analysis.py +++ b/miasm2/analysis/data_analysis.py @@ -1,6 +1,6 @@ from miasm2.expression.expression \ import get_expr_mem, get_list_rw, ExprId, ExprInt -from miasm2.ir.symbexec import symbexec +from miasm2.ir.symbexec import SymbolicExecutionEngine def get_node_name(label, i, n): @@ -77,7 +77,7 @@ def intra_bloc_flow_symbexec(ir_arch, flow_graph, irb): symbols_init = dict(ir_arch.arch.regs.all_regs_ids_init) - sb = symbexec(ir_arch, dict(symbols_init)) + sb = SymbolicExecutionEngine(ir_arch, dict(symbols_init)) sb.emulbloc(irb) # print "*"*40 # print irb @@ -116,10 +116,10 @@ def inter_bloc_flow_link(ir_arch, flow_graph, todo, link_exec_to_data): current_nodes = dict(current_nodes) # link current nodes to bloc in_nodes - if not lbl in ir_arch.blocs: + if not lbl in ir_arch.blocks: print "cannot find bloc!!", lbl return set() - irb = ir_arch.blocs[lbl] + irb = ir_arch.blocks[lbl] # pp(('IN', lbl, [(str(x[0]), str(x[1])) for x in current_nodes.items()])) to_del = set() for n_r, node_n_r in irb.in_nodes.items(): @@ -159,15 +159,15 @@ def create_implicit_flow(ir_arch, flow_graph): # first fix IN/OUT # If a son read a node which in not in OUT, add it - todo = set(ir_arch.blocs.keys()) + todo = set(ir_arch.blocks.keys()) while todo: lbl = todo.pop() - irb = ir_arch.blocs[lbl] + irb = ir_arch.blocks[lbl] for lbl_son in ir_arch.graph.successors(irb.label): - if not lbl_son in ir_arch.blocs: + if not lbl_son in ir_arch.blocks: print "cannot find bloc!!", lbl continue - irb_son = ir_arch.blocs[lbl_son] + irb_son = ir_arch.blocks[lbl_son] for n_r in irb_son.in_nodes: if n_r in irb.out_nodes: continue @@ -211,8 +211,8 @@ class symb_exec_func: """ This algorithm will do symbolic execution on a function, trying to propagate - states between basic blocs in order to extract inter-blocs dataflow. The - algorithm tries to merge states from blocs with multiple parents. + states between basic blocks in order to extract inter-blocs dataflow. The + algorithm tries to merge states from blocks with multiple parents. There is no real magic here, loops and complex merging will certainly fail. """ @@ -297,7 +297,7 @@ class symb_exec_func: # print "state done" # continue - sb = symbexec(self.ir_arch, dict(s)) + sb = SymbolicExecutionEngine(self.ir_arch, dict(s)) return parent, ad, sb return None diff --git a/miasm2/analysis/depgraph.py b/miasm2/analysis/depgraph.py index 281251c2..bab4d2bc 100644 --- a/miasm2/analysis/depgraph.py +++ b/miasm2/analysis/depgraph.py @@ -2,10 +2,10 @@ import miasm2.expression.expression as m2_expr from miasm2.core.graph import DiGraph -from miasm2.core.asmbloc import asm_label, expr_is_int_or_label, expr_is_label +from miasm2.core.asmblock import AsmLabel, expr_is_int_or_label, expr_is_label from miasm2.expression.simplifications import expr_simp -from miasm2.ir.symbexec import symbexec -from miasm2.ir.ir import irbloc, AssignBlock +from miasm2.ir.symbexec import SymbolicExecutionEngine +from miasm2.ir.ir import IRBlock, AssignBlock from miasm2.ir.translators import Translator from miasm2.expression.expression_helper import possible_values @@ -28,7 +28,7 @@ class DependencyNode(object): def __init__(self, label, element, line_nb): """Create a dependency node with: - @label: asm_label instance + @label: AsmLabel instance @element: Expr instance @line_nb: int """ @@ -107,7 +107,7 @@ class DependencyState(object): def extend(self, label): """Return a copy of itself, with itself in history - @label: asm_label instance for the new DependencyState's label + @label: AsmLabel instance for the new DependencyState's label """ new_state = self.__class__(label, self.pending) new_state.links = set(self.links) @@ -270,7 +270,7 @@ class DependencyResult(DependencyState): assignblk[element] = irb.irs[line_nb][element] assignblks.append(assignblk) - return irbloc(irb.label, assignblks) + return IRBlock(irb.label, assignblks) def emul(self, ctx=None, step=False): """Symbolic execution of relevant nodes according to the history @@ -293,13 +293,13 @@ class DependencyResult(DependencyState): line_nb = self.initial_state.line_nb else: line_nb = None - assignblks += self.irblock_slice(self._ira.blocs[label], + assignblks += self.irblock_slice(self._ira.blocks[label], line_nb).irs # Eval the block - temp_label = asm_label("Temp") - symb_exec = symbexec(self._ira, ctx_init) - symb_exec.emulbloc(irbloc(temp_label, assignblks), step=step) + temp_label = AsmLabel("Temp") + symb_exec = SymbolicExecutionEngine(self._ira, ctx_init) + symb_exec.emulbloc(IRBlock(temp_label, assignblks), step=step) # Return only inputs values (others could be wrongs) return {element: symb_exec.symbols[element] @@ -354,7 +354,7 @@ class DependencyResultImplicit(DependencyResult): if ctx is not None: ctx_init.update(ctx) solver = z3.Solver() - symb_exec = symbexec(self._ira, ctx_init) + symb_exec = SymbolicExecutionEngine(self._ira, ctx_init) history = self.history[::-1] history_size = len(history) translator = Translator.to_language("z3") @@ -365,7 +365,7 @@ class DependencyResultImplicit(DependencyResult): line_nb = self.initial_state.line_nb else: line_nb = None - irb = self.irblock_slice(self._ira.blocs[label], line_nb) + irb = self.irblock_slice(self._ira.blocks[label], line_nb) # Emul the block and get back destination dst = symb_exec.emulbloc(irb, step=step) @@ -416,7 +416,7 @@ class FollowExpr(object): """Build a set of FollowExpr(DependencyNode) from the @follow_exprs set of FollowExpr @follow_exprs: set of FollowExpr - @label: asm_label instance + @label: AsmLabel instance @line: integer """ dependencies = set() @@ -580,7 +580,7 @@ class DependencyGraph(object): """Follow dependencies tracked in @state in the current irbloc @state: instance of DependencyState""" - irb = self._ira.blocs[state.label] + irb = self._ira.blocks[state.label] line_nb = len(irb.irs) if state.line_nb is None else state.line_nb for cur_line_nb, assignblk in reversed(list(enumerate(irb.irs[:line_nb]))): @@ -590,10 +590,10 @@ class DependencyGraph(object): """Compute the dependencies of @elements at line number @line_nb in the block named @label in the current IRA, before the execution of this line. Dependency check stop if one of @heads is reached - @label: asm_label instance + @label: AsmLabel instance @element: set of Expr instances @line_nb: int - @heads: set of asm_label instances + @heads: set of AsmLabel instances Return an iterator on DiGraph(DependencyNode) """ # Init the algorithm @@ -630,7 +630,7 @@ class DependencyGraph(object): argument. PRE: Labels and lines of depnodes have to be equals @depnodes: set of DependencyNode instances - @heads: set of asm_label instances + @heads: set of AsmLabel instances """ lead = list(depnodes)[0] elements = set(depnode.element for depnode in depnodes) diff --git a/miasm2/analysis/disasm_cb.py b/miasm2/analysis/disasm_cb.py index f1f23377..284a2c99 100644 --- a/miasm2/analysis/disasm_cb.py +++ b/miasm2/analysis/disasm_cb.py @@ -2,8 +2,8 @@ from miasm2.expression.expression import ExprInt, ExprId, ExprMem, MatchExpr from miasm2.expression.simplifications import expr_simp -from miasm2.core.asmbloc \ - import asm_symbol_pool, asm_constraint_next, asm_constraint_to +from miasm2.core.asmblock \ + import AsmSymbolPool, AsmConstraintNext, AsmConstraintTo from miasm2.core.utils import upck32 # from miasm2.core.graph import DiGraph @@ -25,21 +25,21 @@ def arm_guess_subcall( mnemo, attrib, pool_bin, cur_bloc, offsets_to_dis, symbol_pool): ira = get_ira(mnemo, attrib) - sp = asm_symbol_pool() + sp = AsmSymbolPool() ir_arch = ira(sp) print '###' print cur_bloc ir_arch.add_bloc(cur_bloc) - ir_blocs = ir_arch.blocs.values() + ir_blocks = ir_arch.blocks.values() # flow_graph = DiGraph() to_add = set() - for irb in ir_blocs: + for irblock in ir_blocks: # print 'X'*40 - # print irb + # print irblock pc_val = None lr_val = None - for exprs in irb.irs: + for exprs in irblock.irs: for e in exprs: if e.dst == ir_arch.pc: pc_val = e.src @@ -55,7 +55,7 @@ def arm_guess_subcall( continue # print 'IS CALL!' l = symbol_pool.getby_offset_create(int(lr_val)) - c = asm_constraint_next(l) + c = AsmConstraintNext(l) to_add.add(c) offsets_to_dis.add(int(lr_val)) @@ -74,17 +74,17 @@ def arm_guess_jump_table( jra = ExprId('jra') jrb = ExprId('jrb') - sp = asm_symbol_pool() + sp = AsmSymbolPool() ir_arch = ira(sp) ir_arch.add_bloc(cur_bloc) - ir_blocs = ir_arch.blocs.values() - for irb in ir_blocs: + ir_blocks = ir_arch.blocks.values() + for irblock in ir_blocks: # print 'X'*40 - # print irb + # print irblock pc_val = None # lr_val = None - for exprs in irb.irs: + for exprs in irblock.irs: for e in exprs: if e.dst == ir_arch.pc: pc_val = e.src @@ -125,7 +125,7 @@ def arm_guess_jump_table( for ad in addrs: offsets_to_dis.add(ad) l = symbol_pool.getby_offset_create(ad) - c = asm_constraint_to(l) + c = AsmConstraintTo(l) cur_bloc.addto(c) guess_funcs = [] diff --git a/miasm2/arch/aarch64/arch.py b/miasm2/arch/aarch64/arch.py index 460c134e..6f95df99 100644 --- a/miasm2/arch/aarch64/arch.py +++ b/miasm2/arch/aarch64/arch.py @@ -8,7 +8,7 @@ from collections import defaultdict from miasm2.core.bin_stream import bin_stream import regs as regs_module from regs import * -from miasm2.core.asmbloc import asm_label +from miasm2.core.asmblock import AsmLabel from miasm2.core.cpu import log as log_cpu from miasm2.expression.modint import uint32, uint64 import math @@ -207,7 +207,7 @@ simdregs_h_zero = (simd32_info.parser | def ast_id2expr(t): if not t in mn_aarch64.regs.all_regs_ids_byname: - r = m2_expr.ExprId(asm_label(t)) + r = m2_expr.ExprId(AsmLabel(t)) else: r = mn_aarch64.regs.all_regs_ids_byname[t] return r diff --git a/miasm2/arch/aarch64/disasm.py b/miasm2/arch/aarch64/disasm.py index d31ce3fd..a8604fe5 100644 --- a/miasm2/arch/aarch64/disasm.py +++ b/miasm2/arch/aarch64/disasm.py @@ -1,4 +1,4 @@ -from miasm2.core.asmbloc import asm_constraint, disasmEngine +from miasm2.core.asmblock import disasmEngine from miasm2.arch.aarch64.arch import mn_aarch64 cb_aarch64_funcs = [] diff --git a/miasm2/arch/aarch64/ira.py b/miasm2/arch/aarch64/ira.py index 20a9a66c..ada2e028 100644 --- a/miasm2/arch/aarch64/ira.py +++ b/miasm2/arch/aarch64/ira.py @@ -1,10 +1,7 @@ #-*- coding:utf-8 -*- -from miasm2.expression.expression import * -from miasm2.ir.ir import ir, irbloc, AssignBlock from miasm2.ir.analysis import ira from miasm2.arch.aarch64.sem import ir_aarch64l, ir_aarch64b -from miasm2.arch.aarch64.regs import * class ir_a_aarch64l_base(ir_aarch64l, ira): @@ -28,13 +25,13 @@ class ir_a_aarch64l(ir_a_aarch64l_base): self.ret_reg = self.arch.regs.X0 # for test XXX TODO - def set_dead_regs(self, b): - b.rw[-1][1].add(self.arch.regs.zf) - b.rw[-1][1].add(self.arch.regs.nf) - b.rw[-1][1].add(self.arch.regs.of) - b.rw[-1][1].add(self.arch.regs.cf) + def set_dead_regs(self, irblock): + irblock.rw[-1][1].add(self.arch.regs.zf) + irblock.rw[-1][1].add(self.arch.regs.nf) + irblock.rw[-1][1].add(self.arch.regs.of) + irblock.rw[-1][1].add(self.arch.regs.cf) - def get_out_regs(self, b): + def get_out_regs(self, _): return set([self.ret_reg, self.sp]) def sizeof_char(self): diff --git a/miasm2/arch/aarch64/jit.py b/miasm2/arch/aarch64/jit.py index ca8d7b39..255bb91d 100644 --- a/miasm2/arch/aarch64/jit.py +++ b/miasm2/arch/aarch64/jit.py @@ -1,8 +1,8 @@ import logging from miasm2.jitter.jitload import jitter, named_arguments -from miasm2.core import asmbloc -from miasm2.core.utils import * +from miasm2.core import asmblock +from miasm2.core.utils import pck64, upck64 from miasm2.arch.aarch64.sem import ir_aarch64b, ir_aarch64l log = logging.getLogger('jit_aarch64') @@ -15,22 +15,21 @@ class jitter_aarch64l(jitter): max_reg_arg = 8 def __init__(self, *args, **kwargs): - sp = asmbloc.asm_symbol_pool() + sp = asmblock.AsmSymbolPool() jitter.__init__(self, ir_aarch64l(sp), *args, **kwargs) self.vm.set_little_endian() - def push_uint64_t(self, v): + def push_uint64_t(self, value): self.cpu.SP -= 8 - self.vm.set_mem(self.cpu.SP, pck64(v)) + self.vm.set_mem(self.cpu.SP, pck64(value)) def pop_uint64_t(self): - x = upck32(self.vm.get_mem(self.cpu.SP, 8)) + value = upck64(self.vm.get_mem(self.cpu.SP, 8)) self.cpu.SP += 8 - return x + return value - def get_stack_arg(self, n): - x = upck64(self.vm.get_mem(self.cpu.SP + 8 * n, 8)) - return x + def get_stack_arg(self, index): + return upck64(self.vm.get_mem(self.cpu.SP + 8 * index, 8)) # calling conventions @@ -50,11 +49,11 @@ class jitter_aarch64l(jitter): self.cpu.X0 = ret_value return True - def get_arg_n_stdcall(self, n): - if n < self.max_reg_arg: - arg = self.cpu.get_gpreg()['X%d' % n] + def get_arg_n_stdcall(self, index): + if index < self.max_reg_arg: + arg = self.cpu.get_gpreg()['X%d' % index] else: - arg = self.get_stack_arg(n - self.max_reg_arg) + arg = self.get_stack_arg(index - self.max_reg_arg) return arg def init_run(self, *args, **kwargs): @@ -65,6 +64,6 @@ class jitter_aarch64l(jitter): class jitter_aarch64b(jitter_aarch64l): def __init__(self, *args, **kwargs): - sp = asmbloc.asm_symbol_pool() + sp = asmblock.AsmSymbolPool() jitter.__init__(self, ir_aarch64b(sp), *args, **kwargs) self.vm.set_big_endian() diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py index c3ed56d5..792a4984 100644 --- a/miasm2/arch/aarch64/sem.py +++ b/miasm2/arch/aarch64/sem.py @@ -1,5 +1,5 @@ from miasm2.expression import expression as m2_expr -from miasm2.ir.ir import ir, irbloc, AssignBlock +from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock from miasm2.arch.aarch64.arch import mn_aarch64, conds_expr, replace_regs from miasm2.arch.aarch64.regs import * from miasm2.core.sembuilder import SemBuilder @@ -746,10 +746,10 @@ class aarch64info: # offset -class ir_aarch64l(ir): +class ir_aarch64l(IntermediateRepresentation): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_aarch64, "l", symbol_pool) + IntermediateRepresentation.__init__(self, mn_aarch64, "l", symbol_pool) self.pc = PC self.sp = SP self.IRDst = m2_expr.ExprId('IRDst', 64) @@ -804,8 +804,8 @@ class ir_aarch64l(ir): dst = dst.replace_expr({self.pc: cur_offset}) src = src.replace_expr({self.pc: cur_offset}) instr_ir[i] = m2_expr.ExprAff(dst, src) - for b in extra_ir: - for irs in b.irs: + for irblock in extra_ir: + for irs in irblock.irs: for i, expr in enumerate(irs): dst, src = expr.dst, expr.src if dst != self.pc: @@ -819,9 +819,9 @@ class ir_aarch64l(ir): regs_to_fix = [WZR, XZR] instr_ir = [expr for expr in instr_ir if expr.dst not in regs_to_fix] - for b in extra_ir: - for i, irs in enumerate(b.irs): - b.irs[i] = [expr for expr in irs if expr.dst not in regs_to_fix] + for irblock in extra_ir: + for i, irs in enumerate(irblock.irs): + irblock.irs[i] = [expr for expr in irs if expr.dst not in regs_to_fix] return instr_ir, extra_ir @@ -829,7 +829,7 @@ class ir_aarch64l(ir): class ir_aarch64b(ir_aarch64l): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_aarch64, "b", symbol_pool) + IntermediateRepresentation.__init__(self, mn_aarch64, "b", symbol_pool) self.pc = PC self.sp = SP self.IRDst = m2_expr.ExprId('IRDst', 64) diff --git a/miasm2/arch/arm/arch.py b/miasm2/arch/arm/arch.py index d9bf42ba..54a168af 100644 --- a/miasm2/arch/arm/arch.py +++ b/miasm2/arch/arm/arch.py @@ -8,7 +8,6 @@ from collections import defaultdict from miasm2.core.bin_stream import bin_stream import miasm2.arch.arm.regs as regs_module from miasm2.arch.arm.regs import * -from miasm2.core.asmbloc import asm_label # A1 encoding diff --git a/miasm2/arch/arm/disasm.py b/miasm2/arch/arm/disasm.py index 6209be5e..3f6ea4d5 100644 --- a/miasm2/arch/arm/disasm.py +++ b/miasm2/arch/arm/disasm.py @@ -1,4 +1,4 @@ -from miasm2.core.asmbloc import asm_constraint, disasmEngine +from miasm2.core.asmblock import AsmConstraint, disasmEngine from miasm2.arch.arm.arch import mn_arm, mn_armt @@ -24,7 +24,7 @@ def cb_arm_fix_call(mn, cur_bloc, symbol_pool, offsets_to_dis, *args, **kwargs): return if not l2.args[1] in values: return - cur_bloc.add_cst(l1.offset + 4, asm_constraint.c_next, symbol_pool) + cur_bloc.add_cst(l1.offset + 4, AsmConstraint.c_next, symbol_pool) offsets_to_dis.add(l1.offset + 4) cb_arm_funcs = [cb_arm_fix_call] diff --git a/miasm2/arch/arm/ira.py b/miasm2/arch/arm/ira.py index 8d659b58..760e6d90 100644 --- a/miasm2/arch/arm/ira.py +++ b/miasm2/arch/arm/ira.py @@ -1,11 +1,7 @@ #-*- coding:utf-8 -*- -from miasm2.expression.expression import * -from miasm2.ir.ir import ir, irbloc, AssignBlock from miasm2.ir.analysis import ira from miasm2.arch.arm.sem import ir_arml, ir_armtl, ir_armb, ir_armtb -from miasm2.arch.arm.regs import * -# from miasm2.core.graph import DiGraph class ir_a_arml_base(ir_arml, ira): @@ -26,13 +22,13 @@ class ir_a_arml(ir_a_arml_base): self.ret_reg = self.arch.regs.R0 # for test XXX TODO - def set_dead_regs(self, b): - b.rw[-1][1].add(self.arch.regs.zf) - b.rw[-1][1].add(self.arch.regs.nf) - b.rw[-1][1].add(self.arch.regs.of) - b.rw[-1][1].add(self.arch.regs.cf) + def set_dead_regs(self, irblock): + irblock.rw[-1][1].add(self.arch.regs.zf) + irblock.rw[-1][1].add(self.arch.regs.nf) + irblock.rw[-1][1].add(self.arch.regs.of) + irblock.rw[-1][1].add(self.arch.regs.cf) - def get_out_regs(self, b): + def get_out_regs(self, _): return set([self.ret_reg, self.sp]) def sizeof_char(self): diff --git a/miasm2/arch/arm/jit.py b/miasm2/arch/arm/jit.py index 70d16176..70c708e1 100644 --- a/miasm2/arch/arm/jit.py +++ b/miasm2/arch/arm/jit.py @@ -1,8 +1,8 @@ import logging from miasm2.jitter.jitload import jitter, named_arguments -from miasm2.core import asmbloc -from miasm2.core.utils import * +from miasm2.core import asmblock +from miasm2.core.utils import pck32, upck32 from miasm2.arch.arm.sem import ir_armb, ir_arml log = logging.getLogger('jit_arm') @@ -14,22 +14,21 @@ log.setLevel(logging.CRITICAL) class jitter_arml(jitter): def __init__(self, *args, **kwargs): - sp = asmbloc.asm_symbol_pool() + sp = asmblock.AsmSymbolPool() jitter.__init__(self, ir_arml(sp), *args, **kwargs) self.vm.set_little_endian() - def push_uint32_t(self, v): + def push_uint32_t(self, value): self.cpu.SP -= 4 - self.vm.set_mem(self.cpu.SP, pck32(v)) + self.vm.set_mem(self.cpu.SP, pck32(value)) def pop_uint32_t(self): - x = upck32(self.vm.get_mem(self.cpu.SP, 4)) + value = upck32(self.vm.get_mem(self.cpu.SP, 4)) self.cpu.SP += 4 - return x + return value - def get_stack_arg(self, n): - x = upck32(self.vm.get_mem(self.cpu.SP + 4 * n, 4)) - return x + def get_stack_arg(self, index): + return upck32(self.vm.get_mem(self.cpu.SP + 4 * index, 4)) # calling conventions @@ -49,11 +48,11 @@ class jitter_arml(jitter): self.cpu.R0 = ret_value return True - def get_arg_n_stdcall(self, n): - if n < 4: - arg = self.cpu.get_gpreg()['R%d' % n] + def get_arg_n_stdcall(self, index): + if index < 4: + arg = self.cpu.get_gpreg()['R%d' % index] else: - arg = self.get_stack_arg(n-4) + arg = self.get_stack_arg(index-4) return arg def init_run(self, *args, **kwargs): @@ -63,6 +62,6 @@ class jitter_arml(jitter): class jitter_armb(jitter_arml): def __init__(self, *args, **kwargs): - sp = asmbloc.asm_symbol_pool() + sp = asmblock.AsmSymbolPool() jitter.__init__(self, ir_armb(sp), *args, **kwargs) self.vm.set_big_endian() diff --git a/miasm2/arch/arm/sem.py b/miasm2/arch/arm/sem.py index 225b393c..8c74aa76 100644 --- a/miasm2/arch/arm/sem.py +++ b/miasm2/arch/arm/sem.py @@ -1,5 +1,5 @@ from miasm2.expression.expression import * -from miasm2.ir.ir import ir, irbloc +from miasm2.ir.ir import IntermediateRepresentation, IRBlock from miasm2.arch.arm.arch import mn_arm, mn_armt from miasm2.arch.arm.regs import * @@ -1055,7 +1055,7 @@ def add_condition_expr(ir, instr, cond, instr_ir): break if not has_irdst: instr_ir.append(ExprAff(ir.IRDst, lbl_next)) - e_do = irbloc(lbl_do.name, [instr_ir]) + e_do = IRBlock(lbl_do.name, [instr_ir]) e = [ExprAff(ir.IRDst, dst_cond)] return e, [e_do] @@ -1227,9 +1227,9 @@ class arminfo: # offset -class ir_arml(ir): +class ir_arml(IntermediateRepresentation): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_arm, "l", symbol_pool) + IntermediateRepresentation.__init__(self, mn_arm, "l", symbol_pool) self.pc = PC self.sp = SP self.IRDst = ExprId('IRDst', 32) @@ -1252,8 +1252,8 @@ class ir_arml(ir): x = ExprAff(x.dst, x.src.replace_expr( {self.pc: ExprInt32(instr.offset + 8)})) instr_ir[i] = x - for b in extra_ir: - for irs in b.irs: + for irblock in extra_ir: + for irs in irblock.irs: for i, x in enumerate(irs): x = ExprAff(x.dst, x.src.replace_expr( {self.pc: ExprInt32(instr.offset + 8)})) @@ -1264,14 +1264,14 @@ class ir_arml(ir): class ir_armb(ir_arml): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_arm, "b", symbol_pool) + IntermediateRepresentation.__init__(self, mn_arm, "b", symbol_pool) self.pc = PC self.sp = SP self.IRDst = ExprId('IRDst', 32) -class ir_armtl(ir): +class ir_armtl(IntermediateRepresentation): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_armt, "l", symbol_pool) + IntermediateRepresentation.__init__(self, mn_armt, "l", symbol_pool) self.pc = PC self.sp = SP self.IRDst = ExprId('IRDst', 32) @@ -1281,7 +1281,7 @@ class ir_armtl(ir): class ir_armtb(ir_armtl): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_armt, "b", symbol_pool) + IntermediateRepresentation.__init__(self, mn_armt, "b", symbol_pool) self.pc = PC self.sp = SP self.IRDst = ExprId('IRDst', 32) diff --git a/miasm2/arch/mips32/arch.py b/miasm2/arch/mips32/arch.py index 79176205..f11c6e3a 100644 --- a/miasm2/arch/mips32/arch.py +++ b/miasm2/arch/mips32/arch.py @@ -9,7 +9,6 @@ from miasm2.expression.expression import ExprMem, ExprInt, ExprInt32, ExprId from miasm2.core.bin_stream import bin_stream import miasm2.arch.mips32.regs as regs import miasm2.core.cpu as cpu -from miasm2.core.asmbloc import asm_label log = logging.getLogger("mips32dis") console_handler = logging.StreamHandler() diff --git a/miasm2/arch/mips32/disasm.py b/miasm2/arch/mips32/disasm.py index e5a70349..bdd800d5 100644 --- a/miasm2/arch/mips32/disasm.py +++ b/miasm2/arch/mips32/disasm.py @@ -1,4 +1,4 @@ -from miasm2.core.asmbloc import disasmEngine +from miasm2.core.asmblock import disasmEngine from miasm2.arch.mips32.arch import mn_mips32 diff --git a/miasm2/arch/mips32/ira.py b/miasm2/arch/mips32/ira.py index 8f7b2df3..dd02ff50 100644 --- a/miasm2/arch/mips32/ira.py +++ b/miasm2/arch/mips32/ira.py @@ -1,34 +1,28 @@ #-*- coding:utf-8 -*- -from miasm2.expression.expression import * -from miasm2.ir.ir import ir, irbloc, AssignBlock +from miasm2.expression.expression import ExprAff, ExprInt32, ExprId +from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock from miasm2.ir.analysis import ira from miasm2.arch.mips32.sem import ir_mips32l, ir_mips32b -from miasm2.arch.mips32.regs import * -from miasm2.core.asmbloc import expr_is_int_or_label, expr_is_label +from miasm2.core.asmblock import expr_is_int_or_label, expr_is_label class ir_a_mips32l(ir_mips32l, ira): def __init__(self, symbol_pool=None): ir_mips32l.__init__(self, symbol_pool) self.ret_reg = self.arch.regs.V0 - - # for test XXX TODO - def set_dead_regs(self, b): - pass - def pre_add_instr(self, block, instr, irb_cur, ir_blocks_all, gen_pc_updt): # Avoid adding side effects, already done in post_add_bloc return irb_cur - def post_add_bloc(self, bloc, ir_blocs): - ir.post_add_bloc(self, bloc, ir_blocs) - for irb in ir_blocs: + def post_add_bloc(self, block, ir_blocks): + IntermediateRepresentation.post_add_bloc(self, block, ir_blocks) + for irb in ir_blocks: pc_val = None lr_val = None for assignblk in irb.irs: - pc_val = assignblk.get(PC, pc_val) - lr_val = assignblk.get(RA, lr_val) + pc_val = assignblk.get(self.arch.regs.PC, pc_val) + lr_val = assignblk.get(self.arch.regs.RA, lr_val) if pc_val is None or lr_val is None: continue @@ -37,22 +31,22 @@ class ir_a_mips32l(ir_mips32l, ira): if expr_is_label(lr_val): lr_val = ExprInt32(lr_val.name.offset) - l = bloc.lines[-2] - if lr_val.arg != l.offset + 8: + line = block.lines[-2] + if lr_val.arg != line.offset + 8: raise ValueError("Wrong arg") # CALL - lbl = bloc.get_next() + lbl = block.get_next() new_lbl = self.gen_label() - irs = self.call_effects(pc_val, l) + irs = self.call_effects(pc_val, line) irs.append(AssignBlock([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))])) - nbloc = irbloc(new_lbl, irs) - nbloc.lines = [l] * len(irs) - self.blocs[new_lbl] = nbloc + nblock = IRBlock(new_lbl, irs) + nblock.lines = [line] * len(irs) + self.blocks[new_lbl] = nblock irb.dst = ExprId(new_lbl, size=self.pc.size) - def get_out_regs(self, b): + def get_out_regs(self, _): return set([self.ret_reg, self.sp]) def sizeof_char(self): diff --git a/miasm2/arch/mips32/jit.py b/miasm2/arch/mips32/jit.py index 332e8d13..0ba531f1 100644 --- a/miasm2/arch/mips32/jit.py +++ b/miasm2/arch/mips32/jit.py @@ -1,8 +1,8 @@ import logging from miasm2.jitter.jitload import jitter -from miasm2.core import asmbloc -from miasm2.core.utils import * +from miasm2.core import asmblock +from miasm2.core.utils import pck32, upck32 from miasm2.arch.mips32.sem import ir_mips32l, ir_mips32b from miasm2.jitter.codegen import CGen import miasm2.expression.expression as m2_expr @@ -43,7 +43,7 @@ class mipsCGen(CGen): if not instr.breakflow(): continue for irblock in irblocks: - for i, assignblock in enumerate(irblock.irs): + for assignblock in irblock.irs: if self.ir_arch.pc not in assignblock: continue # Add internal branch destination @@ -68,7 +68,7 @@ class mipsCGen(CGen): m2_expr.ExprId('branch_dst_irdst'), m2_expr.ExprId('branch_dst_irdst'), self.id_to_c(m2_expr.ExprInt(lbl.offset, 32))) - ).split('\n') + ).split('\n') return out @@ -77,22 +77,21 @@ class jitter_mips32l(jitter): C_Gen = mipsCGen def __init__(self, *args, **kwargs): - sp = asmbloc.asm_symbol_pool() + sp = asmblock.AsmSymbolPool() jitter.__init__(self, ir_mips32l(sp), *args, **kwargs) self.vm.set_little_endian() - def push_uint32_t(self, v): + def push_uint32_t(self, value): self.cpu.SP -= 4 - self.vm.set_mem(self.cpu.SP, pck32(v)) + self.vm.set_mem(self.cpu.SP, pck32(value)) def pop_uint32_t(self): - x = upck32(self.vm.get_mem(self.cpu.SP, 4)) + value = upck32(self.vm.get_mem(self.cpu.SP, 4)) self.cpu.SP += 4 - return x + return value - def get_stack_arg(self, n): - x = upck32(self.vm.get_mem(self.cpu.SP + 4 * n, 4)) - return x + def get_stack_arg(self, index): + return upck32(self.vm.get_mem(self.cpu.SP + 4 * index, 4)) def init_run(self, *args, **kwargs): jitter.init_run(self, *args, **kwargs) @@ -102,6 +101,6 @@ class jitter_mips32l(jitter): class jitter_mips32b(jitter_mips32l): def __init__(self, *args, **kwargs): - sp = asmbloc.asm_symbol_pool() + sp = asmblock.AsmSymbolPool() jitter.__init__(self, ir_mips32b(sp), *args, **kwargs) self.vm.set_big_endian() diff --git a/miasm2/arch/mips32/sem.py b/miasm2/arch/mips32/sem.py index b52b8401..d982f033 100644 --- a/miasm2/arch/mips32/sem.py +++ b/miasm2/arch/mips32/sem.py @@ -1,5 +1,5 @@ import miasm2.expression.expression as m2_expr -from miasm2.ir.ir import ir, irbloc +from miasm2.ir.ir import IntermediateRepresentation, IRBlock from miasm2.arch.mips32.arch import mn_mips32 from miasm2.arch.mips32.regs import R_LO, R_HI, PC, RA from miasm2.core.sembuilder import SemBuilder @@ -429,10 +429,10 @@ def get_mnemo_expr(ir, instr, *args): instr, extra_ir = mnemo_func[instr.name.lower()](ir, instr, *args) return instr, extra_ir -class ir_mips32l(ir): +class ir_mips32l(IntermediateRepresentation): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_mips32, 'l', symbol_pool) + IntermediateRepresentation.__init__(self, mn_mips32, 'l', symbol_pool) self.pc = mn_mips32.getpc() self.sp = mn_mips32.getsp() self.IRDst = m2_expr.ExprId('IRDst', 32) @@ -445,8 +445,8 @@ class ir_mips32l(ir): x = m2_expr.ExprAff(x.dst, x.src.replace_expr( {self.pc: m2_expr.ExprInt32(instr.offset + 4)})) instr_ir[i] = x - for b in extra_ir: - for irs in b.irs: + for irblock in extra_ir: + for irs in irblock.irs: for i, x in enumerate(irs): x = m2_expr.ExprAff(x.dst, x.src.replace_expr( {self.pc: m2_expr.ExprInt32(instr.offset + 4)})) @@ -454,53 +454,14 @@ class ir_mips32l(ir): return instr_ir, extra_ir def get_next_instr(self, instr): - l = self.symbol_pool.getby_offset_create(instr.offset + 4) - return l + return self.symbol_pool.getby_offset_create(instr.offset + 4) def get_next_break_label(self, instr): - l = self.symbol_pool.getby_offset_create(instr.offset + 8) - return l - """ - def add_bloc(self, bloc, gen_pc_updt = False): - c = None - ir_blocs_all = [] - for l in bloc.lines: - if c is None: - # print 'new c' - label = self.get_label(l) - c = irbloc(label, [], []) - ir_blocs_all.append(c) - bloc_dst = None - # print 'Translate', l - dst, ir_bloc_cur, ir_blocs_extra = self.instr2ir(l) - # print ir_bloc_cur - # for xxx in ir_bloc_cur: - # print "\t", xxx - assert((dst is None) or (bloc_dst is None)) - bloc_dst = dst - #if bloc_dst is not None: - # c.dst = bloc_dst - if dst is not None: - ir_bloc_cur.append(m2_expr.ExprAff(PC_FETCH, dst)) - c.dst = PC_FETCH - if gen_pc_updt is not False: - self.gen_pc_update(c, l) - - c.irs.append(ir_bloc_cur) - c.lines.append(l) - if ir_blocs_extra: - # print 'split' - for b in ir_blocs_extra: - b.lines = [l] * len(b.irs) - ir_blocs_all += ir_blocs_extra - c = None - self.post_add_bloc(bloc, ir_blocs_all) - return ir_blocs_all - """ + return self.symbol_pool.getby_offset_create(instr.offset + 8) class ir_mips32b(ir_mips32l): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_mips32, 'b', symbol_pool) + IntermediateRepresentation.__init__(self, mn_mips32, 'b', symbol_pool) self.pc = mn_mips32.getpc() self.sp = mn_mips32.getsp() self.IRDst = m2_expr.ExprId('IRDst', 32) diff --git a/miasm2/arch/msp430/arch.py b/miasm2/arch/msp430/arch.py index d7463f3d..07ba3019 100644 --- a/miasm2/arch/msp430/arch.py +++ b/miasm2/arch/msp430/arch.py @@ -8,7 +8,6 @@ from collections import defaultdict from miasm2.core.bin_stream import bin_stream import miasm2.arch.msp430.regs as regs_module from miasm2.arch.msp430.regs import * -from miasm2.core.asmbloc import asm_label log = logging.getLogger("msp430dis") console_handler = logging.StreamHandler() diff --git a/miasm2/arch/msp430/disasm.py b/miasm2/arch/msp430/disasm.py index ac5d9cce..849cd675 100644 --- a/miasm2/arch/msp430/disasm.py +++ b/miasm2/arch/msp430/disasm.py @@ -1,4 +1,4 @@ -from miasm2.core.asmbloc import disasmEngine +from miasm2.core.asmblock import disasmEngine from miasm2.arch.msp430.arch import mn_msp430 diff --git a/miasm2/arch/msp430/ira.py b/miasm2/arch/msp430/ira.py index 071bfae8..0dc63c61 100644 --- a/miasm2/arch/msp430/ira.py +++ b/miasm2/arch/msp430/ira.py @@ -1,11 +1,7 @@ #-*- coding:utf-8 -*- -from miasm2.expression.expression import * -from miasm2.ir.ir import ir, irbloc, AssignBlock from miasm2.ir.analysis import ira from miasm2.arch.msp430.sem import ir_msp430 -from miasm2.arch.msp430.regs import * -# from miasm2.core.graph import DiGraph class ir_a_msp430_base(ir_msp430, ira): @@ -21,19 +17,19 @@ class ir_a_msp430(ir_a_msp430_base): ir_a_msp430_base.__init__(self, symbol_pool) # for test XXX TODO - def set_dead_regs(self, b): - b.rw[-1][1].add(self.arch.regs.zf) - b.rw[-1][1].add(self.arch.regs.nf) - b.rw[-1][1].add(self.arch.regs.of) - b.rw[-1][1].add(self.arch.regs.cf) - - b.rw[-1][1].add(self.arch.regs.res) - b.rw[-1][1].add(self.arch.regs.scg1) - b.rw[-1][1].add(self.arch.regs.scg0) - b.rw[-1][1].add(self.arch.regs.osc) - b.rw[-1][1].add(self.arch.regs.cpuoff) - b.rw[-1][1].add(self.arch.regs.gie) - - def get_out_regs(self, b): + def set_dead_regs(self, irblock): + irblock.rw[-1][1].add(self.arch.regs.zf) + irblock.rw[-1][1].add(self.arch.regs.nf) + irblock.rw[-1][1].add(self.arch.regs.of) + irblock.rw[-1][1].add(self.arch.regs.cf) + + irblock.rw[-1][1].add(self.arch.regs.res) + irblock.rw[-1][1].add(self.arch.regs.scg1) + irblock.rw[-1][1].add(self.arch.regs.scg0) + irblock.rw[-1][1].add(self.arch.regs.osc) + irblock.rw[-1][1].add(self.arch.regs.cpuoff) + irblock.rw[-1][1].add(self.arch.regs.gie) + + def get_out_regs(self, _): return set([self.ret_reg, self.sp]) diff --git a/miasm2/arch/msp430/jit.py b/miasm2/arch/msp430/jit.py index 95d34f96..dd5fe94e 100644 --- a/miasm2/arch/msp430/jit.py +++ b/miasm2/arch/msp430/jit.py @@ -1,6 +1,6 @@ from miasm2.jitter.jitload import jitter -from miasm2.core import asmbloc -from miasm2.core.utils import * +from miasm2.core import asmblock +from miasm2.core.utils import pck16, upck16 from miasm2.arch.msp430.sem import ir_msp430 import logging @@ -14,27 +14,27 @@ log.setLevel(logging.CRITICAL) class jitter_msp430(jitter): def __init__(self, *args, **kwargs): - sp = asmbloc.asm_symbol_pool() + sp = asmblock.AsmSymbolPool() jitter.__init__(self, ir_msp430(sp), *args, **kwargs) self.vm.set_little_endian() - def push_uint16_t(self, v): + def push_uint16_t(self, value): regs = self.cpu.get_gpreg() regs['SP'] -= 2 self.cpu.set_gpreg(regs) - self.vm.set_mem(regs['SP'], pck16(v)) + self.vm.set_mem(regs['SP'], pck16(value)) def pop_uint16_t(self): regs = self.cpu.get_gpreg() - x = upck16(self.vm.get_mem(regs['SP'], 2)) + value = upck16(self.vm.get_mem(regs['SP'], 2)) regs['SP'] += 2 self.cpu.set_gpreg(regs) - return x + return value - def get_stack_arg(self, n): + def get_stack_arg(self, index): regs = self.cpu.get_gpreg() - x = upck16(self.vm.get_mem(regs['SP'] + 2 * n, 2)) - return x + value = upck16(self.vm.get_mem(regs['SP'] + 2 * index, 2)) + return value def init_run(self, *args, **kwargs): jitter.init_run(self, *args, **kwargs) diff --git a/miasm2/arch/msp430/sem.py b/miasm2/arch/msp430/sem.py index 4b52361d..e8eb91cc 100644 --- a/miasm2/arch/msp430/sem.py +++ b/miasm2/arch/msp430/sem.py @@ -3,7 +3,7 @@ from miasm2.expression.expression import * from miasm2.arch.msp430.regs import * from miasm2.arch.msp430.arch import mn_msp430 -from miasm2.ir.ir import ir +from miasm2.ir.ir import IntermediateRepresentation # Utils @@ -412,10 +412,10 @@ def ComposeExprAff(dst, src): return e -class ir_msp430(ir): +class ir_msp430(IntermediateRepresentation): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_msp430, None, symbol_pool) + IntermediateRepresentation.__init__(self, mn_msp430, None, symbol_pool) self.pc = PC self.sp = SP self.IRDst = ExprId('IRDst', 16) diff --git a/miasm2/arch/sh4/arch.py b/miasm2/arch/sh4/arch.py index ae96fef1..634cbf43 100644 --- a/miasm2/arch/sh4/arch.py +++ b/miasm2/arch/sh4/arch.py @@ -6,7 +6,6 @@ from miasm2.expression.expression import * from collections import defaultdict import miasm2.arch.sh4.regs as regs_module from miasm2.arch.sh4.regs import * -from miasm2.core.asmbloc import asm_label jra = ExprId('jra') jrb = ExprId('jrb') diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py index 8ae6cd31..d686cd55 100644 --- a/miasm2/arch/x86/arch.py +++ b/miasm2/arch/x86/arch.py @@ -7,7 +7,7 @@ from miasm2.core.cpu import * from collections import defaultdict import miasm2.arch.x86.regs as regs_module from miasm2.arch.x86.regs import * -from miasm2.core.asmbloc import asm_label +from miasm2.core.asmblock import AsmLabel log = logging.getLogger("x86_arch") console_handler = logging.StreamHandler() @@ -489,7 +489,7 @@ class instruction_x86(instruction): return expr = self.args[0] if isinstance(expr, ExprId): - if not isinstance(expr.name, asm_label) and expr not in all_regs_ids: + if not isinstance(expr.name, AsmLabel) and expr not in all_regs_ids: raise ValueError("ExprId must be a label or a register") elif isinstance(expr, ExprInt): ad = expr.arg + int(self.offset) diff --git a/miasm2/arch/x86/disasm.py b/miasm2/arch/x86/disasm.py index 0ff55097..fc981c09 100644 --- a/miasm2/arch/x86/disasm.py +++ b/miasm2/arch/x86/disasm.py @@ -1,4 +1,4 @@ -from miasm2.core.asmbloc import disasmEngine +from miasm2.core.asmblock import disasmEngine from miasm2.arch.x86.arch import mn_x86 diff --git a/miasm2/arch/x86/ira.py b/miasm2/arch/x86/ira.py index 31d38b37..74aa0203 100644 --- a/miasm2/arch/x86/ira.py +++ b/miasm2/arch/x86/ira.py @@ -1,9 +1,7 @@ #-*- coding:utf-8 -*- -from miasm2.expression.expression import ExprAff, ExprOp, ExprId -from miasm2.core.graph import DiGraph -from miasm2.core.asmbloc import expr_is_label -from miasm2.ir.ir import ir, irbloc, AssignBlock +from miasm2.expression.expression import ExprAff, ExprOp +from miasm2.ir.ir import AssignBlock from miasm2.ir.analysis import ira from miasm2.arch.x86.sem import ir_x86_16, ir_x86_32, ir_x86_64 @@ -15,21 +13,21 @@ class ir_a_x86_16(ir_x86_16, ira): self.ret_reg = self.arch.regs.AX # for test XXX TODO - def set_dead_regs(self, b): - b.rw[-1][1].add(self.arch.regs.zf) - b.rw[-1][1].add(self.arch.regs.of) - b.rw[-1][1].add(self.arch.regs.pf) - b.rw[-1][1].add(self.arch.regs.cf) - b.rw[-1][1].add(self.arch.regs.nf) - b.rw[-1][1].add(self.arch.regs.af) - - def get_out_regs(self, b): + def set_dead_regs(self, irblock): + irblock.rw[-1][1].add(self.arch.regs.zf) + irblock.rw[-1][1].add(self.arch.regs.of) + irblock.rw[-1][1].add(self.arch.regs.pf) + irblock.rw[-1][1].add(self.arch.regs.cf) + irblock.rw[-1][1].add(self.arch.regs.nf) + irblock.rw[-1][1].add(self.arch.regs.af) + + def get_out_regs(self, _): return set([self.ret_reg, self.sp]) def add_unused_regs(self): - leaves = [self.blocs[n] for n in self.g.leafs()] - for b in leaves: - self.set_dead_regs(b) + leaves = [self.blocks[label] for label in self.g.leafs()] + for irblock in leaves: + self.set_dead_regs(irblock) class ir_a_x86_32(ir_x86_32, ir_a_x86_16): diff --git a/miasm2/arch/x86/jit.py b/miasm2/arch/x86/jit.py index 2e483f2a..cfdabf8c 100644 --- a/miasm2/arch/x86/jit.py +++ b/miasm2/arch/x86/jit.py @@ -1,8 +1,8 @@ import logging from miasm2.jitter.jitload import jitter, named_arguments -from miasm2.core import asmbloc -from miasm2.core.utils import * +from miasm2.core import asmblock +from miasm2.core.utils import pck16, pck32, pck64, upck16, upck32, upck64 from miasm2.arch.x86.sem import ir_x86_16, ir_x86_32, ir_x86_64 from miasm2.jitter.codegen import CGen @@ -37,28 +37,27 @@ class jitter_x86_16(jitter): C_Gen = x86_32_CGen def __init__(self, *args, **kwargs): - sp = asmbloc.asm_symbol_pool() + sp = asmblock.AsmSymbolPool() jitter.__init__(self, ir_x86_16(sp), *args, **kwargs) self.vm.set_little_endian() self.ir_arch.do_stk_segm = False self.orig_irbloc_fix_regs_for_mode = self.ir_arch.irbloc_fix_regs_for_mode self.ir_arch.irbloc_fix_regs_for_mode = self.ir_archbloc_fix_regs_for_mode - def ir_archbloc_fix_regs_for_mode(self, irbloc, attrib=64): - self.orig_irbloc_fix_regs_for_mode(irbloc, 64) + def ir_archbloc_fix_regs_for_mode(self, irblock, attrib=64): + self.orig_irbloc_fix_regs_for_mode(irblock, 64) - def push_uint16_t(self, v): + def push_uint16_t(self, value): self.cpu.SP -= self.ir_arch.sp.size / 8 - self.vm.set_mem(self.cpu.SP, pck16(v)) + self.vm.set_mem(self.cpu.SP, pck16(value)) def pop_uint16_t(self): - x = upck16(self.vm.get_mem(self.cpu.SP, self.ir_arch.sp.size / 8)) + value = upck16(self.vm.get_mem(self.cpu.SP, self.ir_arch.sp.size / 8)) self.cpu.SP += self.ir_arch.sp.size / 8 - return x + return value - def get_stack_arg(self, n): - x = upck16(self.vm.get_mem(self.cpu.SP + 4 * n, 4)) - return x + def get_stack_arg(self, index): + return upck16(self.vm.get_mem(self.cpu.SP + 4 * index, 4)) def init_run(self, *args, **kwargs): jitter.init_run(self, *args, **kwargs) @@ -70,7 +69,7 @@ class jitter_x86_32(jitter): C_Gen = x86_32_CGen def __init__(self, *args, **kwargs): - sp = asmbloc.asm_symbol_pool() + sp = asmblock.AsmSymbolPool() jitter.__init__(self, ir_x86_32(sp), *args, **kwargs) self.vm.set_little_endian() self.ir_arch.do_stk_segm = False @@ -78,21 +77,20 @@ class jitter_x86_32(jitter): self.orig_irbloc_fix_regs_for_mode = self.ir_arch.irbloc_fix_regs_for_mode self.ir_arch.irbloc_fix_regs_for_mode = self.ir_archbloc_fix_regs_for_mode - def ir_archbloc_fix_regs_for_mode(self, irbloc, attrib=64): - self.orig_irbloc_fix_regs_for_mode(irbloc, 64) + def ir_archbloc_fix_regs_for_mode(self, irblock, attrib=64): + self.orig_irbloc_fix_regs_for_mode(irblock, 64) - def push_uint32_t(self, v): + def push_uint32_t(self, value): self.cpu.ESP -= self.ir_arch.sp.size / 8 - self.vm.set_mem(self.cpu.ESP, pck32(v)) + self.vm.set_mem(self.cpu.ESP, pck32(value)) def pop_uint32_t(self): - x = upck32(self.vm.get_mem(self.cpu.ESP, self.ir_arch.sp.size / 8)) + value = upck32(self.vm.get_mem(self.cpu.ESP, self.ir_arch.sp.size / 8)) self.cpu.ESP += self.ir_arch.sp.size / 8 - return x + return value - def get_stack_arg(self, n): - x = upck32(self.vm.get_mem(self.cpu.ESP + 4 * n, 4)) - return x + def get_stack_arg(self, index): + return upck32(self.vm.get_mem(self.cpu.ESP + 4 * index, 4)) # calling conventions @@ -131,7 +129,7 @@ class jitter_x86_64(jitter): C_Gen = x86_64_CGen def __init__(self, *args, **kwargs): - sp = asmbloc.asm_symbol_pool() + sp = asmblock.AsmSymbolPool() jitter.__init__(self, ir_x86_64(sp), *args, **kwargs) self.vm.set_little_endian() self.ir_arch.do_stk_segm = False @@ -139,21 +137,20 @@ class jitter_x86_64(jitter): self.orig_irbloc_fix_regs_for_mode = self.ir_arch.irbloc_fix_regs_for_mode self.ir_arch.irbloc_fix_regs_for_mode = self.ir_archbloc_fix_regs_for_mode - def ir_archbloc_fix_regs_for_mode(self, irbloc, attrib=64): - self.orig_irbloc_fix_regs_for_mode(irbloc, 64) + def ir_archbloc_fix_regs_for_mode(self, irblock, attrib=64): + self.orig_irbloc_fix_regs_for_mode(irblock, 64) - def push_uint64_t(self, v): + def push_uint64_t(self, value): self.cpu.RSP -= self.ir_arch.sp.size / 8 - self.vm.set_mem(self.cpu.RSP, pck64(v)) + self.vm.set_mem(self.cpu.RSP, pck64(value)) def pop_uint64_t(self): - x = upck64(self.vm.get_mem(self.cpu.RSP, self.ir_arch.sp.size / 8)) + value = upck64(self.vm.get_mem(self.cpu.RSP, self.ir_arch.sp.size / 8)) self.cpu.RSP += self.ir_arch.sp.size / 8 - return x + return value - def get_stack_arg(self, n): - x = upck64(self.vm.get_mem(self.cpu.RSP + 8 * n, 8)) - return x + def get_stack_arg(self, index): + return upck64(self.vm.get_mem(self.cpu.RSP + 8 * index, 8)) @named_arguments def func_args_stdcall(self, n_args): diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 18a1421e..729806b5 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -21,7 +21,7 @@ from miasm2.expression.simplifications import expr_simp from miasm2.arch.x86.regs import * from miasm2.arch.x86.arch import mn_x86, repeat_mn, replace_regs from miasm2.expression.expression_helper import expr_cmps, expr_cmpu -from miasm2.ir.ir import ir, irbloc +from miasm2.ir.ir import IntermediateRepresentation, IRBlock from miasm2.core.sembuilder import SemBuilder import math import struct @@ -277,7 +277,7 @@ def gen_fcmov(ir, instr, cond, arg1, arg2, mov_if): e_do, extra_irs = [m2_expr.ExprAff(arg1, arg2)], [] e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB))) - return e, [irbloc(lbl_do.name, [e_do])] + return e, [IRBlock(lbl_do.name, [e_do])] def gen_cmov(ir, instr, cond, dst, src, mov_if): @@ -297,7 +297,7 @@ def gen_cmov(ir, instr, cond, dst, src, mov_if): e_do, extra_irs = mov(ir, instr, dst, src) e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB))) - return e, [irbloc(lbl_do.name, [e_do])] + return e, [IRBlock(lbl_do.name, [e_do])] def mov(_, instr, dst, src): @@ -518,7 +518,7 @@ def _rotate_tpl(ir, instr, dst, src, op, left=False, include_cf=False): e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) e.append(m2_expr.ExprAff( ir.IRDst, m2_expr.ExprCond(shifter, lbl_do, lbl_skip))) - return (e, [irbloc(lbl_do.name, [e_do])]) + return (e, [IRBlock(lbl_do.name, [e_do])]) def l_rol(ir, instr, dst, src): @@ -615,7 +615,7 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False, e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(shifter, lbl_do, lbl_skip))) - return e, [irbloc(lbl_do.name, [e_do])] + return e, [IRBlock(lbl_do.name, [e_do])] def sar(ir, instr, dst, src): @@ -963,7 +963,7 @@ def cmps(ir, instr, size): e0.append(m2_expr.ExprAff(b.arg, b.arg + m2_expr.ExprInt(size / 8, b.arg.size))) e0.append(m2_expr.ExprAff(ir.IRDst, lbl_next)) - e0 = irbloc(lbl_df_0.name, [e0]) + e0 = IRBlock(lbl_df_0.name, [e0]) e1 = [] e1.append(m2_expr.ExprAff(a.arg, @@ -971,7 +971,7 @@ def cmps(ir, instr, size): e1.append(m2_expr.ExprAff(b.arg, b.arg - m2_expr.ExprInt(size / 8, b.arg.size))) e1.append(m2_expr.ExprAff(ir.IRDst, lbl_next)) - e1 = irbloc(lbl_df_1.name, [e1]) + e1 = IRBlock(lbl_df_1.name, [e1]) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, lbl_df_1, lbl_df_0))) @@ -992,13 +992,13 @@ def scas(ir, instr, size): e0.append(m2_expr.ExprAff(a.arg, a.arg + m2_expr.ExprInt(size / 8, a.arg.size))) e0.append(m2_expr.ExprAff(ir.IRDst, lbl_next)) - e0 = irbloc(lbl_df_0.name, [e0]) + e0 = IRBlock(lbl_df_0.name, [e0]) e1 = [] e1.append(m2_expr.ExprAff(a.arg, a.arg - m2_expr.ExprInt(size / 8, a.arg.size))) e1.append(m2_expr.ExprAff(ir.IRDst, lbl_next)) - e1 = irbloc(lbl_df_1.name, [e1]) + e1 = IRBlock(lbl_df_1.name, [e1]) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, lbl_df_1, lbl_df_0))) @@ -1641,12 +1641,12 @@ def stos(ir, instr, size): e0 = [] e0.append(m2_expr.ExprAff(addr_o, addr_p)) e0.append(m2_expr.ExprAff(ir.IRDst, lbl_next)) - e0 = irbloc(lbl_df_0.name, [e0]) + e0 = IRBlock(lbl_df_0.name, [e0]) e1 = [] e1.append(m2_expr.ExprAff(addr_o, addr_m)) e1.append(m2_expr.ExprAff(ir.IRDst, lbl_next)) - e1 = irbloc(lbl_df_1.name, [e1]) + e1 = IRBlock(lbl_df_1.name, [e1]) e = [] e.append(m2_expr.ExprAff(ir.ExprMem(addr, size), b)) @@ -1676,12 +1676,12 @@ def lods(ir, instr, size): e0 = [] e0.append(m2_expr.ExprAff(addr_o, addr_p)) e0.append(m2_expr.ExprAff(ir.IRDst, lbl_next)) - e0 = irbloc(lbl_df_0.name, [e0]) + e0 = IRBlock(lbl_df_0.name, [e0]) e1 = [] e1.append(m2_expr.ExprAff(addr_o, addr_m)) e1.append(m2_expr.ExprAff(ir.IRDst, lbl_next)) - e1 = irbloc(lbl_df_1.name, [e1]) + e1 = IRBlock(lbl_df_1.name, [e1]) e = [] if instr.mode == 64 and b.size == 32: @@ -1718,13 +1718,13 @@ def movs(ir, instr, size): e0.append(m2_expr.ExprAff(a, a + m2_expr.ExprInt(size / 8, a.size))) e0.append(m2_expr.ExprAff(b, b + m2_expr.ExprInt(size / 8, b.size))) e0.append(m2_expr.ExprAff(ir.IRDst, lbl_next)) - e0 = irbloc(lbl_df_0.name, [e0]) + e0 = IRBlock(lbl_df_0.name, [e0]) e1 = [] e1.append(m2_expr.ExprAff(a, a - m2_expr.ExprInt(size / 8, a.size))) e1.append(m2_expr.ExprAff(b, b - m2_expr.ExprInt(size / 8, b.size))) e1.append(m2_expr.ExprAff(ir.IRDst, lbl_next)) - e1 = irbloc(lbl_df_1.name, [e1]) + e1 = IRBlock(lbl_df_1.name, [e1]) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, lbl_df_1, lbl_df_0))) @@ -2758,8 +2758,8 @@ def bsr_bsf(ir, instr, dst, src, op_name): e_src_not_null.append(m2_expr.ExprAff(dst, m2_expr.ExprOp(op_name, src))) e_src_not_null.append(aff_dst) - return e, [irbloc(lbl_src_null.name, [e_src_null]), - irbloc(lbl_src_not_null.name, [e_src_not_null])] + return e, [IRBlock(lbl_src_null.name, [e_src_null]), + IRBlock(lbl_src_not_null.name, [e_src_not_null])] def bsf(ir, instr, dst, src): @@ -3655,7 +3655,7 @@ def ps_rl_ll(ir, instr, dst, src, op, size): e_do = [] e.append(m2_expr.ExprAff(dst[0:dst.size], m2_expr.ExprCompose(*slices))) e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_next)) - return e, [irbloc(lbl_do.name, [e_do]), irbloc(lbl_zero.name, [e_zero])] + return e, [IRBlock(lbl_do.name, [e_do]), IRBlock(lbl_zero.name, [e_zero])] def psrlw(ir, instr, dst, src): @@ -4484,10 +4484,10 @@ mnemo_func = {'mov': mov, } -class ir_x86_16(ir): +class ir_x86_16(IntermediateRepresentation): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_x86, 16, symbol_pool) + IntermediateRepresentation.__init__(self, mn_x86, 16, symbol_pool) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False @@ -4571,8 +4571,8 @@ class ir_x86_16(ir): lbl_skip = m2_expr.ExprId(self.get_next_label(instr), self.IRDst.size) lbl_next = m2_expr.ExprId(self.get_next_label(instr), self.IRDst.size) - for b in extra_ir: - for ir in b.irs: + for irblock in extra_ir: + for ir in irblock.irs: for i, e in enumerate(ir): src = e.src.replace_expr({lbl_next: lbl_end}) ir[i] = m2_expr.ExprAff(e.dst, src) @@ -4583,10 +4583,10 @@ class ir_x86_16(ir): cond_bloc.append(m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_cond, lbl_skip, lbl_do))) - cond_bloc = irbloc(lbl_end.name, [cond_bloc]) + cond_bloc = IRBlock(lbl_end.name, [cond_bloc]) e_do = instr_ir - c = irbloc(lbl_do.name, [e_do]) + c = IRBlock(lbl_do.name, [e_do]) c.except_automod = False e_n = [m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_reg, lbl_do, lbl_skip))] @@ -4622,7 +4622,7 @@ class ir_x86_16(ir): class ir_x86_32(ir_x86_16): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_x86, 32, symbol_pool) + IntermediateRepresentation.__init__(self, mn_x86, 32, symbol_pool) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False @@ -4636,7 +4636,7 @@ class ir_x86_32(ir_x86_16): class ir_x86_64(ir_x86_16): def __init__(self, symbol_pool=None): - ir.__init__(self, mn_x86, 64, symbol_pool) + IntermediateRepresentation.__init__(self, mn_x86, 64, symbol_pool) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False @@ -4656,8 +4656,8 @@ class ir_x86_64(ir_x86_16): src = src.replace_expr( {self.pc: m2_expr.ExprInt64(instr.offset + instr.l)}) instr_ir[i] = m2_expr.ExprAff(dst, src) - for b in extra_ir: - for irs in b.irs: + for irblock in extra_ir: + for irs in irblock.irs: for i, expr in enumerate(irs): dst, src = expr.dst, expr.src if dst != self.pc: diff --git a/miasm2/core/asmbloc.py b/miasm2/core/asmbloc.py index ef068a3f..54760f4e 100644 --- a/miasm2/core/asmbloc.py +++ b/miasm2/core/asmbloc.py @@ -1,1500 +1,10 @@ -#-*- coding:utf-8 -*- +""" +This module will be removed in favour of asmblock.py +Cause: French tipo. +""" +import warnings +from miasm2.core.asmblock import * -import logging -import inspect -from collections import namedtuple +warnings.warn('DEPRECATION WARNING: use "asmblock" sub-module instead of "asmbloc"') -import miasm2.expression.expression as m2_expr -from miasm2.expression.simplifications import expr_simp -from miasm2.expression.modint import moduint, modint -from miasm2.core.utils import Disasm_Exception, pck -from miasm2.core.graph import DiGraph, DiGraphSimplifier, MatchGraphJoker -from miasm2.core.interval import interval - - -log_asmbloc = logging.getLogger("asmblock") -console_handler = logging.StreamHandler() -console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) -log_asmbloc.addHandler(console_handler) -log_asmbloc.setLevel(logging.WARNING) - - -def is_int(a): - return isinstance(a, int) or isinstance(a, long) or \ - isinstance(a, moduint) or isinstance(a, modint) - - -def expr_is_label(e): - return isinstance(e, m2_expr.ExprId) and isinstance(e.name, asm_label) - - -def expr_is_int_or_label(e): - return isinstance(e, m2_expr.ExprInt) or \ - (isinstance(e, m2_expr.ExprId) and isinstance(e.name, asm_label)) - - -class asm_label: - - "Stand for an assembly label" - - def __init__(self, name="", offset=None): - self.fixedblocs = False - if is_int(name): - name = "loc_%.16X" % (int(name) & 0xFFFFFFFFFFFFFFFF) - self.name = name - self.attrib = None - if offset is None: - self.offset = offset - else: - self.offset = int(offset) - - def __str__(self): - if isinstance(self.offset, (int, long)): - return "%s:0x%08x" % (self.name, self.offset) - else: - return "%s:%s" % (self.name, str(self.offset)) - - def __repr__(self): - rep = '<asmlabel ' - if self.name: - rep += repr(self.name) + ' ' - rep += '>' - return rep - - -class asm_raw: - - def __init__(self, raw=""): - self.raw = raw - - def __str__(self): - return repr(self.raw) - - -class asm_constraint(object): - c_to = "c_to" - c_next = "c_next" - - def __init__(self, label, c_t=c_to): - # Sanity check - assert isinstance(label, asm_label) - - self.label = label - self.c_t = c_t - - def __str__(self): - return "%s:%s" % (str(self.c_t), str(self.label)) - - -class asm_constraint_next(asm_constraint): - - def __init__(self, label): - super(asm_constraint_next, self).__init__( - label, c_t=asm_constraint.c_next) - - -class asm_constraint_to(asm_constraint): - - def __init__(self, label): - super(asm_constraint_to, self).__init__( - label, c_t=asm_constraint.c_to) - - -class asm_bloc(object): - - def __init__(self, label, alignment=1): - assert isinstance(label, asm_label) - self.bto = set() - self.lines = [] - self.label = label - self.alignment = alignment - - def __str__(self): - out = [] - out.append(str(self.label)) - for l in self.lines: - out.append(str(l)) - if self.bto: - lbls = ["->"] - for l in self.bto: - if l is None: - lbls.append("Unknown? ") - else: - lbls.append(str(l) + " ") - lbls = '\t'.join(lbls) - out.append(lbls) - return '\n'.join(out) - - def addline(self, l): - self.lines.append(l) - - def addto(self, c): - assert isinstance(self.bto, set) - self.bto.add(c) - - def split(self, offset, l): - log_asmbloc.debug('split at %x', offset) - i = -1 - offsets = [x.offset for x in self.lines] - if not l.offset in offsets: - log_asmbloc.warning( - 'cannot split bloc at %X ' % offset + - 'middle instruction? default middle') - offsets.sort() - return None - new_bloc = asm_bloc(l) - i = offsets.index(offset) - - self.lines, new_bloc.lines = self.lines[:i], self.lines[i:] - flow_mod_instr = self.get_flow_instr() - log_asmbloc.debug('flow mod %r', flow_mod_instr) - c = asm_constraint(l, asm_constraint.c_next) - # move dst if flowgraph modifier was in original bloc - # (usecase: split delayslot bloc) - if flow_mod_instr: - for xx in self.bto: - log_asmbloc.debug('lbl %s', xx) - c_next = set( - [x for x in self.bto if x.c_t == asm_constraint.c_next]) - c_to = [x for x in self.bto if x.c_t != asm_constraint.c_next] - self.bto = set([c] + c_to) - new_bloc.bto = c_next - else: - new_bloc.bto = self.bto - self.bto = set([c]) - return new_bloc - - def get_range(self): - """Returns the offset hull of an asm_bloc""" - if len(self.lines): - return (self.lines[0].offset, - self.lines[-1].offset + self.lines[-1].l) - else: - return 0, 0 - - def get_offsets(self): - return [x.offset for x in self.lines] - - def add_cst(self, offset, c_t, symbol_pool): - if isinstance(offset, (int, long)): - l = symbol_pool.getby_offset_create(offset) - elif isinstance(offset, str): - l = symbol_pool.getby_name_create(offset) - elif isinstance(offset, asm_label): - l = offset - else: - raise ValueError('unknown offset type %r' % offset) - c = asm_constraint(l, c_t) - self.bto.add(c) - - def get_flow_instr(self): - if not self.lines: - return None - for i in xrange(-1, -1 - self.lines[0].delayslot - 1, -1): - if not 0 <= i < len(self.lines): - return None - l = self.lines[i] - if l.splitflow() or l.breakflow(): - raise NotImplementedError('not fully functional') - - def get_subcall_instr(self): - if not self.lines: - return None - delayslot = self.lines[0].delayslot - end_index = len(self.lines) - 1 - ds_max_index = max(end_index - delayslot, 0) - for i in xrange(end_index, ds_max_index - 1, -1): - l = self.lines[i] - if l.is_subcall(): - return l - return None - - def get_next(self): - for x in self.bto: - if x.c_t == asm_constraint.c_next: - return x.label - return None - - @staticmethod - def _filter_constraint(constraints): - """Sort and filter @constraints for asm_bloc.bto - @constraints: non-empty set of asm_constraint instance - - Always the same type -> one of the constraint - c_next and c_to -> c_next - """ - # Only one constraint - if len(constraints) == 1: - return next(iter(constraints)) - - # Constraint type -> set of corresponding constraint - cbytype = {} - for cons in constraints: - cbytype.setdefault(cons.c_t, set()).add(cons) - - # Only one type -> any constraint is OK - if len(cbytype) == 1: - return next(iter(constraints)) - - # At least 2 types -> types = {c_next, c_to} - # c_to is included in c_next - return next(iter(cbytype[asm_constraint.c_next])) - - def fix_constraints(self): - """Fix next block constraints""" - # destination -> associated constraints - dests = {} - for constraint in self.bto: - dests.setdefault(constraint.label, set()).add(constraint) - - self.bto = set(self._filter_constraint(constraints) - for constraints in dests.itervalues()) - - -class asm_block_bad(asm_bloc): - - """Stand for a *bad* ASM block (malformed, unreachable, - not disassembled, ...)""" - - ERROR_TYPES = {-1: "Unknown error", - 0: "Unable to disassemble", - 1: "Null starting block", - 2: "Address forbidden by dont_dis", - } - - def __init__(self, label=None, alignment=1, errno=-1, *args, **kwargs): - """Instanciate an asm_block_bad. - @label, @alignement: same as asm_bloc.__init__ - @errno: (optional) specify a error type associated with the block - """ - super(asm_block_bad, self).__init__(label, alignment, *args, **kwargs) - self._errno = errno - - def __str__(self): - error_txt = self.ERROR_TYPES.get(self._errno, self._errno) - return "\n".join([str(self.label), - "\tBad block: %s" % error_txt]) - - def addline(self, *args, **kwargs): - raise RuntimeError("An asm_block_bad cannot have line") - - def addto(self, *args, **kwargs): - raise RuntimeError("An asm_block_bad cannot have bto") - - def split(self, *args, **kwargs): - raise RuntimeError("An asm_block_bad cannot be splitted") - - -class asm_symbol_pool: - - def __init__(self): - self._labels = [] - self._name2label = {} - self._offset2label = {} - self._label_num = 0 - - def add_label(self, name, offset=None): - """ - Create and add a label to the symbol_pool - @name: label's name - @offset: (optional) label's offset - """ - label = asm_label(name, offset) - - # Test for collisions - if (label.offset in self._offset2label and - label != self._offset2label[label.offset]): - raise ValueError('symbol %s has same offset as %s' % - (label, self._offset2label[label.offset])) - if (label.name in self._name2label and - label != self._name2label[label.name]): - raise ValueError('symbol %s has same name as %s' % - (label, self._name2label[label.name])) - - self._labels.append(label) - if label.offset is not None: - self._offset2label[label.offset] = label - if label.name != "": - self._name2label[label.name] = label - return label - - def remove_label(self, label): - """ - Delete a @label - """ - self._name2label.pop(label.name, None) - self._offset2label.pop(label.offset, None) - if label in self._labels: - self._labels.remove(label) - - def del_label_offset(self, label): - """Unpin the @label from its offset""" - self._offset2label.pop(label.offset, None) - label.offset = None - - def getby_offset(self, offset): - """Retrieve label using its @offset""" - return self._offset2label.get(offset, None) - - def getby_name(self, name): - """Retrieve label using its @name""" - return self._name2label.get(name, None) - - def getby_name_create(self, name): - """Get a label from its @name, create it if it doesn't exist""" - label = self.getby_name(name) - if label is None: - label = self.add_label(name) - return label - - def getby_offset_create(self, offset): - """Get a label from its @offset, create it if it doesn't exist""" - label = self.getby_offset(offset) - if label is None: - label = self.add_label(offset, offset) - return label - - def rename_label(self, label, newname): - """Rename the @label name to @newname""" - if newname in self._name2label: - raise ValueError('Symbol already known') - self._name2label.pop(label.name, None) - label.name = newname - self._name2label[label.name] = label - - def set_offset(self, label, offset): - """Pin the @label from at @offset - Note that there is a special case when the offset is a list - it happens when offsets are recomputed in resolve_symbol* - """ - if label is None: - raise ValueError('label should not be None') - if not label.name in self._name2label: - raise ValueError('label %s not in symbol pool' % label) - if offset is not None and offset in self._offset2label: - raise ValueError('Conflict in label %s' % label) - self._offset2label.pop(label.offset, None) - label.offset = offset - if is_int(label.offset): - self._offset2label[label.offset] = label - - @property - def items(self): - """Return all labels""" - return self._labels - - def __str__(self): - return reduce(lambda x, y: x + str(y) + '\n', self._labels, "") - - def __getitem__(self, item): - if item in self._name2label: - return self._name2label[item] - if item in self._offset2label: - return self._offset2label[item] - raise KeyError('unknown symbol %r' % item) - - def __contains__(self, item): - return item in self._name2label or item in self._offset2label - - def merge(self, symbol_pool): - """Merge with another @symbol_pool""" - self._labels += symbol_pool._labels - self._name2label.update(symbol_pool._name2label) - self._offset2label.update(symbol_pool._offset2label) - - def gen_label(self): - """Generate a new unpinned label""" - label = self.add_label("lbl_gen_%.8X" % (self._label_num)) - self._label_num += 1 - return label - - -class AsmCFG(DiGraph): - - """Directed graph standing for a ASM Control Flow Graph with: - - nodes: asm_bloc - - edges: constraints between blocks, synchronized with asm_bloc's "bto" - - Specialized the .dot export and force the relation between block to be uniq, - and associated with a constraint. - - Offer helpers on AsmCFG management, such as research by label, sanity - checking and mnemonic size guessing. - """ - - # Internal structure for pending management - AsmCFGPending = namedtuple("AsmCFGPending", - ["waiter", "constraint"]) - - def __init__(self, *args, **kwargs): - super(AsmCFG, self).__init__(*args, **kwargs) - # Edges -> constraint - self.edges2constraint = {} - # Expected asm_label -> set( (src, dst), constraint ) - self._pendings = {} - # Label2block built on the fly - self._label2block = {} - - # Compatibility with old list API - def append(self, *args, **kwargs): - raise DeprecationWarning("AsmCFG is a graph, use add_node") - - def remove(self, *args, **kwargs): - raise DeprecationWarning("AsmCFG is a graph, use del_node") - - def __getitem__(self, *args, **kwargs): - raise DeprecationWarning("Order of AsmCFG elements is not reliable") - - def __iter__(self): - """Iterator on asm_bloc composing the current graph""" - return iter(self._nodes) - - def __len__(self): - """Return the number of blocks in AsmCFG""" - return len(self._nodes) - - # Manage graph with associated constraints - def add_edge(self, src, dst, constraint): - """Add an edge to the graph - @src: asm_bloc instance, source - @dst: asm_block instance, destination - @constraint: constraint associated to this edge - """ - # Sanity check - assert (src, dst) not in self.edges2constraint - - # Add the edge to src.bto if needed - if dst.label not in [cons.label for cons in src.bto]: - src.bto.add(asm_constraint(dst.label, constraint)) - - # Add edge - self.edges2constraint[(src, dst)] = constraint - super(AsmCFG, self).add_edge(src, dst) - - def add_uniq_edge(self, src, dst, constraint): - """Add an edge from @src to @dst if it doesn't already exist""" - if (src not in self._nodes_succ or - dst not in self._nodes_succ[src]): - self.add_edge(src, dst, constraint) - - def del_edge(self, src, dst): - """Delete the edge @src->@dst and its associated constraint""" - # Delete from src.bto - to_remove = [cons for cons in src.bto if cons.label == dst.label] - if to_remove: - assert len(to_remove) == 1 - src.bto.remove(to_remove[0]) - - # Del edge - del self.edges2constraint[(src, dst)] - super(AsmCFG, self).del_edge(src, dst) - - def add_node(self, block): - """Add the block @block to the current instance, if it is not already in - @block: asm_bloc instance - - Edges will be created for @block.bto, if destinations are already in - this instance. If not, they will be resolved when adding these - aforementionned destinations. - `self.pendings` indicates which blocks are not yet resolved. - """ - status = super(AsmCFG, self).add_node(block) - if not status: - return status - - # Update waiters - if block.label in self._pendings: - for bblpend in self._pendings[block.label]: - self.add_edge(bblpend.waiter, block, bblpend.constraint) - del self._pendings[block.label] - - # Synchronize edges with block destinations - self._label2block[block.label] = block - for constraint in block.bto: - dst = self._label2block.get(constraint.label, - None) - if dst is None: - # Block is yet unknown, add it to pendings - to_add = self.AsmCFGPending(waiter=block, - constraint=constraint.c_t) - self._pendings.setdefault(constraint.label, - set()).add(to_add) - else: - # Block is already in known nodes - self.add_edge(block, dst, constraint.c_t) - - return status - - def del_node(self, block): - super(AsmCFG, self).del_node(block) - del self._label2block[block.label] - - def merge(self, graph): - """Merge with @graph, taking in account constraints""" - # -> add_edge(x, y, constraint) - for node in graph._nodes: - self.add_node(node) - for edge in graph._edges: - # Use "_uniq_" beacause the edge can already exist due to add_node - self.add_uniq_edge(*edge, constraint=graph.edges2constraint[edge]) - - def node2lines(self, node): - yield self.DotCellDescription(text=str(node.label.name), - attr={'align': 'center', - 'colspan': 2, - 'bgcolor': 'grey'}) - - if isinstance(node, asm_block_bad): - yield [self.DotCellDescription( - text=node.ERROR_TYPES.get(node._errno, - node._errno), - attr={})] - raise StopIteration - for line in node.lines: - if self._dot_offset: - yield [self.DotCellDescription(text="%.8X" % line.offset, - attr={}), - self.DotCellDescription(text=str(line), attr={})] - else: - yield self.DotCellDescription(text=str(line), attr={}) - - def node_attr(self, node): - if isinstance(node, asm_block_bad): - return {'style': 'filled', 'fillcolor': 'red'} - return {} - - def edge_attr(self, src, dst): - cst = self.edges2constraint.get((src, dst), None) - edge_color = "blue" - - if len(self.successors(src)) > 1: - if cst == asm_constraint.c_next: - edge_color = "red" - else: - edge_color = "limegreen" - - return {"color": edge_color} - - def dot(self, offset=False): - """ - @offset: (optional) if set, add the corresponding offsets in each node - """ - self._dot_offset = offset - return super(AsmCFG, self).dot() - - # Helpers - @property - def pendings(self): - """Dictionary of label -> set(AsmCFGPending instance) indicating - which label are missing in the current instance. - A label is missing if a block which is already in nodes has constraints - with him (thanks to its .bto) and the corresponding block is not yet in - nodes - """ - return self._pendings - - def _build_label2block(self): - self._label2block = {block.label: block - for block in self._nodes} - - def label2block(self, label): - """Return the block corresponding to label @label - @label: asm_label instance or ExprId(asm_label) instance""" - return self._label2block[label] - - def rebuild_edges(self): - """Consider blocks '.bto' and rebuild edges according to them, ie: - - update constraint type - - add missing edge - - remove no more used edge - - This method should be called if a block's '.bto' in nodes have been - modified without notifying this instance to resynchronize edges. - """ - self._build_label2block() - for block in self._nodes: - edges = [] - # Rebuild edges from bto - for constraint in block.bto: - dst = self._label2block.get(constraint.label, - None) - if dst is None: - # Missing destination, add to pendings - self._pendings.setdefault(constraint.label, - set()).add(self.AsmCFGPending(block, - constraint.c_t)) - continue - edge = (block, dst) - edges.append(edge) - if edge in self._edges: - # Already known edge, constraint may have changed - self.edges2constraint[edge] = constraint.c_t - else: - # An edge is missing - self.add_edge(edge[0], edge[1], constraint.c_t) - - # Remove useless edges - for succ in self.successors(block): - edge = (block, succ) - if edge not in edges: - self.del_edge(*edge) - - def get_bad_blocks(self): - """Iterator on asm_block_bad elements""" - # A bad asm block is always a leaf - for block in self.leaves(): - if isinstance(block, asm_block_bad): - yield block - - def get_bad_blocks_predecessors(self, strict=False): - """Iterator on block with an asm_block_bad destination - @strict: (optional) if set, return block with only bad - successors - """ - # Avoid returning the same block - done = set() - for badblock in self.get_bad_blocks(): - for predecessor in self.predecessors_iter(badblock): - if predecessor not in done: - if (strict and - not all(isinstance(block, asm_block_bad) - for block in self.successors_iter(predecessor))): - continue - yield predecessor - done.add(predecessor) - - def sanity_check(self): - """Do sanity checks on blocks' constraints: - * no pendings - * no multiple next constraint to same block - * no next constraint to self - """ - - if len(self._pendings) != 0: - raise RuntimeError("Some blocks are missing: %s" % map(str, - self._pendings.keys())) - - next_edges = {edge: constraint - for edge, constraint in self.edges2constraint.iteritems() - if constraint == asm_constraint.c_next} - - for block in self._nodes: - # No next constraint to self - if (block, block) in next_edges: - raise RuntimeError('Bad constraint: self in next') - - # No multiple next constraint to same block - pred_next = list(pblock - for (pblock, dblock) in next_edges - if dblock == block) - - if len(pred_next) > 1: - raise RuntimeError("Too many next constraints for bloc %r" - "(%s)" % (block.label, - map(lambda x: x.label, pred_next))) - - def guess_blocks_size(self, mnemo): - """Asm and compute max block size - Add a 'size' and 'max_size' attribute on each block - @mnemo: metamn instance""" - for block in self._nodes: - size = 0 - for instr in block.lines: - if isinstance(instr, asm_raw): - # for special asm_raw, only extract len - if isinstance(instr.raw, list): - data = None - if len(instr.raw) == 0: - l = 0 - else: - l = instr.raw[0].size / 8 * len(instr.raw) - elif isinstance(instr.raw, str): - data = instr.raw - l = len(data) - else: - raise NotImplementedError('asm raw') - else: - # Assemble the instruction to retrieve its len. - # If the instruction uses symbol it will fail - # In this case, the max_instruction_len is used - try: - candidates = mnemo.asm(instr) - l = len(candidates[-1]) - except: - l = mnemo.max_instruction_len - data = None - instr.data = data - instr.l = l - size += l - - block.size = size - block.max_size = size - log_asmbloc.info("size: %d max: %d", block.size, block.max_size) - - def apply_splitting(self, symbol_pool, dis_block_callback=None, **kwargs): - """Consider @self' bto destinations and split block in @self if one of - these destinations jumps in the middle of this block. - In order to work, they must be only one block in @self per label in - @symbol_pool (which is true if @self come from the same disasmEngine). - - @symbol_pool: asm_symbol_pool instance associated with @self'labels - @dis_block_callback: (optional) if set, this callback will be called on - new block destinations - @kwargs: (optional) named arguments to pass to dis_block_callback - """ - # Get all possible destinations not yet resolved, with a resolved - # offset - block_dst = [label.offset - for label in self.pendings - if label.offset is not None] - - todo = self.nodes().copy() - rebuild_needed = False - - while todo: - # Find a block with a destination inside another one - cur_block = todo.pop() - range_start, range_stop = cur_block.get_range() - - for off in block_dst: - if not (off > range_start and off < range_stop): - continue - - # `cur_block` must be splitted at offset `off` - label = symbol_pool.getby_offset_create(off) - new_b = cur_block.split(off, label) - log_asmbloc.debug("Split block %x", off) - if new_b is None: - log_asmbloc.error("Cannot split %x!!", off) - continue - - # Remove pending from cur_block - # Links from new_b will be generated in rebuild_edges - for dst in new_b.bto: - if dst.label not in self.pendings: - continue - self.pendings[dst.label] = set(pending for pending in self.pendings[dst.label] - if pending.waiter != cur_block) - - # The new block destinations may need to be disassembled - if dis_block_callback: - offsets_to_dis = set(constraint.label.offset - for constraint in new_b.bto) - dis_block_callback(cur_bloc=new_b, - offsets_to_dis=offsets_to_dis, - symbol_pool=symbol_pool, **kwargs) - - # Update structure - rebuild_needed = True - self.add_node(new_b) - - # The new block must be considered - todo.add(new_b) - range_start, range_stop = cur_block.get_range() - - # Rebuild edges to match new blocks'bto - if rebuild_needed: - self.rebuild_edges() - - def __str__(self): - out = [] - for node in self.nodes(): - out.append(str(node)) - for nodeA, nodeB in self.edges(): - out.append("%s -> %s" % (nodeA.label, nodeB.label)) - return '\n'.join(out) - - def __repr__(self): - return "<%s %s>" % (self.__class__.__name__, hex(id(self))) - -# Out of _merge_blocks to be computed only once -_acceptable_block = lambda block: (not isinstance(block, asm_block_bad) and - len(block.lines) > 0) -_parent = MatchGraphJoker(restrict_in=False, filt=_acceptable_block) -_son = MatchGraphJoker(restrict_out=False, filt=_acceptable_block) -_expgraph = _parent >> _son - - -def _merge_blocks(dg, graph): - """Graph simplification merging asm_bloc with one and only one son with this - son if this son has one and only one parent""" - - # Blocks to ignore, because they have been removed from the graph - to_ignore = set() - - for match in _expgraph.match(graph): - - # Get matching blocks - block, succ = match[_parent], match[_son] - - # Ignore already deleted blocks - if (block in to_ignore or - succ in to_ignore): - continue - - # Remove block last instruction if needed - last_instr = block.lines[-1] - if last_instr.delayslot > 0: - # TODO: delayslot - raise RuntimeError("Not implemented yet") - - if last_instr.is_subcall(): - continue - if last_instr.breakflow() and last_instr.dstflow(): - block.lines.pop() - - # Merge block - block.lines += succ.lines - for nextb in graph.successors_iter(succ): - graph.add_edge(block, nextb, graph.edges2constraint[(succ, nextb)]) - - graph.del_node(succ) - to_ignore.add(succ) - - -bbl_simplifier = DiGraphSimplifier() -bbl_simplifier.enable_passes([_merge_blocks]) - - -def conservative_asm(mnemo, instr, symbols, conservative): - """ - Asm instruction; - Try to keep original instruction bytes if it exists - """ - candidates = mnemo.asm(instr, symbols) - if not candidates: - raise ValueError('cannot asm:%s' % str(instr)) - if not hasattr(instr, "b"): - return candidates[0], candidates - if instr.b in candidates: - return instr.b, candidates - if conservative: - for c in candidates: - if len(c) == len(instr.b): - return c, candidates - return candidates[0], candidates - - -def fix_expr_val(expr, symbols): - """Resolve an expression @expr using @symbols""" - def expr_calc(e): - if isinstance(e, m2_expr.ExprId): - s = symbols._name2label[e.name] - e = m2_expr.ExprInt(s.offset, e.size) - return e - result = expr.visit(expr_calc) - result = expr_simp(result) - if not isinstance(result, m2_expr.ExprInt): - raise RuntimeError('Cannot resolve symbol %s' % expr) - return result - - -def fix_label_offset(symbol_pool, label, offset, modified): - """Fix the @label offset to @offset. If the @offset has changed, add @label - to @modified - @symbol_pool: current symbol_pool - """ - if label.offset == offset: - return - symbol_pool.set_offset(label, offset) - modified.add(label) - - -class BlockChain(object): - - """Manage blocks linked with an asm_constraint_next""" - - def __init__(self, symbol_pool, blocks): - self.symbol_pool = symbol_pool - self.blocks = blocks - self.place() - - @property - def pinned(self): - """Return True iff at least one block is pinned""" - return self.pinned_block_idx is not None - - def _set_pinned_block_idx(self): - self.pinned_block_idx = None - for i, block in enumerate(self.blocks): - if is_int(block.label.offset): - if self.pinned_block_idx is not None: - raise ValueError("Multiples pinned block detected") - self.pinned_block_idx = i - - def place(self): - """Compute BlockChain min_offset and max_offset using pinned block and - blocks' size - """ - self._set_pinned_block_idx() - self.max_size = 0 - for block in self.blocks: - self.max_size += block.max_size + block.alignment - 1 - - # Check if chain has one block pinned - if not self.pinned: - return - - offset_base = self.blocks[self.pinned_block_idx].label.offset - assert(offset_base % self.blocks[self.pinned_block_idx].alignment == 0) - - self.offset_min = offset_base - for block in self.blocks[:self.pinned_block_idx - 1:-1]: - self.offset_min -= block.max_size + \ - (block.alignment - block.max_size) % block.alignment - - self.offset_max = offset_base - for block in self.blocks[self.pinned_block_idx:]: - self.offset_max += block.max_size + \ - (block.alignment - block.max_size) % block.alignment - - def merge(self, chain): - """Best effort merge two block chains - Return the list of resulting blockchains""" - self.blocks += chain.blocks - self.place() - return [self] - - def fix_blocks(self, modified_labels): - """Propagate a pinned to its blocks' neighbour - @modified_labels: store new pinned labels""" - - if not self.pinned: - raise ValueError('Trying to fix unpinned block') - - # Propagate offset to blocks before pinned block - pinned_block = self.blocks[self.pinned_block_idx] - offset = pinned_block.label.offset - if offset % pinned_block.alignment != 0: - raise RuntimeError('Bad alignment') - - for block in self.blocks[:self.pinned_block_idx - 1:-1]: - new_offset = offset - block.size - new_offset = new_offset - new_offset % pinned_block.alignment - fix_label_offset(self.symbol_pool, - block.label, - new_offset, - modified_labels) - - # Propagate offset to blocks after pinned block - offset = pinned_block.label.offset + pinned_block.size - - last_block = pinned_block - for block in self.blocks[self.pinned_block_idx + 1:]: - offset += (- offset) % last_block.alignment - fix_label_offset(self.symbol_pool, - block.label, - offset, - modified_labels) - offset += block.size - last_block = block - return modified_labels - - -class BlockChainWedge(object): - - """Stand for wedges between blocks""" - - def __init__(self, symbol_pool, offset, size): - self.symbol_pool = symbol_pool - self.offset = offset - self.max_size = size - self.offset_min = offset - self.offset_max = offset + size - - def merge(self, chain): - """Best effort merge two block chains - Return the list of resulting blockchains""" - self.symbol_pool.set_offset(chain.blocks[0].label, self.offset_max) - chain.place() - return [self, chain] - - -def group_constrained_blocks(symbol_pool, blocks): - """ - Return the BlockChains list built from grouped asm blocks linked by - asm_constraint_next - @blocks: a list of asm block - """ - log_asmbloc.info('group_constrained_blocks') - - # Group adjacent blocks - remaining_blocks = list(blocks) - known_block_chains = {} - lbl2block = {block.label: block for block in blocks} - - while remaining_blocks: - # Create a new block chain - block_list = [remaining_blocks.pop()] - - # Find sons in remainings blocks linked with a next constraint - while True: - # Get next block - next_label = block_list[-1].get_next() - if next_label is None or next_label not in lbl2block: - break - next_block = lbl2block[next_label] - - # Add the block at the end of the current chain - if next_block not in remaining_blocks: - break - block_list.append(next_block) - remaining_blocks.remove(next_block) - - # Check if son is in a known block group - if next_label is not None and next_label in known_block_chains: - block_list += known_block_chains[next_label] - del known_block_chains[next_label] - - known_block_chains[block_list[0].label] = block_list - - out_block_chains = [] - for label in known_block_chains: - chain = BlockChain(symbol_pool, known_block_chains[label]) - out_block_chains.append(chain) - return out_block_chains - - -def get_blockchains_address_interval(blockChains, dst_interval): - """Compute the interval used by the pinned @blockChains - Check if the placed chains are in the @dst_interval""" - - allocated_interval = interval() - for chain in blockChains: - if not chain.pinned: - continue - chain_interval = interval([(chain.offset_min, chain.offset_max - 1)]) - if chain_interval not in dst_interval: - raise ValueError('Chain placed out of destination interval') - allocated_interval += chain_interval - return allocated_interval - - -def resolve_symbol(blockChains, symbol_pool, dst_interval=None): - """Place @blockChains in the @dst_interval""" - - log_asmbloc.info('resolve_symbol') - if dst_interval is None: - dst_interval = interval([(0, 0xFFFFFFFFFFFFFFFF)]) - - forbidden_interval = interval( - [(-1, 0xFFFFFFFFFFFFFFFF + 1)]) - dst_interval - allocated_interval = get_blockchains_address_interval(blockChains, - dst_interval) - log_asmbloc.debug('allocated interval: %s', allocated_interval) - - pinned_chains = [chain for chain in blockChains if chain.pinned] - - # Add wedge in forbidden intervals - for start, stop in forbidden_interval.intervals: - wedge = BlockChainWedge( - symbol_pool, offset=start, size=stop + 1 - start) - pinned_chains.append(wedge) - - # Try to place bigger blockChains first - pinned_chains.sort(key=lambda x: x.offset_min) - blockChains.sort(key=lambda x: -x.max_size) - - fixed_chains = list(pinned_chains) - - log_asmbloc.debug("place chains") - for chain in blockChains: - if chain.pinned: - continue - fixed = False - for i in xrange(1, len(fixed_chains)): - prev_chain = fixed_chains[i - 1] - next_chain = fixed_chains[i] - - if prev_chain.offset_max + chain.max_size < next_chain.offset_min: - new_chains = prev_chain.merge(chain) - fixed_chains[i - 1:i] = new_chains - fixed = True - break - if not fixed: - raise RuntimeError('Cannot find enough space to place blocks') - - return [chain for chain in fixed_chains if isinstance(chain, BlockChain)] - - -def filter_exprid_label(exprs): - """Extract labels from list of ExprId @exprs""" - return set(expr.name for expr in exprs if isinstance(expr.name, asm_label)) - - -def get_block_labels(block): - """Extract labels used by @block""" - symbols = set() - for instr in block.lines: - if isinstance(instr, asm_raw): - if isinstance(instr.raw, list): - for expr in instr.raw: - symbols.update(m2_expr.get_expr_ids(expr)) - else: - for arg in instr.args: - symbols.update(m2_expr.get_expr_ids(arg)) - labels = filter_exprid_label(symbols) - return labels - - -def assemble_block(mnemo, block, symbol_pool, conservative=False): - """Assemble a @block using @symbol_pool - @conservative: (optional) use original bytes when possible - """ - offset_i = 0 - - for instr in block.lines: - if isinstance(instr, asm_raw): - if isinstance(instr.raw, list): - # Fix special asm_raw - data = "" - for expr in instr.raw: - expr_int = fix_expr_val(expr, symbol_pool) - data += pck[expr_int.size](expr_int.arg) - instr.data = data - - instr.offset = offset_i - offset_i += instr.l - continue - - # Assemble an instruction - saved_args = list(instr.args) - instr.offset = block.label.offset + offset_i - - # Replace instruction's arguments by resolved ones - instr.args = instr.resolve_args_with_symbols(symbol_pool) - - if instr.dstflow(): - instr.fixDstOffset() - - old_l = instr.l - cached_candidate, _ = conservative_asm(mnemo, instr, symbol_pool, - conservative) - - # Restore original arguments - instr.args = saved_args - - # We need to update the block size - block.size = block.size - old_l + len(cached_candidate) - instr.data = cached_candidate - instr.l = len(cached_candidate) - - offset_i += instr.l - - -def asmbloc_final(mnemo, blocks, blockChains, symbol_pool, conservative=False): - """Resolve and assemble @blockChains using @symbol_pool until fixed point is - reached""" - - log_asmbloc.debug("asmbloc_final") - - # Init structures - lbl2block = {block.label: block for block in blocks} - blocks_using_label = {} - for block in blocks: - labels = get_block_labels(block) - for label in labels: - blocks_using_label.setdefault(label, set()).add(block) - - block2chain = {} - for chain in blockChains: - for block in chain.blocks: - block2chain[block] = chain - - # Init worklist - blocks_to_rework = set(blocks) - - # Fix and re-assemble blocks until fixed point is reached - while True: - - # Propagate pinned blocks into chains - modified_labels = set() - for chain in blockChains: - chain.fix_blocks(modified_labels) - - for label in modified_labels: - # Retrive block with modified reference - if label in lbl2block: - blocks_to_rework.add(lbl2block[label]) - - # Enqueue blocks referencing a modified label - if label not in blocks_using_label: - continue - for block in blocks_using_label[label]: - blocks_to_rework.add(block) - - # No more work - if not blocks_to_rework: - break - - while blocks_to_rework: - block = blocks_to_rework.pop() - assemble_block(mnemo, block, symbol_pool, conservative) - - -def asm_resolve_final(mnemo, blocks, symbol_pool, dst_interval=None): - """Resolve and assemble @blocks using @symbol_pool into interval - @dst_interval""" - - blocks.sanity_check() - - blocks.guess_blocks_size(mnemo) - blockChains = group_constrained_blocks(symbol_pool, blocks) - resolved_blockChains = resolve_symbol( - blockChains, symbol_pool, dst_interval) - - asmbloc_final(mnemo, blocks, resolved_blockChains, symbol_pool) - patches = {} - output_interval = interval() - - for block in blocks: - offset = block.label.offset - for instr in block.lines: - if not instr.data: - # Empty line - continue - assert len(instr.data) == instr.l - patches[offset] = instr.data - instruction_interval = interval([(offset, offset + instr.l - 1)]) - if not (instruction_interval & output_interval).empty: - raise RuntimeError("overlapping bytes %X" % int(offset)) - instr.offset = offset - offset += instr.l - return patches - - -class disasmEngine(object): - - """Disassembly engine, taking care of disassembler options and mutli-block - strategy. - - Engine options: - - + Object supporting membership test (offset in ..) - - dont_dis: stop the current disassembly branch if reached - - split_dis: force a basic block end if reached, - with a next constraint on its successor - - dont_dis_retcall_funcs: stop disassembly after a call to one - of the given functions - - + On/Off - - follow_call: recursively disassemble CALL destinations - - dontdis_retcall: stop on CALL return addresses - - dont_dis_nulstart_bloc: stop if a block begin with a few \x00 - - + Number - - lines_wd: maximum block's size (in number of instruction) - - blocs_wd: maximum number of distinct disassembled block - - + callback(arch, attrib, pool_bin, cur_bloc, offsets_to_dis, - symbol_pool) - - dis_bloc_callback: callback after each new disassembled block - - The engine also tracks already handled block, for performance and to avoid - infinite cycling. - Addresses of disassembled block is in the attribute `job_done`. - To force a new disassembly, the targeted offset must first be removed from - this structure. - """ - - def __init__(self, arch, attrib, bin_stream, **kwargs): - """Instanciate a new disassembly engine - @arch: targeted architecture - @attrib: architecture attribute - @bin_stream: bytes source - @kwargs: (optional) custom options - """ - self.arch = arch - self.attrib = attrib - self.bin_stream = bin_stream - self.symbol_pool = asm_symbol_pool() - self.job_done = set() - - # Setup options - self.dont_dis = [] - self.split_dis = [] - self.follow_call = False - self.dontdis_retcall = False - self.lines_wd = None - self.blocs_wd = None - self.dis_bloc_callback = None - self.dont_dis_nulstart_bloc = False - self.dont_dis_retcall_funcs = set() - - # Override options if needed - self.__dict__.update(kwargs) - - def _dis_bloc(self, offset): - """Disassemble the block at offset @offset - Return the created asm_bloc and future offsets to disassemble - """ - - lines_cpt = 0 - in_delayslot = False - delayslot_count = self.arch.delayslot - offsets_to_dis = set() - add_next_offset = False - label = self.symbol_pool.getby_offset_create(offset) - cur_block = asm_bloc(label) - log_asmbloc.debug("dis at %X", int(offset)) - while not in_delayslot or delayslot_count > 0: - if in_delayslot: - delayslot_count -= 1 - - if offset in self.dont_dis: - if not cur_block.lines: - self.job_done.add(offset) - # Block is empty -> bad block - cur_block = asm_block_bad(label, errno=2) - else: - # Block is not empty, stop the desassembly pass and add a - # constraint to the next block - cur_block.add_cst(offset, asm_constraint.c_next, - self.symbol_pool) - break - - if lines_cpt > 0 and offset in self.split_dis: - cur_block.add_cst(offset, asm_constraint.c_next, - self.symbol_pool) - offsets_to_dis.add(offset) - break - - lines_cpt += 1 - if self.lines_wd is not None and lines_cpt > self.lines_wd: - log_asmbloc.debug("lines watchdog reached at %X", int(offset)) - break - - if offset in self.job_done: - cur_block.add_cst(offset, asm_constraint.c_next, - self.symbol_pool) - break - - off_i = offset - try: - instr = self.arch.dis(self.bin_stream, self.attrib, offset) - except (Disasm_Exception, IOError), e: - log_asmbloc.warning(e) - instr = None - - if instr is None: - log_asmbloc.warning("cannot disasm at %X", int(off_i)) - if not cur_block.lines: - self.job_done.add(offset) - # Block is empty -> bad block - cur_block = asm_block_bad(label, errno=0) - else: - # Block is not empty, stop the desassembly pass and add a - # constraint to the next block - cur_block.add_cst(off_i, asm_constraint.c_next, - self.symbol_pool) - break - - # XXX TODO nul start block option - if self.dont_dis_nulstart_bloc and instr.b.count('\x00') == instr.l: - log_asmbloc.warning("reach nul instr at %X", int(off_i)) - if not cur_block.lines: - # Block is empty -> bad block - cur_block = asm_block_bad(label, errno=1) - else: - # Block is not empty, stop the desassembly pass and add a - # constraint to the next block - cur_block.add_cst(off_i, asm_constraint.c_next, - self.symbol_pool) - break - - # special case: flow graph modificator in delayslot - if in_delayslot and instr and (instr.splitflow() or instr.breakflow()): - add_next_offset = True - break - - self.job_done.add(offset) - log_asmbloc.debug("dis at %X", int(offset)) - - offset += instr.l - log_asmbloc.debug(instr) - log_asmbloc.debug(instr.args) - - cur_block.addline(instr) - if not instr.breakflow(): - continue - # test split - if instr.splitflow() and not (instr.is_subcall() and self.dontdis_retcall): - add_next_offset = True - pass - if instr.dstflow(): - instr.dstflow2label(self.symbol_pool) - dst = instr.getdstflow(self.symbol_pool) - dstn = [] - for d in dst: - if isinstance(d, m2_expr.ExprId) and \ - isinstance(d.name, asm_label): - dstn.append(d.name) - if d.name.offset in self.dont_dis_retcall_funcs: - add_next_offset = False - dst = dstn - if (not instr.is_subcall()) or self.follow_call: - cur_block.bto.update( - [asm_constraint(x, asm_constraint.c_to) for x in dst]) - - # get in delayslot mode - in_delayslot = True - delayslot_count = instr.delayslot - - for c in cur_block.bto: - offsets_to_dis.add(c.label.offset) - - if add_next_offset: - cur_block.add_cst(offset, asm_constraint.c_next, self.symbol_pool) - offsets_to_dis.add(offset) - - # Fix multiple constraints - cur_block.fix_constraints() - - if self.dis_bloc_callback is not None: - self.dis_bloc_callback(mn=self.arch, attrib=self.attrib, - pool_bin=self.bin_stream, cur_bloc=cur_block, - offsets_to_dis=offsets_to_dis, - symbol_pool=self.symbol_pool) - return cur_block, offsets_to_dis - - def dis_bloc(self, offset): - """Disassemble the block at offset @offset and return the created - asm_bloc - @offset: targeted offset to disassemble - """ - current_block, _ = self._dis_bloc(offset) - return current_block - - def dis_multibloc(self, offset, blocs=None): - """Disassemble every block reachable from @offset regarding - specific disasmEngine conditions - Return an AsmCFG instance containing disassembled blocks - @offset: starting offset - @blocs: (optional) AsmCFG instance of already disassembled blocks to - merge with - """ - log_asmbloc.info("dis bloc all") - if blocs is None: - blocs = AsmCFG() - todo = [offset] - - bloc_cpt = 0 - while len(todo): - bloc_cpt += 1 - if self.blocs_wd is not None and bloc_cpt > self.blocs_wd: - log_asmbloc.debug("blocs watchdog reached at %X", int(offset)) - break - - target_offset = int(todo.pop(0)) - if (target_offset is None or - target_offset in self.job_done): - continue - cur_block, nexts = self._dis_bloc(target_offset) - todo += nexts - blocs.add_node(cur_block) - - blocs.apply_splitting(self.symbol_pool, - dis_block_callback=self.dis_bloc_callback, - mn=self.arch, attrib=self.attrib, - pool_bin=self.bin_stream) - return blocs +log_asmbloc = log_asmblock diff --git a/miasm2/core/asmblock.py b/miasm2/core/asmblock.py new file mode 100644 index 00000000..72f259f9 --- /dev/null +++ b/miasm2/core/asmblock.py @@ -0,0 +1,1562 @@ +#-*- coding:utf-8 -*- + +import logging +import inspect +import warnings +from collections import namedtuple + +import miasm2.expression.expression as m2_expr +from miasm2.expression.simplifications import expr_simp +from miasm2.expression.modint import moduint, modint +from miasm2.core.utils import Disasm_Exception, pck +from miasm2.core.graph import DiGraph, DiGraphSimplifier, MatchGraphJoker +from miasm2.core.interval import interval + + +log_asmblock = logging.getLogger("asmblock") +console_handler = logging.StreamHandler() +console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) +log_asmblock.addHandler(console_handler) +log_asmblock.setLevel(logging.WARNING) + + +def is_int(a): + return isinstance(a, int) or isinstance(a, long) or \ + isinstance(a, moduint) or isinstance(a, modint) + + +def expr_is_label(e): + return isinstance(e, m2_expr.ExprId) and isinstance(e.name, AsmLabel) + + +def expr_is_int_or_label(e): + return isinstance(e, m2_expr.ExprInt) or \ + (isinstance(e, m2_expr.ExprId) and isinstance(e.name, AsmLabel)) + + +class AsmLabel(object): + + "Stand for an assembly label" + + def __init__(self, name="", offset=None): + self.fixedblocs = False + if is_int(name): + name = "loc_%.16X" % (int(name) & 0xFFFFFFFFFFFFFFFF) + self.name = name + self.attrib = None + if offset is None: + self.offset = offset + else: + self.offset = int(offset) + + def __str__(self): + if isinstance(self.offset, (int, long)): + return "%s:0x%08x" % (self.name, self.offset) + else: + return "%s:%s" % (self.name, str(self.offset)) + + def __repr__(self): + rep = '<%s ' % self.__class__.__name__ + if self.name: + rep += repr(self.name) + ' ' + rep += '>' + return rep + + +class asm_label(AsmLabel): + + def __init__(self, name="", offset=None): + warnings.warn('DEPRECATION WARNING: use "AsmLabel" instead of "asm_label"') + super(asm_label, self).__init__(name, offset) + +class AsmRaw(object): + + def __init__(self, raw=""): + self.raw = raw + + def __str__(self): + return repr(self.raw) + + +class asm_raw(AsmRaw): + + def __init__(self, raw=""): + warnings.warn('DEPRECATION WARNING: use "AsmRaw" instead of "asm_raw"') + super(asm_label, self).__init__(raw) + + +class AsmConstraint(object): + c_to = "c_to" + c_next = "c_next" + + def __init__(self, label, c_t=c_to): + # Sanity check + assert isinstance(label, AsmLabel) + + self.label = label + self.c_t = c_t + + def __str__(self): + return "%s:%s" % (str(self.c_t), str(self.label)) + + +class asm_constraint(AsmConstraint): + + def __init__(self, label, c_t=AsmConstraint.c_to): + warnings.warn('DEPRECATION WARNING: use "AsmConstraint" instead of "asm_constraint"') + super(asm_constraint, self).__init__(label, c_t) + + +class AsmConstraintNext(AsmConstraint): + + def __init__(self, label): + super(AsmConstraintNext, self).__init__( + label, c_t=AsmConstraint.c_next) + + +class asm_constraint_next(AsmConstraint): + + def __init__(self, label): + warnings.warn('DEPRECATION WARNING: use "AsmConstraintNext" instead of "asm_constraint_next"') + super(asm_constraint_next, self).__init__(label) + + +class AsmConstraintTo(AsmConstraint): + + def __init__(self, label): + super(AsmConstraintTo, self).__init__( + label, c_t=AsmConstraint.c_to) + +class asm_constraint_to(AsmConstraint): + + def __init__(self, label): + warnings.warn('DEPRECATION WARNING: use "AsmConstraintTo" instead of "asm_constraint_to"') + super(asm_constraint_to, self).__init__(label) + + +class AsmBlock(object): + + def __init__(self, label, alignment=1): + assert isinstance(label, AsmLabel) + self.bto = set() + self.lines = [] + self.label = label + self.alignment = alignment + + def __str__(self): + out = [] + out.append(str(self.label)) + for l in self.lines: + out.append(str(l)) + if self.bto: + lbls = ["->"] + for l in self.bto: + if l is None: + lbls.append("Unknown? ") + else: + lbls.append(str(l) + " ") + lbls = '\t'.join(lbls) + out.append(lbls) + return '\n'.join(out) + + def addline(self, l): + self.lines.append(l) + + def addto(self, c): + assert isinstance(self.bto, set) + self.bto.add(c) + + def split(self, offset, l): + log_asmblock.debug('split at %x', offset) + i = -1 + offsets = [x.offset for x in self.lines] + if not l.offset in offsets: + log_asmblock.warning( + 'cannot split bloc at %X ' % offset + + 'middle instruction? default middle') + offsets.sort() + return None + new_bloc = AsmBlock(l) + i = offsets.index(offset) + + self.lines, new_bloc.lines = self.lines[:i], self.lines[i:] + flow_mod_instr = self.get_flow_instr() + log_asmblock.debug('flow mod %r', flow_mod_instr) + c = AsmConstraint(l, AsmConstraint.c_next) + # move dst if flowgraph modifier was in original bloc + # (usecase: split delayslot bloc) + if flow_mod_instr: + for xx in self.bto: + log_asmblock.debug('lbl %s', xx) + c_next = set( + [x for x in self.bto if x.c_t == AsmConstraint.c_next]) + c_to = [x for x in self.bto if x.c_t != AsmConstraint.c_next] + self.bto = set([c] + c_to) + new_bloc.bto = c_next + else: + new_bloc.bto = self.bto + self.bto = set([c]) + return new_bloc + + def get_range(self): + """Returns the offset hull of an AsmBlock""" + if len(self.lines): + return (self.lines[0].offset, + self.lines[-1].offset + self.lines[-1].l) + else: + return 0, 0 + + def get_offsets(self): + return [x.offset for x in self.lines] + + def add_cst(self, offset, c_t, symbol_pool): + if isinstance(offset, (int, long)): + l = symbol_pool.getby_offset_create(offset) + elif isinstance(offset, str): + l = symbol_pool.getby_name_create(offset) + elif isinstance(offset, AsmLabel): + l = offset + else: + raise ValueError('unknown offset type %r' % offset) + c = AsmConstraint(l, c_t) + self.bto.add(c) + + def get_flow_instr(self): + if not self.lines: + return None + for i in xrange(-1, -1 - self.lines[0].delayslot - 1, -1): + if not 0 <= i < len(self.lines): + return None + l = self.lines[i] + if l.splitflow() or l.breakflow(): + raise NotImplementedError('not fully functional') + + def get_subcall_instr(self): + if not self.lines: + return None + delayslot = self.lines[0].delayslot + end_index = len(self.lines) - 1 + ds_max_index = max(end_index - delayslot, 0) + for i in xrange(end_index, ds_max_index - 1, -1): + l = self.lines[i] + if l.is_subcall(): + return l + return None + + def get_next(self): + for x in self.bto: + if x.c_t == AsmConstraint.c_next: + return x.label + return None + + @staticmethod + def _filter_constraint(constraints): + """Sort and filter @constraints for AsmBlock.bto + @constraints: non-empty set of AsmConstraint instance + + Always the same type -> one of the constraint + c_next and c_to -> c_next + """ + # Only one constraint + if len(constraints) == 1: + return next(iter(constraints)) + + # Constraint type -> set of corresponding constraint + cbytype = {} + for cons in constraints: + cbytype.setdefault(cons.c_t, set()).add(cons) + + # Only one type -> any constraint is OK + if len(cbytype) == 1: + return next(iter(constraints)) + + # At least 2 types -> types = {c_next, c_to} + # c_to is included in c_next + return next(iter(cbytype[AsmConstraint.c_next])) + + def fix_constraints(self): + """Fix next block constraints""" + # destination -> associated constraints + dests = {} + for constraint in self.bto: + dests.setdefault(constraint.label, set()).add(constraint) + + self.bto = set(self._filter_constraint(constraints) + for constraints in dests.itervalues()) + + +class asm_bloc(object): + + def __init__(self, label, alignment=1): + warnings.warn('DEPRECATION WARNING: use "AsmBlock" instead of "asm_bloc"') + super(asm_bloc, self).__init__(label, alignment) + + +class AsmBlockBad(AsmBlock): + + """Stand for a *bad* ASM block (malformed, unreachable, + not disassembled, ...)""" + + ERROR_TYPES = {-1: "Unknown error", + 0: "Unable to disassemble", + 1: "Null starting block", + 2: "Address forbidden by dont_dis", + } + + def __init__(self, label=None, alignment=1, errno=-1, *args, **kwargs): + """Instanciate an AsmBlock_bad. + @label, @alignement: same as AsmBlock.__init__ + @errno: (optional) specify a error type associated with the block + """ + super(AsmBlockBad, self).__init__(label, alignment, *args, **kwargs) + self._errno = errno + + def __str__(self): + error_txt = self.ERROR_TYPES.get(self._errno, self._errno) + return "\n".join([str(self.label), + "\tBad block: %s" % error_txt]) + + def addline(self, *args, **kwargs): + raise RuntimeError("An AsmBlockBad cannot have line") + + def addto(self, *args, **kwargs): + raise RuntimeError("An AsmBlockBad cannot have bto") + + def split(self, *args, **kwargs): + raise RuntimeError("An AsmBlockBad cannot be splitted") + + +class asm_block_bad(AsmBlockBad): + + def __init__(self, label=None, alignment=1, errno=-1, *args, **kwargs): + warnings.warn('DEPRECATION WARNING: use "AsmBlockBad" instead of "asm_block_bad"') + super(asm_block_bad, self).__init__(label, alignment, *args, **kwargs) + + +class AsmSymbolPool(object): + + def __init__(self): + self._labels = [] + self._name2label = {} + self._offset2label = {} + self._label_num = 0 + + def add_label(self, name, offset=None): + """ + Create and add a label to the symbol_pool + @name: label's name + @offset: (optional) label's offset + """ + label = AsmLabel(name, offset) + + # Test for collisions + if (label.offset in self._offset2label and + label != self._offset2label[label.offset]): + raise ValueError('symbol %s has same offset as %s' % + (label, self._offset2label[label.offset])) + if (label.name in self._name2label and + label != self._name2label[label.name]): + raise ValueError('symbol %s has same name as %s' % + (label, self._name2label[label.name])) + + self._labels.append(label) + if label.offset is not None: + self._offset2label[label.offset] = label + if label.name != "": + self._name2label[label.name] = label + return label + + def remove_label(self, label): + """ + Delete a @label + """ + self._name2label.pop(label.name, None) + self._offset2label.pop(label.offset, None) + if label in self._labels: + self._labels.remove(label) + + def del_label_offset(self, label): + """Unpin the @label from its offset""" + self._offset2label.pop(label.offset, None) + label.offset = None + + def getby_offset(self, offset): + """Retrieve label using its @offset""" + return self._offset2label.get(offset, None) + + def getby_name(self, name): + """Retrieve label using its @name""" + return self._name2label.get(name, None) + + def getby_name_create(self, name): + """Get a label from its @name, create it if it doesn't exist""" + label = self.getby_name(name) + if label is None: + label = self.add_label(name) + return label + + def getby_offset_create(self, offset): + """Get a label from its @offset, create it if it doesn't exist""" + label = self.getby_offset(offset) + if label is None: + label = self.add_label(offset, offset) + return label + + def rename_label(self, label, newname): + """Rename the @label name to @newname""" + if newname in self._name2label: + raise ValueError('Symbol already known') + self._name2label.pop(label.name, None) + label.name = newname + self._name2label[label.name] = label + + def set_offset(self, label, offset): + """Pin the @label from at @offset + Note that there is a special case when the offset is a list + it happens when offsets are recomputed in resolve_symbol* + """ + if label is None: + raise ValueError('label should not be None') + if not label.name in self._name2label: + raise ValueError('label %s not in symbol pool' % label) + if offset is not None and offset in self._offset2label: + raise ValueError('Conflict in label %s' % label) + self._offset2label.pop(label.offset, None) + label.offset = offset + if is_int(label.offset): + self._offset2label[label.offset] = label + + @property + def items(self): + """Return all labels""" + return self._labels + + def __str__(self): + return reduce(lambda x, y: x + str(y) + '\n', self._labels, "") + + def __getitem__(self, item): + if item in self._name2label: + return self._name2label[item] + if item in self._offset2label: + return self._offset2label[item] + raise KeyError('unknown symbol %r' % item) + + def __contains__(self, item): + return item in self._name2label or item in self._offset2label + + def merge(self, symbol_pool): + """Merge with another @symbol_pool""" + self._labels += symbol_pool._labels + self._name2label.update(symbol_pool._name2label) + self._offset2label.update(symbol_pool._offset2label) + + def gen_label(self): + """Generate a new unpinned label""" + label = self.add_label("lbl_gen_%.8X" % (self._label_num)) + self._label_num += 1 + return label + + +class asm_symbol_pool(AsmSymbolPool): + + def __init__(self): + warnings.warn('DEPRECATION WARNING: use "AsmSymbolPool" instead of "asm_symbol_pool"') + super(asm_symbol_pool, self).__init__() + + +class AsmCFG(DiGraph): + + """Directed graph standing for a ASM Control Flow Graph with: + - nodes: AsmBlock + - edges: constraints between blocks, synchronized with AsmBlock's "bto" + + Specialized the .dot export and force the relation between block to be uniq, + and associated with a constraint. + + Offer helpers on AsmCFG management, such as research by label, sanity + checking and mnemonic size guessing. + """ + + # Internal structure for pending management + AsmCFGPending = namedtuple("AsmCFGPending", + ["waiter", "constraint"]) + + def __init__(self, *args, **kwargs): + super(AsmCFG, self).__init__(*args, **kwargs) + # Edges -> constraint + self.edges2constraint = {} + # Expected AsmLabel -> set( (src, dst), constraint ) + self._pendings = {} + # Label2block built on the fly + self._label2block = {} + + # Compatibility with old list API + def append(self, *args, **kwargs): + raise DeprecationWarning("AsmCFG is a graph, use add_node") + + def remove(self, *args, **kwargs): + raise DeprecationWarning("AsmCFG is a graph, use del_node") + + def __getitem__(self, *args, **kwargs): + raise DeprecationWarning("Order of AsmCFG elements is not reliable") + + def __iter__(self): + """Iterator on AsmBlock composing the current graph""" + return iter(self._nodes) + + def __len__(self): + """Return the number of blocks in AsmCFG""" + return len(self._nodes) + + # Manage graph with associated constraints + def add_edge(self, src, dst, constraint): + """Add an edge to the graph + @src: AsmBlock instance, source + @dst: AsmBlock instance, destination + @constraint: constraint associated to this edge + """ + # Sanity check + assert (src, dst) not in self.edges2constraint + + # Add the edge to src.bto if needed + if dst.label not in [cons.label for cons in src.bto]: + src.bto.add(AsmConstraint(dst.label, constraint)) + + # Add edge + self.edges2constraint[(src, dst)] = constraint + super(AsmCFG, self).add_edge(src, dst) + + def add_uniq_edge(self, src, dst, constraint): + """Add an edge from @src to @dst if it doesn't already exist""" + if (src not in self._nodes_succ or + dst not in self._nodes_succ[src]): + self.add_edge(src, dst, constraint) + + def del_edge(self, src, dst): + """Delete the edge @src->@dst and its associated constraint""" + # Delete from src.bto + to_remove = [cons for cons in src.bto if cons.label == dst.label] + if to_remove: + assert len(to_remove) == 1 + src.bto.remove(to_remove[0]) + + # Del edge + del self.edges2constraint[(src, dst)] + super(AsmCFG, self).del_edge(src, dst) + + def add_node(self, block): + """Add the block @block to the current instance, if it is not already in + @block: AsmBlock instance + + Edges will be created for @block.bto, if destinations are already in + this instance. If not, they will be resolved when adding these + aforementionned destinations. + `self.pendings` indicates which blocks are not yet resolved. + """ + status = super(AsmCFG, self).add_node(block) + if not status: + return status + + # Update waiters + if block.label in self._pendings: + for bblpend in self._pendings[block.label]: + self.add_edge(bblpend.waiter, block, bblpend.constraint) + del self._pendings[block.label] + + # Synchronize edges with block destinations + self._label2block[block.label] = block + for constraint in block.bto: + dst = self._label2block.get(constraint.label, + None) + if dst is None: + # Block is yet unknown, add it to pendings + to_add = self.AsmCFGPending(waiter=block, + constraint=constraint.c_t) + self._pendings.setdefault(constraint.label, + set()).add(to_add) + else: + # Block is already in known nodes + self.add_edge(block, dst, constraint.c_t) + + return status + + def del_node(self, block): + super(AsmCFG, self).del_node(block) + del self._label2block[block.label] + + def merge(self, graph): + """Merge with @graph, taking in account constraints""" + # -> add_edge(x, y, constraint) + for node in graph._nodes: + self.add_node(node) + for edge in graph._edges: + # Use "_uniq_" beacause the edge can already exist due to add_node + self.add_uniq_edge(*edge, constraint=graph.edges2constraint[edge]) + + def node2lines(self, node): + yield self.DotCellDescription(text=str(node.label.name), + attr={'align': 'center', + 'colspan': 2, + 'bgcolor': 'grey'}) + + if isinstance(node, AsmBlockBad): + yield [self.DotCellDescription( + text=node.ERROR_TYPES.get(node._errno, + node._errno), + attr={})] + raise StopIteration + for line in node.lines: + if self._dot_offset: + yield [self.DotCellDescription(text="%.8X" % line.offset, + attr={}), + self.DotCellDescription(text=str(line), attr={})] + else: + yield self.DotCellDescription(text=str(line), attr={}) + + def node_attr(self, node): + if isinstance(node, AsmBlockBad): + return {'style': 'filled', 'fillcolor': 'red'} + return {} + + def edge_attr(self, src, dst): + cst = self.edges2constraint.get((src, dst), None) + edge_color = "blue" + + if len(self.successors(src)) > 1: + if cst == AsmConstraint.c_next: + edge_color = "red" + else: + edge_color = "limegreen" + + return {"color": edge_color} + + def dot(self, offset=False): + """ + @offset: (optional) if set, add the corresponding offsets in each node + """ + self._dot_offset = offset + return super(AsmCFG, self).dot() + + # Helpers + @property + def pendings(self): + """Dictionary of label -> set(AsmCFGPending instance) indicating + which label are missing in the current instance. + A label is missing if a block which is already in nodes has constraints + with him (thanks to its .bto) and the corresponding block is not yet in + nodes + """ + return self._pendings + + def _build_label2block(self): + self._label2block = {block.label: block + for block in self._nodes} + + def label2block(self, label): + """Return the block corresponding to label @label + @label: AsmLabel instance or ExprId(AsmLabel) instance""" + return self._label2block[label] + + def rebuild_edges(self): + """Consider blocks '.bto' and rebuild edges according to them, ie: + - update constraint type + - add missing edge + - remove no more used edge + + This method should be called if a block's '.bto' in nodes have been + modified without notifying this instance to resynchronize edges. + """ + self._build_label2block() + for block in self._nodes: + edges = [] + # Rebuild edges from bto + for constraint in block.bto: + dst = self._label2block.get(constraint.label, + None) + if dst is None: + # Missing destination, add to pendings + self._pendings.setdefault(constraint.label, + set()).add(self.AsmCFGPending(block, + constraint.c_t)) + continue + edge = (block, dst) + edges.append(edge) + if edge in self._edges: + # Already known edge, constraint may have changed + self.edges2constraint[edge] = constraint.c_t + else: + # An edge is missing + self.add_edge(edge[0], edge[1], constraint.c_t) + + # Remove useless edges + for succ in self.successors(block): + edge = (block, succ) + if edge not in edges: + self.del_edge(*edge) + + def get_bad_blocks(self): + """Iterator on AsmBlockBad elements""" + # A bad asm block is always a leaf + for block in self.leaves(): + if isinstance(block, AsmBlockBad): + yield block + + def get_bad_blocks_predecessors(self, strict=False): + """Iterator on block with an AsmBlockBad destination + @strict: (optional) if set, return block with only bad + successors + """ + # Avoid returning the same block + done = set() + for badblock in self.get_bad_blocks(): + for predecessor in self.predecessors_iter(badblock): + if predecessor not in done: + if (strict and + not all(isinstance(block, AsmBlockBad) + for block in self.successors_iter(predecessor))): + continue + yield predecessor + done.add(predecessor) + + def sanity_check(self): + """Do sanity checks on blocks' constraints: + * no pendings + * no multiple next constraint to same block + * no next constraint to self + """ + + if len(self._pendings) != 0: + raise RuntimeError("Some blocks are missing: %s" % map(str, + self._pendings.keys())) + + next_edges = {edge: constraint + for edge, constraint in self.edges2constraint.iteritems() + if constraint == AsmConstraint.c_next} + + for block in self._nodes: + # No next constraint to self + if (block, block) in next_edges: + raise RuntimeError('Bad constraint: self in next') + + # No multiple next constraint to same block + pred_next = list(pblock + for (pblock, dblock) in next_edges + if dblock == block) + + if len(pred_next) > 1: + raise RuntimeError("Too many next constraints for bloc %r" + "(%s)" % (block.label, + map(lambda x: x.label, pred_next))) + + def guess_blocks_size(self, mnemo): + """Asm and compute max block size + Add a 'size' and 'max_size' attribute on each block + @mnemo: metamn instance""" + for block in self._nodes: + size = 0 + for instr in block.lines: + if isinstance(instr, AsmRaw): + # for special AsmRaw, only extract len + if isinstance(instr.raw, list): + data = None + if len(instr.raw) == 0: + l = 0 + else: + l = instr.raw[0].size / 8 * len(instr.raw) + elif isinstance(instr.raw, str): + data = instr.raw + l = len(data) + else: + raise NotImplementedError('asm raw') + else: + # Assemble the instruction to retrieve its len. + # If the instruction uses symbol it will fail + # In this case, the max_instruction_len is used + try: + candidates = mnemo.asm(instr) + l = len(candidates[-1]) + except: + l = mnemo.max_instruction_len + data = None + instr.data = data + instr.l = l + size += l + + block.size = size + block.max_size = size + log_asmblock.info("size: %d max: %d", block.size, block.max_size) + + def apply_splitting(self, symbol_pool, dis_block_callback=None, **kwargs): + """Consider @self' bto destinations and split block in @self if one of + these destinations jumps in the middle of this block. + In order to work, they must be only one block in @self per label in + @symbol_pool (which is true if @self come from the same disasmEngine). + + @symbol_pool: AsmSymbolPool instance associated with @self'labels + @dis_block_callback: (optional) if set, this callback will be called on + new block destinations + @kwargs: (optional) named arguments to pass to dis_block_callback + """ + # Get all possible destinations not yet resolved, with a resolved + # offset + block_dst = [label.offset + for label in self.pendings + if label.offset is not None] + + todo = self.nodes().copy() + rebuild_needed = False + + while todo: + # Find a block with a destination inside another one + cur_block = todo.pop() + range_start, range_stop = cur_block.get_range() + + for off in block_dst: + if not (off > range_start and off < range_stop): + continue + + # `cur_block` must be splitted at offset `off` + label = symbol_pool.getby_offset_create(off) + new_b = cur_block.split(off, label) + log_asmblock.debug("Split block %x", off) + if new_b is None: + log_asmblock.error("Cannot split %x!!", off) + continue + + # Remove pending from cur_block + # Links from new_b will be generated in rebuild_edges + for dst in new_b.bto: + if dst.label not in self.pendings: + continue + self.pendings[dst.label] = set(pending for pending in self.pendings[dst.label] + if pending.waiter != cur_block) + + # The new block destinations may need to be disassembled + if dis_block_callback: + offsets_to_dis = set(constraint.label.offset + for constraint in new_b.bto) + dis_block_callback(cur_bloc=new_b, + offsets_to_dis=offsets_to_dis, + symbol_pool=symbol_pool, **kwargs) + + # Update structure + rebuild_needed = True + self.add_node(new_b) + + # The new block must be considered + todo.add(new_b) + range_start, range_stop = cur_block.get_range() + + # Rebuild edges to match new blocks'bto + if rebuild_needed: + self.rebuild_edges() + + def __str__(self): + out = [] + for node in self.nodes(): + out.append(str(node)) + for nodeA, nodeB in self.edges(): + out.append("%s -> %s" % (nodeA.label, nodeB.label)) + return '\n'.join(out) + + def __repr__(self): + return "<%s %s>" % (self.__class__.__name__, hex(id(self))) + +# Out of _merge_blocks to be computed only once +_acceptable_block = lambda block: (not isinstance(block, AsmBlockBad) and + len(block.lines) > 0) +_parent = MatchGraphJoker(restrict_in=False, filt=_acceptable_block) +_son = MatchGraphJoker(restrict_out=False, filt=_acceptable_block) +_expgraph = _parent >> _son + + +def _merge_blocks(dg, graph): + """Graph simplification merging AsmBlock with one and only one son with this + son if this son has one and only one parent""" + + # Blocks to ignore, because they have been removed from the graph + to_ignore = set() + + for match in _expgraph.match(graph): + + # Get matching blocks + block, succ = match[_parent], match[_son] + + # Ignore already deleted blocks + if (block in to_ignore or + succ in to_ignore): + continue + + # Remove block last instruction if needed + last_instr = block.lines[-1] + if last_instr.delayslot > 0: + # TODO: delayslot + raise RuntimeError("Not implemented yet") + + if last_instr.is_subcall(): + continue + if last_instr.breakflow() and last_instr.dstflow(): + block.lines.pop() + + # Merge block + block.lines += succ.lines + for nextb in graph.successors_iter(succ): + graph.add_edge(block, nextb, graph.edges2constraint[(succ, nextb)]) + + graph.del_node(succ) + to_ignore.add(succ) + + +bbl_simplifier = DiGraphSimplifier() +bbl_simplifier.enable_passes([_merge_blocks]) + + +def conservative_asm(mnemo, instr, symbols, conservative): + """ + Asm instruction; + Try to keep original instruction bytes if it exists + """ + candidates = mnemo.asm(instr, symbols) + if not candidates: + raise ValueError('cannot asm:%s' % str(instr)) + if not hasattr(instr, "b"): + return candidates[0], candidates + if instr.b in candidates: + return instr.b, candidates + if conservative: + for c in candidates: + if len(c) == len(instr.b): + return c, candidates + return candidates[0], candidates + + +def fix_expr_val(expr, symbols): + """Resolve an expression @expr using @symbols""" + def expr_calc(e): + if isinstance(e, m2_expr.ExprId): + s = symbols._name2label[e.name] + e = m2_expr.ExprInt(s.offset, e.size) + return e + result = expr.visit(expr_calc) + result = expr_simp(result) + if not isinstance(result, m2_expr.ExprInt): + raise RuntimeError('Cannot resolve symbol %s' % expr) + return result + + +def fix_label_offset(symbol_pool, label, offset, modified): + """Fix the @label offset to @offset. If the @offset has changed, add @label + to @modified + @symbol_pool: current symbol_pool + """ + if label.offset == offset: + return + symbol_pool.set_offset(label, offset) + modified.add(label) + + +class BlockChain(object): + + """Manage blocks linked with an asm_constraint_next""" + + def __init__(self, symbol_pool, blocks): + self.symbol_pool = symbol_pool + self.blocks = blocks + self.place() + + @property + def pinned(self): + """Return True iff at least one block is pinned""" + return self.pinned_block_idx is not None + + def _set_pinned_block_idx(self): + self.pinned_block_idx = None + for i, block in enumerate(self.blocks): + if is_int(block.label.offset): + if self.pinned_block_idx is not None: + raise ValueError("Multiples pinned block detected") + self.pinned_block_idx = i + + def place(self): + """Compute BlockChain min_offset and max_offset using pinned block and + blocks' size + """ + self._set_pinned_block_idx() + self.max_size = 0 + for block in self.blocks: + self.max_size += block.max_size + block.alignment - 1 + + # Check if chain has one block pinned + if not self.pinned: + return + + offset_base = self.blocks[self.pinned_block_idx].label.offset + assert(offset_base % self.blocks[self.pinned_block_idx].alignment == 0) + + self.offset_min = offset_base + for block in self.blocks[:self.pinned_block_idx - 1:-1]: + self.offset_min -= block.max_size + \ + (block.alignment - block.max_size) % block.alignment + + self.offset_max = offset_base + for block in self.blocks[self.pinned_block_idx:]: + self.offset_max += block.max_size + \ + (block.alignment - block.max_size) % block.alignment + + def merge(self, chain): + """Best effort merge two block chains + Return the list of resulting blockchains""" + self.blocks += chain.blocks + self.place() + return [self] + + def fix_blocks(self, modified_labels): + """Propagate a pinned to its blocks' neighbour + @modified_labels: store new pinned labels""" + + if not self.pinned: + raise ValueError('Trying to fix unpinned block') + + # Propagate offset to blocks before pinned block + pinned_block = self.blocks[self.pinned_block_idx] + offset = pinned_block.label.offset + if offset % pinned_block.alignment != 0: + raise RuntimeError('Bad alignment') + + for block in self.blocks[:self.pinned_block_idx - 1:-1]: + new_offset = offset - block.size + new_offset = new_offset - new_offset % pinned_block.alignment + fix_label_offset(self.symbol_pool, + block.label, + new_offset, + modified_labels) + + # Propagate offset to blocks after pinned block + offset = pinned_block.label.offset + pinned_block.size + + last_block = pinned_block + for block in self.blocks[self.pinned_block_idx + 1:]: + offset += (- offset) % last_block.alignment + fix_label_offset(self.symbol_pool, + block.label, + offset, + modified_labels) + offset += block.size + last_block = block + return modified_labels + + +class BlockChainWedge(object): + + """Stand for wedges between blocks""" + + def __init__(self, symbol_pool, offset, size): + self.symbol_pool = symbol_pool + self.offset = offset + self.max_size = size + self.offset_min = offset + self.offset_max = offset + size + + def merge(self, chain): + """Best effort merge two block chains + Return the list of resulting blockchains""" + self.symbol_pool.set_offset(chain.blocks[0].label, self.offset_max) + chain.place() + return [self, chain] + + +def group_constrained_blocks(symbol_pool, blocks): + """ + Return the BlockChains list built from grouped asm blocks linked by + asm_constraint_next + @blocks: a list of asm block + """ + log_asmblock.info('group_constrained_blocks') + + # Group adjacent blocks + remaining_blocks = list(blocks) + known_block_chains = {} + lbl2block = {block.label: block for block in blocks} + + while remaining_blocks: + # Create a new block chain + block_list = [remaining_blocks.pop()] + + # Find sons in remainings blocks linked with a next constraint + while True: + # Get next block + next_label = block_list[-1].get_next() + if next_label is None or next_label not in lbl2block: + break + next_block = lbl2block[next_label] + + # Add the block at the end of the current chain + if next_block not in remaining_blocks: + break + block_list.append(next_block) + remaining_blocks.remove(next_block) + + # Check if son is in a known block group + if next_label is not None and next_label in known_block_chains: + block_list += known_block_chains[next_label] + del known_block_chains[next_label] + + known_block_chains[block_list[0].label] = block_list + + out_block_chains = [] + for label in known_block_chains: + chain = BlockChain(symbol_pool, known_block_chains[label]) + out_block_chains.append(chain) + return out_block_chains + + +def get_blockchains_address_interval(blockChains, dst_interval): + """Compute the interval used by the pinned @blockChains + Check if the placed chains are in the @dst_interval""" + + allocated_interval = interval() + for chain in blockChains: + if not chain.pinned: + continue + chain_interval = interval([(chain.offset_min, chain.offset_max - 1)]) + if chain_interval not in dst_interval: + raise ValueError('Chain placed out of destination interval') + allocated_interval += chain_interval + return allocated_interval + + +def resolve_symbol(blockChains, symbol_pool, dst_interval=None): + """Place @blockChains in the @dst_interval""" + + log_asmblock.info('resolve_symbol') + if dst_interval is None: + dst_interval = interval([(0, 0xFFFFFFFFFFFFFFFF)]) + + forbidden_interval = interval( + [(-1, 0xFFFFFFFFFFFFFFFF + 1)]) - dst_interval + allocated_interval = get_blockchains_address_interval(blockChains, + dst_interval) + log_asmblock.debug('allocated interval: %s', allocated_interval) + + pinned_chains = [chain for chain in blockChains if chain.pinned] + + # Add wedge in forbidden intervals + for start, stop in forbidden_interval.intervals: + wedge = BlockChainWedge( + symbol_pool, offset=start, size=stop + 1 - start) + pinned_chains.append(wedge) + + # Try to place bigger blockChains first + pinned_chains.sort(key=lambda x: x.offset_min) + blockChains.sort(key=lambda x: -x.max_size) + + fixed_chains = list(pinned_chains) + + log_asmblock.debug("place chains") + for chain in blockChains: + if chain.pinned: + continue + fixed = False + for i in xrange(1, len(fixed_chains)): + prev_chain = fixed_chains[i - 1] + next_chain = fixed_chains[i] + + if prev_chain.offset_max + chain.max_size < next_chain.offset_min: + new_chains = prev_chain.merge(chain) + fixed_chains[i - 1:i] = new_chains + fixed = True + break + if not fixed: + raise RuntimeError('Cannot find enough space to place blocks') + + return [chain for chain in fixed_chains if isinstance(chain, BlockChain)] + + +def filter_exprid_label(exprs): + """Extract labels from list of ExprId @exprs""" + return set(expr.name for expr in exprs if isinstance(expr.name, AsmLabel)) + + +def get_block_labels(block): + """Extract labels used by @block""" + symbols = set() + for instr in block.lines: + if isinstance(instr, AsmRaw): + if isinstance(instr.raw, list): + for expr in instr.raw: + symbols.update(m2_expr.get_expr_ids(expr)) + else: + for arg in instr.args: + symbols.update(m2_expr.get_expr_ids(arg)) + labels = filter_exprid_label(symbols) + return labels + + +def assemble_block(mnemo, block, symbol_pool, conservative=False): + """Assemble a @block using @symbol_pool + @conservative: (optional) use original bytes when possible + """ + offset_i = 0 + + for instr in block.lines: + if isinstance(instr, AsmRaw): + if isinstance(instr.raw, list): + # Fix special AsmRaw + data = "" + for expr in instr.raw: + expr_int = fix_expr_val(expr, symbol_pool) + data += pck[expr_int.size](expr_int.arg) + instr.data = data + + instr.offset = offset_i + offset_i += instr.l + continue + + # Assemble an instruction + saved_args = list(instr.args) + instr.offset = block.label.offset + offset_i + + # Replace instruction's arguments by resolved ones + instr.args = instr.resolve_args_with_symbols(symbol_pool) + + if instr.dstflow(): + instr.fixDstOffset() + + old_l = instr.l + cached_candidate, _ = conservative_asm(mnemo, instr, symbol_pool, + conservative) + + # Restore original arguments + instr.args = saved_args + + # We need to update the block size + block.size = block.size - old_l + len(cached_candidate) + instr.data = cached_candidate + instr.l = len(cached_candidate) + + offset_i += instr.l + + +def asmblock_final(mnemo, blocks, blockChains, symbol_pool, conservative=False): + """Resolve and assemble @blockChains using @symbol_pool until fixed point is + reached""" + + log_asmblock.debug("asmbloc_final") + + # Init structures + lbl2block = {block.label: block for block in blocks} + blocks_using_label = {} + for block in blocks: + labels = get_block_labels(block) + for label in labels: + blocks_using_label.setdefault(label, set()).add(block) + + block2chain = {} + for chain in blockChains: + for block in chain.blocks: + block2chain[block] = chain + + # Init worklist + blocks_to_rework = set(blocks) + + # Fix and re-assemble blocks until fixed point is reached + while True: + + # Propagate pinned blocks into chains + modified_labels = set() + for chain in blockChains: + chain.fix_blocks(modified_labels) + + for label in modified_labels: + # Retrive block with modified reference + if label in lbl2block: + blocks_to_rework.add(lbl2block[label]) + + # Enqueue blocks referencing a modified label + if label not in blocks_using_label: + continue + for block in blocks_using_label[label]: + blocks_to_rework.add(block) + + # No more work + if not blocks_to_rework: + break + + while blocks_to_rework: + block = blocks_to_rework.pop() + assemble_block(mnemo, block, symbol_pool, conservative) + + +def asmbloc_final(mnemo, blocks, blockChains, symbol_pool, conservative=False): + """Resolve and assemble @blockChains using @symbol_pool until fixed point is + reached""" + + warnings.warn('DEPRECATION WARNING: use "asmblock_final" instead of "asmbloc_final"') + asmblock_final(mnemo, blocks, blockChains, symbol_pool, conservative) + +def asm_resolve_final(mnemo, blocks, symbol_pool, dst_interval=None): + """Resolve and assemble @blocks using @symbol_pool into interval + @dst_interval""" + + blocks.sanity_check() + + blocks.guess_blocks_size(mnemo) + blockChains = group_constrained_blocks(symbol_pool, blocks) + resolved_blockChains = resolve_symbol( + blockChains, symbol_pool, dst_interval) + + asmblock_final(mnemo, blocks, resolved_blockChains, symbol_pool) + patches = {} + output_interval = interval() + + for block in blocks: + offset = block.label.offset + for instr in block.lines: + if not instr.data: + # Empty line + continue + assert len(instr.data) == instr.l + patches[offset] = instr.data + instruction_interval = interval([(offset, offset + instr.l - 1)]) + if not (instruction_interval & output_interval).empty: + raise RuntimeError("overlapping bytes %X" % int(offset)) + instr.offset = offset + offset += instr.l + return patches + + +class disasmEngine(object): + + """Disassembly engine, taking care of disassembler options and mutli-block + strategy. + + Engine options: + + + Object supporting membership test (offset in ..) + - dont_dis: stop the current disassembly branch if reached + - split_dis: force a basic block end if reached, + with a next constraint on its successor + - dont_dis_retcall_funcs: stop disassembly after a call to one + of the given functions + + + On/Off + - follow_call: recursively disassemble CALL destinations + - dontdis_retcall: stop on CALL return addresses + - dont_dis_nulstart_bloc: stop if a block begin with a few \x00 + + + Number + - lines_wd: maximum block's size (in number of instruction) + - blocs_wd: maximum number of distinct disassembled block + + + callback(arch, attrib, pool_bin, cur_bloc, offsets_to_dis, + symbol_pool) + - dis_bloc_callback: callback after each new disassembled block + + The engine also tracks already handled block, for performance and to avoid + infinite cycling. + Addresses of disassembled block is in the attribute `job_done`. + To force a new disassembly, the targeted offset must first be removed from + this structure. + """ + + def __init__(self, arch, attrib, bin_stream, **kwargs): + """Instanciate a new disassembly engine + @arch: targeted architecture + @attrib: architecture attribute + @bin_stream: bytes source + @kwargs: (optional) custom options + """ + self.arch = arch + self.attrib = attrib + self.bin_stream = bin_stream + self.symbol_pool = AsmSymbolPool() + self.job_done = set() + + # Setup options + self.dont_dis = [] + self.split_dis = [] + self.follow_call = False + self.dontdis_retcall = False + self.lines_wd = None + self.blocs_wd = None + self.dis_bloc_callback = None + self.dont_dis_nulstart_bloc = False + self.dont_dis_retcall_funcs = set() + + # Override options if needed + self.__dict__.update(kwargs) + + def _dis_bloc(self, offset): + """Disassemble the block at offset @offset + Return the created AsmBlock and future offsets to disassemble + """ + + lines_cpt = 0 + in_delayslot = False + delayslot_count = self.arch.delayslot + offsets_to_dis = set() + add_next_offset = False + label = self.symbol_pool.getby_offset_create(offset) + cur_block = AsmBlock(label) + log_asmblock.debug("dis at %X", int(offset)) + while not in_delayslot or delayslot_count > 0: + if in_delayslot: + delayslot_count -= 1 + + if offset in self.dont_dis: + if not cur_block.lines: + self.job_done.add(offset) + # Block is empty -> bad block + cur_block = AsmBlockBad(label, errno=2) + else: + # Block is not empty, stop the desassembly pass and add a + # constraint to the next block + cur_block.add_cst(offset, AsmConstraint.c_next, + self.symbol_pool) + break + + if lines_cpt > 0 and offset in self.split_dis: + cur_block.add_cst(offset, AsmConstraint.c_next, + self.symbol_pool) + offsets_to_dis.add(offset) + break + + lines_cpt += 1 + if self.lines_wd is not None and lines_cpt > self.lines_wd: + log_asmblock.debug("lines watchdog reached at %X", int(offset)) + break + + if offset in self.job_done: + cur_block.add_cst(offset, AsmConstraint.c_next, + self.symbol_pool) + break + + off_i = offset + try: + instr = self.arch.dis(self.bin_stream, self.attrib, offset) + except (Disasm_Exception, IOError), e: + log_asmblock.warning(e) + instr = None + + if instr is None: + log_asmblock.warning("cannot disasm at %X", int(off_i)) + if not cur_block.lines: + self.job_done.add(offset) + # Block is empty -> bad block + cur_block = AsmBlockBad(label, errno=0) + else: + # Block is not empty, stop the desassembly pass and add a + # constraint to the next block + cur_block.add_cst(off_i, AsmConstraint.c_next, + self.symbol_pool) + break + + # XXX TODO nul start block option + if self.dont_dis_nulstart_bloc and instr.b.count('\x00') == instr.l: + log_asmblock.warning("reach nul instr at %X", int(off_i)) + if not cur_block.lines: + # Block is empty -> bad block + cur_block = AsmBlockBad(label, errno=1) + else: + # Block is not empty, stop the desassembly pass and add a + # constraint to the next block + cur_block.add_cst(off_i, AsmConstraint.c_next, + self.symbol_pool) + break + + # special case: flow graph modificator in delayslot + if in_delayslot and instr and (instr.splitflow() or instr.breakflow()): + add_next_offset = True + break + + self.job_done.add(offset) + log_asmblock.debug("dis at %X", int(offset)) + + offset += instr.l + log_asmblock.debug(instr) + log_asmblock.debug(instr.args) + + cur_block.addline(instr) + if not instr.breakflow(): + continue + # test split + if instr.splitflow() and not (instr.is_subcall() and self.dontdis_retcall): + add_next_offset = True + pass + if instr.dstflow(): + instr.dstflow2label(self.symbol_pool) + dst = instr.getdstflow(self.symbol_pool) + dstn = [] + for d in dst: + if isinstance(d, m2_expr.ExprId) and \ + isinstance(d.name, AsmLabel): + dstn.append(d.name) + if d.name.offset in self.dont_dis_retcall_funcs: + add_next_offset = False + dst = dstn + if (not instr.is_subcall()) or self.follow_call: + cur_block.bto.update( + [AsmConstraint(x, AsmConstraint.c_to) for x in dst]) + + # get in delayslot mode + in_delayslot = True + delayslot_count = instr.delayslot + + for c in cur_block.bto: + offsets_to_dis.add(c.label.offset) + + if add_next_offset: + cur_block.add_cst(offset, AsmConstraint.c_next, self.symbol_pool) + offsets_to_dis.add(offset) + + # Fix multiple constraints + cur_block.fix_constraints() + + if self.dis_bloc_callback is not None: + self.dis_bloc_callback(mn=self.arch, attrib=self.attrib, + pool_bin=self.bin_stream, cur_bloc=cur_block, + offsets_to_dis=offsets_to_dis, + symbol_pool=self.symbol_pool) + return cur_block, offsets_to_dis + + def dis_bloc(self, offset): + """Disassemble the block at offset @offset and return the created + AsmBlock + @offset: targeted offset to disassemble + """ + current_block, _ = self._dis_bloc(offset) + return current_block + + def dis_multibloc(self, offset, blocs=None): + """Disassemble every block reachable from @offset regarding + specific disasmEngine conditions + Return an AsmCFG instance containing disassembled blocks + @offset: starting offset + @blocs: (optional) AsmCFG instance of already disassembled blocks to + merge with + """ + log_asmblock.info("dis bloc all") + if blocs is None: + blocs = AsmCFG() + todo = [offset] + + bloc_cpt = 0 + while len(todo): + bloc_cpt += 1 + if self.blocs_wd is not None and bloc_cpt > self.blocs_wd: + log_asmblock.debug("blocs watchdog reached at %X", int(offset)) + break + + target_offset = int(todo.pop(0)) + if (target_offset is None or + target_offset in self.job_done): + continue + cur_block, nexts = self._dis_bloc(target_offset) + todo += nexts + blocs.add_node(cur_block) + + blocs.apply_splitting(self.symbol_pool, + dis_block_callback=self.dis_bloc_callback, + mn=self.arch, attrib=self.attrib, + pool_bin=self.bin_stream) + return blocs diff --git a/miasm2/core/cpu.py b/miasm2/core/cpu.py index 1beeeff0..8b906027 100644 --- a/miasm2/core/cpu.py +++ b/miasm2/core/cpu.py @@ -8,7 +8,7 @@ from collections import defaultdict import pyparsing import miasm2.expression.expression as m2_expr -from miasm2.core import asmbloc +from miasm2.core import asmblock from miasm2.core.bin_stream import bin_stream, bin_stream_str from miasm2.core.utils import Disasm_Exception from miasm2.expression.simplifications import expr_simp @@ -232,7 +232,7 @@ class ParseAst(object): if size is None: size = self.default_size assert value is not None - return m2_expr.ExprId(asmbloc.asm_label(value), size) + return m2_expr.ExprId(asmblock.AsmLabel(value), size) def ast_to_expr(self, size, ast): """Transform a typed ast into a Miasm expression @@ -974,7 +974,7 @@ class instruction(object): ids = m2_expr.get_expr_ids(e) fixed_ids = {} for x in ids: - if isinstance(x.name, asmbloc.asm_label): + if isinstance(x.name, asmblock.AsmLabel): name = x.name.name # special symbol $ if name == '$': diff --git a/miasm2/core/parse_asm.py b/miasm2/core/parse_asm.py index 11fa4040..8ea0f6b1 100644 --- a/miasm2/core/parse_asm.py +++ b/miasm2/core/parse_asm.py @@ -2,7 +2,7 @@ import re import miasm2.expression.expression as m2_expr -import miasm2.core.asmbloc as asmbloc +import miasm2.core.asmblock as asmblock from miasm2.core.cpu import gen_base_expr, ParseAst from miasm2.core.cpu import instruction @@ -61,7 +61,7 @@ class DirectiveDontSplit(Directive): def guess_next_new_label(symbol_pool): """Generate a new label - @symbol_pool: the asm_symbol_pool instance""" + @symbol_pool: the AsmSymbolPool instance""" i = 0 gen_name = "loc_%.8X" while True: @@ -73,11 +73,11 @@ def guess_next_new_label(symbol_pool): def replace_expr_labels(expr, symbol_pool, replace_id): - """Create asm_label of the expression @expr in the @symbol_pool + """Create AsmLabel of the expression @expr in the @symbol_pool Update @replace_id""" if not (isinstance(expr, m2_expr.ExprId) and - isinstance(expr.name, asmbloc.asm_label)): + isinstance(expr.name, asmblock.AsmLabel)): return expr old_lbl = expr.name @@ -103,21 +103,21 @@ STATE_IN_BLOC = 1 def parse_txt(mnemo, attrib, txt, symbol_pool=None): """Parse an assembly listing. Returns a couple (blocks, symbol_pool), where - blocks is a list of asm_bloc and symbol_pool the associated asm_symbol_pool + blocks is a list of asm_bloc and symbol_pool the associated AsmSymbolPool @mnemo: architecture used @attrib: architecture attribute @txt: assembly listing - @symbol_pool: (optional) the asm_symbol_pool instance used to handle labels + @symbol_pool: (optional) the AsmSymbolPool instance used to handle labels of the listing """ if symbol_pool is None: - symbol_pool = asmbloc.asm_symbol_pool() + symbol_pool = asmblock.AsmSymbolPool() - C_NEXT = asmbloc.asm_constraint.c_next - C_TO = asmbloc.asm_constraint.c_to + C_NEXT = asmblock.AsmConstraint.c_next + C_TO = asmblock.AsmConstraint.c_to lines = [] # parse each line @@ -151,7 +151,7 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None): raw = raw.decode('string_escape') if directive == 'string': raw += "\x00" - lines.append(asmbloc.asm_raw(raw)) + lines.append(asmblock.AsmRaw(raw)) continue if directive == 'ustring': # XXX HACK @@ -159,7 +159,7 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None): raw = line[line.find(r'"') + 1:line.rfind(r'"')] + "\x00" raw = raw.decode('string_escape') raw = "".join([string + '\x00' for string in raw]) - lines.append(asmbloc.asm_raw(raw)) + lines.append(asmblock.AsmRaw(raw)) continue if directive in declarator: data_raw = line[match_re.end():].split(' ', 1)[1] @@ -179,7 +179,7 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None): element_expr = base_expr.parseString(element)[0] expr_list.append(element_expr.canonize()) - raw_data = asmbloc.asm_raw(expr_list) + raw_data = asmblock.AsmRaw(expr_list) raw_data.element_size = size lines.append(raw_data) continue @@ -218,20 +218,20 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None): line = line.strip(' ').strip('\t') instr = mnemo.fromstring(line, attrib) - # replace orphan asm_label with labels from symbol_pool + # replace orphan AsmLabel with labels from symbol_pool replace_orphan_labels(instr, symbol_pool) if instr.dstflow(): instr.dstflow2label(symbol_pool) lines.append(instr) - asmbloc.log_asmbloc.info("___pre asm oki___") + asmblock.log_asmblock.info("___pre asm oki___") # make blocks cur_block = None state = STATE_NO_BLOC i = 0 - blocks = asmbloc.AsmCFG() + blocks = asmblock.AsmCFG() block_to_nlink = None delayslot = 0 while i < len(lines): @@ -250,20 +250,20 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None): block_to_nlink = None i += 1 continue - elif not isinstance(line, asmbloc.asm_label): + elif not isinstance(line, asmblock.AsmLabel): # First line must be a label. If it's not the case, generate # it. label = guess_next_new_label(symbol_pool) - cur_block = asmbloc.asm_bloc(label, alignment=mnemo.alignment) + cur_block = asmblock.AsmBlock(label, alignment=mnemo.alignment) else: - cur_block = asmbloc.asm_bloc(line, alignment=mnemo.alignment) + cur_block = asmblock.AsmBlock(line, alignment=mnemo.alignment) i += 1 # Generate the current bloc blocks.add_node(cur_block) state = STATE_IN_BLOC if block_to_nlink: block_to_nlink.addto( - asmbloc.asm_constraint(cur_block.label, + asmblock.AsmConstraint(cur_block.label, C_NEXT)) block_to_nlink = None continue @@ -278,13 +278,13 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None): block_to_nlink = cur_block elif isinstance(line, DirectiveAlign): cur_block.alignment = line.alignment - elif isinstance(line, asmbloc.asm_raw): + elif isinstance(line, asmblock.AsmRaw): cur_block.addline(line) block_to_nlink = cur_block - elif isinstance(line, asmbloc.asm_label): + elif isinstance(line, asmblock.AsmLabel): if block_to_nlink: cur_block.addto( - asmbloc.asm_constraint(line, C_NEXT)) + asmblock.AsmConstraint(line, C_NEXT)) block_to_nlink = None state = STATE_NO_BLOC continue @@ -303,7 +303,7 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None): continue if dst in mnemo.regs.all_regs_ids: continue - cur_block.addto(asmbloc.asm_constraint(dst.name, C_TO)) + cur_block.addto(asmblock.AsmConstraint(dst.name, C_TO)) if not line.splitflow(): block_to_nlink = None @@ -318,5 +318,5 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None): block.fix_constraints() # Log block - asmbloc.log_asmbloc.info(block) + asmblock.log_asmblock.info(block) return blocks, symbol_pool diff --git a/miasm2/core/sembuilder.py b/miasm2/core/sembuilder.py index 6ff390bb..f101d94c 100644 --- a/miasm2/core/sembuilder.py +++ b/miasm2/core/sembuilder.py @@ -5,7 +5,7 @@ import ast import re import miasm2.expression.expression as m2_expr -from miasm2.ir.ir import irbloc +from miasm2.ir.ir import IRBlock class MiasmTransformer(ast.NodeTransformer): @@ -125,7 +125,7 @@ class SemBuilder(object): # Init self.transformer = MiasmTransformer() self._ctx = dict(m2_expr.__dict__) - self._ctx["irbloc"] = irbloc + self._ctx["IRBlock"] = IRBlock self._functions = {} # Update context @@ -250,12 +250,12 @@ class SemBuilder(object): sub_blocks[-1] = ast.List(elts=sub_blocks[-1], ctx=ast.Load()) - ## Replace the block with a call to 'irbloc' + ## Replace the block with a call to 'IRBlock' lbl_if_name = ast.Attribute(value=ast.Name(id=lbl_name, ctx=ast.Load()), attr='name', ctx=ast.Load()) - sub_blocks[-1] = ast.Call(func=ast.Name(id='irbloc', + sub_blocks[-1] = ast.Call(func=ast.Name(id='IRBlock', ctx=ast.Load()), args=[lbl_if_name, sub_blocks[-1]], diff --git a/miasm2/ir/analysis.py b/miasm2/ir/analysis.py index 73391bb2..4f7b321f 100644 --- a/miasm2/ir/analysis.py +++ b/miasm2/ir/analysis.py @@ -2,8 +2,8 @@ import logging -from miasm2.ir.symbexec import symbexec -from miasm2.ir.ir import ir, AssignBlock +from miasm2.ir.symbexec import SymbolicExecutionEngine +from miasm2.ir.ir import IntermediateRepresentation, AssignBlock from miasm2.expression.expression \ import ExprAff, ExprCond, ExprId, ExprInt, ExprMem, ExprOp @@ -14,14 +14,17 @@ log.addHandler(console_handler) log.setLevel(logging.WARNING) -class ira(ir): +class ira(IntermediateRepresentation): """IR Analysis This class provides higher level manipulations on IR, such as dead instruction removals. - This class can be used as a common parent with `miasm2.ir.ir::ir` class. + This class can be used as a common parent with + `miasm2.ir.ir::IntermediateRepresentation` class. + For instance: class ira_x86_16(ir_x86_16, ira) + """ def ira_regs_ids(self): @@ -84,14 +87,14 @@ class ira(ir): useful = set() for node in self.graph.nodes(): - if node not in self.blocs: + if node not in self.blocks: continue - block = self.blocs[node] + block = self.blocks[node] successors = self.graph.successors(node) has_son = bool(successors) for p_son in successors: - if p_son not in self.blocs: + if p_son not in self.blocks: # Leaf has lost its son: don't remove anything # reaching this block for r in self.ira_regs_ids(): @@ -136,7 +139,7 @@ class ira(ir): useful.add(elem) irb_label, irs_ind, dst = elem - assignblk = self.blocs[irb_label].irs[irs_ind] + assignblk = self.blocks[irb_label].irs[irs_ind] ins = assignblk.dst2ExprAff(dst) # Handle dependencies of used variables in ins @@ -161,10 +164,10 @@ class ira(ir): """ useful = self._mark_useful_code() modified = False - for block in self.blocs.values(): - modified |= self.remove_dead_instr(block, useful) + for irblock in self.blocks.values(): + modified |= self.remove_dead_instr(irblock, useful) # Remove useless structures - for assignblk in block.irs: + for assignblk in irblock.irs: del assignblk._cur_kill del assignblk._prev_kill del assignblk._cur_reach @@ -214,7 +217,7 @@ class ira(ir): # Compute reach from predecessors for n_pred in self.graph.predecessors(irb.label): - p_block = self.blocs[n_pred] + p_block = self.blocks[n_pred] # Handle each register definition for c_reg in self.ira_regs_ids(): @@ -253,8 +256,8 @@ class ira(ir): fixed = True for node in self.graph.nodes(): - if node in self.blocs: - irb = self.blocs[node] + if node in self.blocks: + irb = self.blocks[node] for assignblk in irb.irs: if (assignblk._cur_reach != assignblk._prev_reach or assignblk._cur_kill != assignblk._prev_kill): @@ -276,8 +279,8 @@ class ira(ir): log.debug('iteration...') while not fixed_point: for node in self.graph.nodes(): - if node in self.blocs: - self.compute_reach_block(self.blocs[node]) + if node in self.blocks: + self.compute_reach_block(self.blocks[node]) fixed_point = self._test_kill_reach_fix() def dead_simp(self): @@ -288,7 +291,7 @@ class ira(ir): Source : Kennedy, K. (1979). A survey of data flow analysis techniques. IBM Thomas J. Watson Research Division, page 43 """ - # Update r/w variables for all irblocs + # Update r/w variables for all irblocks self.get_rw(self.ira_regs_ids()) # Liveness step self.compute_reach() @@ -297,10 +300,10 @@ class ira(ir): self.simplify_blocs() def gen_equations(self): - for irb in self.blocs.values(): + for irb in self.blocks.values(): symbols_init = dict(self.arch.regs.all_regs_ids_init) - sb = symbexec(self, dict(symbols_init)) + sb = SymbolicExecutionEngine(self, dict(symbols_init)) sb.emulbloc(irb) eqs = [] for n_w in sb.symbols: diff --git a/miasm2/ir/ir.py b/miasm2/ir/ir.py index 0a7d68ce..5ebb51ec 100644 --- a/miasm2/ir/ir.py +++ b/miasm2/ir/ir.py @@ -17,13 +17,15 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # +import warnings + from itertools import chain import miasm2.expression.expression as m2_expr from miasm2.expression.expression_helper import get_missing_interval from miasm2.expression.simplifications import expr_simp -from miasm2.core.asmbloc import asm_symbol_pool, expr_is_label, asm_label, \ - asm_bloc +from miasm2.core.asmblock import AsmSymbolPool, expr_is_label, AsmLabel, \ + AsmBlock from miasm2.core.graph import DiGraph @@ -95,7 +97,7 @@ class AssignBlock(dict): # Build the merging expression args = list(e_colision.union(remaining)) - args.sort(key=lambda x:x[1]) + args.sort(key=lambda x: x[1]) starts = [start for (_, start, _) in args] assert len(set(starts)) == len(starts) args = [expr for (expr, _, _) in args] @@ -108,7 +110,7 @@ class AssignBlock(dict): """Return an Expr list of extra expressions needed during the object instanciation""" if not isinstance(src, m2_expr.ExprCompose): - raise ValueError("Get mod slice not on expraff slice", str(self)) + raise ValueError("Get mod slice not on expraff slice", str(src)) modified_s = [] for index, arg in src.iter_args(): if not (isinstance(arg, m2_expr.ExprSlice) and @@ -160,10 +162,20 @@ class AssignBlock(dict): return m2_expr.ExprAff(dst, self[dst]) -class irbloc(object): +class IRBlock(object): + """Intermediate representation block object. + + Stand for an intermediate representation basic block. + """ def __init__(self, label, irs, lines=None): - assert(isinstance(label, asm_label)) + """ + @label: AsmLabel of the IR basic block + @irs: list of AssignBlock + @lines: list of native instructions + """ + + assert isinstance(label, AsmLabel) if lines is None: lines = [] self.label = label @@ -196,7 +208,7 @@ class irbloc(object): assignblk = self.irs[self._dst_linenb] for dst in assignblk: if isinstance(dst, m2_expr.ExprId) and dst.name == "IRDst": - del(assignblk[dst]) + del assignblk[dst] assignblk[dst] = value # Sanity check is already done in _get_dst break @@ -240,6 +252,17 @@ class irbloc(object): return "\n".join(out) +class irbloc(IRBlock): + """ + DEPRECATED object + Use IRBlock instead of irbloc + """ + + def __init__(self, label, irs, lines=None): + warnings.warn('DEPRECATION WARNING: use "IRBlock" instead of "irblock"') + super(irbloc, self).__init__(label, irs, lines) + + class DiGraphIR(DiGraph): """DiGraph for IR instances""" @@ -297,13 +320,18 @@ class DiGraphIR(DiGraph): return super(DiGraphIR, self).dot() -class ir(object): +class IntermediateRepresentation(object): + """ + Intermediate representation object + + Allow native assembly to intermediate representation traduction + """ def __init__(self, arch, attrib, symbol_pool=None): if symbol_pool is None: - symbol_pool = asm_symbol_pool() + symbol_pool = AsmSymbolPool() self.symbol_pool = symbol_pool - self.blocs = {} + self.blocks = {} self.pc = arch.getpc(attrib) self.sp = arch.getsp(attrib) self.arch = arch @@ -311,6 +339,11 @@ class ir(object): # Lazy structure self._graph = None + @property + def get_blocs(self): + warnings.warn('DEPRECATION WARNING: use ".blocks" instead of ".blocs"') + return self.blocks + def get_ir(self, instr): raise NotImplementedError("Abstract Method") @@ -326,13 +359,13 @@ class ir(object): @ad: an ExprId/ExprInt/label/int""" if (isinstance(ad, m2_expr.ExprId) and - isinstance(ad.name, asm_label)): + isinstance(ad.name, AsmLabel)): ad = ad.name if isinstance(ad, m2_expr.ExprInt): ad = int(ad) - if type(ad) in [int, long]: + if isinstance(ad, (int, long)): ad = self.symbol_pool.getby_offset_create(ad) - elif isinstance(ad, asm_label): + elif isinstance(ad, AsmLabel): ad = self.symbol_pool.getby_name_create(ad.name) return ad @@ -341,16 +374,16 @@ class ir(object): @ad: an ExprId/ExprInt/label/int""" label = self.get_label(ad) - return self.blocs.get(label, None) + return self.blocks.get(label, None) def add_instr(self, l, ad=0, gen_pc_updt=False): - b = asm_bloc(self.gen_label()) + b = AsmBlock(self.gen_label()) b.lines = [l] self.add_bloc(b, gen_pc_updt) def getby_offset(self, offset): out = set() - for irb in self.blocs.values(): + for irb in self.blocks.values(): for l in irb.lines: if l.offset <= offset < l.offset + l.l: out.add(irb) @@ -360,7 +393,7 @@ class ir(object): c.irs.append(AssignBlock([m2_expr.ExprAff(self.pc, m2_expr.ExprInt(l.offset, self.pc.size) - )])) + )])) c.lines.append(l) def pre_add_instr(self, block, instr, irb_cur, ir_blocks_all, gen_pc_updt): @@ -398,7 +431,7 @@ class ir(object): if irb_cur is None: return None - assignblk, ir_blocs_extra = self.instr2ir(instr) + assignblk, ir_blocks_extra = self.instr2ir(instr) if gen_pc_updt is not False: self.gen_pc_update(irb_cur, instr) @@ -406,14 +439,14 @@ class ir(object): irb_cur.irs.append(assignblk) irb_cur.lines.append(instr) - if ir_blocs_extra: - for b in ir_blocs_extra: - b.lines = [instr] * len(b.irs) - ir_blocks_all += ir_blocs_extra + if ir_blocks_extra: + for irblock in ir_blocks_extra: + irblock.lines = [instr] * len(irblock.irs) + ir_blocks_all += ir_blocks_extra irb_cur = None return irb_cur - def add_bloc(self, block, gen_pc_updt = False): + def add_bloc(self, block, gen_pc_updt=False): """ Add a native block to the current IR @block: native assembly block @@ -425,7 +458,7 @@ class ir(object): for instr in block.lines: if irb_cur is None: label = self.get_instr_label(instr) - irb_cur = irbloc(label, [], []) + irb_cur = IRBlock(label, [], []) ir_blocks_all.append(irb_cur) irb_cur = self.add_instr_to_irblock(block, instr, irb_cur, ir_blocks_all, gen_pc_updt) @@ -449,27 +482,26 @@ class ir(object): return ir return None - def set_empty_dst_to_next(self, bloc, ir_blocs): - for b in ir_blocs: - if b.dst is not None: + def set_empty_dst_to_next(self, block, ir_blocks): + for irblock in ir_blocks: + if irblock.dst is not None: continue - next_lbl = bloc.get_next() + next_lbl = block.get_next() if next_lbl is None: - dst = m2_expr.ExprId(self.get_next_label(bloc.lines[-1]), + dst = m2_expr.ExprId(self.get_next_label(block.lines[-1]), self.pc.size) else: dst = m2_expr.ExprId(next_lbl, self.pc.size) - b.irs.append(AssignBlock([m2_expr.ExprAff(self.IRDst, dst)])) - b.lines.append(b.lines[-1]) + irblock.irs.append(AssignBlock([m2_expr.ExprAff(self.IRDst, dst)])) + irblock.lines.append(irblock.lines[-1]) - def post_add_bloc(self, bloc, ir_blocs): - self.set_empty_dst_to_next(bloc, ir_blocs) + def post_add_bloc(self, block, ir_blocks): + self.set_empty_dst_to_next(block, ir_blocks) - for irb in ir_blocs: - self.irbloc_fix_regs_for_mode(irb, self.attrib) - - self.blocs[irb.label] = irb + for irblock in ir_blocks: + self.irbloc_fix_regs_for_mode(irblock, self.attrib) + self.blocks[irblock.label] = irblock # Forget graph if any self._graph = None @@ -490,8 +522,8 @@ class ir(object): return l def simplify_blocs(self): - for irb in self.blocs.values(): - for assignblk in irb.irs: + for irblock in self.blocks.values(): + for assignblk in irblock.irs: for dst, src in assignblk.items(): del assignblk[dst] assignblk[expr_simp(dst)] = expr_simp(src) @@ -509,8 +541,8 @@ class ir(object): """ if regs_ids is None: regs_ids = [] - for b in self.blocs.values(): - b.get_rw(regs_ids) + for irblock in self.blocks.values(): + irblock.get_rw(regs_ids) def _extract_dst(self, todo, done): """ @@ -522,7 +554,7 @@ class ir(object): dst = todo.pop() if expr_is_label(dst): done.add(dst) - elif isinstance(dst, m2_expr.ExprMem) or isinstance(dst, m2_expr.ExprInt): + elif isinstance(dst, (m2_expr.ExprMem, m2_expr.ExprInt)): done.add(dst) elif isinstance(dst, m2_expr.ExprCond): todo.add(dst.src1) @@ -561,8 +593,8 @@ class ir(object): """ Gen irbloc digraph """ - self._graph = DiGraphIR(self.blocs) - for lbl, b in self.blocs.iteritems(): + self._graph = DiGraphIR(self.blocks) + for lbl, b in self.blocks.iteritems(): self._graph.add_node(lbl) dst = self.dst_trackback(b) for d in dst: @@ -579,3 +611,15 @@ class ir(object): if self._graph is None: self._gen_graph() return self._graph + + + +class ir(IntermediateRepresentation): + """ + DEPRECATED object + Use IntermediateRepresentation instead of ir + """ + + def __init__(self, label, irs, lines=None): + warnings.warn('DEPRECATION WARNING: use "IntermediateRepresentation" instead of "ir"') + super(ir, self).__init__(label, irs, lines) diff --git a/miasm2/ir/symbexec.py b/miasm2/ir/symbexec.py index 8e04c45b..ab873cfd 100644 --- a/miasm2/ir/symbexec.py +++ b/miasm2/ir/symbexec.py @@ -1,13 +1,12 @@ +import warnings +import logging + import miasm2.expression.expression as m2_expr from miasm2.expression.modint import int32 from miasm2.expression.simplifications import expr_simp -from miasm2.core import asmbloc +from miasm2.core import asmblock from miasm2.ir.ir import AssignBlock from miasm2.core.interval import interval -from miasm2.core.utils import get_caller_name -import warnings - -import logging log = logging.getLogger("symbexec") @@ -17,7 +16,10 @@ log.addHandler(console_handler) log.setLevel(logging.INFO) -class symbols(object): +class SymbolsMngr(object): + """ + Store registers and memory symbolic values + """ def __init__(self, init=None): if init is None: @@ -81,13 +83,13 @@ class symbols(object): [x[0] for x in self.symbols_mem.values()]) def copy(self): - new_symbols = symbols() + new_symbols = SymbolsMngr() new_symbols.symbols_id = dict(self.symbols_id) new_symbols.symbols_mem = dict(self.symbols_mem) return new_symbols def inject_info(self, info): - new_symbols = symbols() + new_symbols = SymbolsMngr() for expr, value in self.items(): expr = expr_simp(expr.replace_expr(info)) value = expr_simp(value.replace_expr(info)) @@ -95,13 +97,17 @@ class symbols(object): return new_symbols -class symbexec(object): +class SymbolicExecutionEngine(object): + """ + Symbolic execution engine + Allow IR code emulation in symbolic domain + """ def __init__(self, ir_arch, known_symbols, func_read=None, func_write=None, sb_expr_simp=expr_simp): - self.symbols = symbols() + self.symbols = SymbolsMngr() for expr, value in known_symbols.items(): self.symbols[expr] = value self.func_read = func_read @@ -199,7 +205,7 @@ class symbexec(object): elif isinstance(expr, m2_expr.ExprInt): return expr elif isinstance(expr, m2_expr.ExprId): - if isinstance(expr.name, asmbloc.asm_label) and expr.name.offset is not None: + if isinstance(expr.name, asmblock.AsmLabel) and expr.name.offset is not None: ret = m2_expr.ExprInt(expr.name.offset, expr.size) else: ret = state.get(expr, expr) @@ -441,7 +447,7 @@ class symbexec(object): print '_' * 80 return self.eval_expr(self.ir_arch.IRDst) - def emul_ir_bloc(self, myir, addr, step=False): + def emul_ir_bloc(self, _, addr, step=False): warnings.warn('DEPRECATION WARNING: use "emul_ir_block(self, addr, step=False)" instead of emul_ir_bloc') return self.emul_ir_block(addr, step) @@ -451,7 +457,7 @@ class symbexec(object): addr = self.emulbloc(irblock, step=step) return addr - def emul_ir_blocs(self, myir, addr, lbl_stop=None, step=False): + def emul_ir_blocs(self, _, addr, lbl_stop=None, step=False): warnings.warn('DEPRECATION WARNING: use "emul_ir_blocks(self, addr, lbl_stop=None, step=False):" instead of emul_ir_blocs') return self.emul_ir_blocks(addr, lbl_stop, step) @@ -466,6 +472,11 @@ class symbexec(object): return addr def del_mem_above_stack(self, stack_ptr): + """ + Remove all stored memory values with following properties: + * pointer based on initial stack value + * pointer below current stack pointer + """ stack_ptr = self.eval_expr(stack_ptr) for mem_addr, (mem, _) in self.symbols.symbols_mem.items(): diff = self.expr_simp(mem_addr - stack_ptr) @@ -487,3 +498,19 @@ class symbexec(object): ret = self.eval_expr(expr) return ret + +class symbexec(SymbolicExecutionEngine): + """ + DEPRECATED object + Use SymbolicExecutionEngine instead of symbexec + """ + + def __init__(self, ir_arch, known_symbols, + func_read=None, + func_write=None, + sb_expr_simp=expr_simp): + warnings.warn("Deprecated API: use SymbolicExecutionEngine") + super(symbexec, self).__init__(ir_arch, known_symbols, + func_read, + func_write, + sb_expr_simp=expr_simp) diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py index c7913ea8..1dfdbb00 100644 --- a/miasm2/ir/translators/C.py +++ b/miasm2/ir/translators/C.py @@ -1,5 +1,5 @@ from miasm2.ir.translators.translator import Translator -from miasm2.core import asmbloc +from miasm2.core import asmblock from miasm2.expression.modint import size2mask @@ -23,7 +23,7 @@ class TranslatorC(Translator): def from_ExprId(self, expr): - if isinstance(expr.name, asmbloc.asm_label): + if isinstance(expr.name, asmblock.AsmLabel): return "0x%x" % expr.name.offset return str(expr) diff --git a/miasm2/ir/translators/smt2.py b/miasm2/ir/translators/smt2.py index 5d5fb26b..26ff9127 100644 --- a/miasm2/ir/translators/smt2.py +++ b/miasm2/ir/translators/smt2.py @@ -1,7 +1,7 @@ import logging import operator -from miasm2.core.asmbloc import asm_label +from miasm2.core.asmblock import AsmLabel from miasm2.ir.translators.translator import Translator from miasm2.expression.smt2_helper import * @@ -134,7 +134,7 @@ class TranslatorSMT2(Translator): return bit_vec_val(expr.arg.arg, expr.size) def from_ExprId(self, expr): - if isinstance(expr.name, asm_label): + if isinstance(expr.name, AsmLabel): if expr.name.offset is not None: return bit_vec_val(str(expr.name.offset), expr.size) else: diff --git a/miasm2/ir/translators/z3_ir.py b/miasm2/ir/translators/z3_ir.py index ccb14b4f..d8b550d9 100644 --- a/miasm2/ir/translators/z3_ir.py +++ b/miasm2/ir/translators/z3_ir.py @@ -3,7 +3,7 @@ import operator import z3 -from miasm2.core.asmbloc import asm_label +from miasm2.core.asmblock import AsmLabel from miasm2.ir.translators.translator import Translator log = logging.getLogger("translator_z3") @@ -121,7 +121,7 @@ class TranslatorZ3(Translator): return z3.BitVecVal(expr.arg.arg, expr.size) def from_ExprId(self, expr): - if isinstance(expr.name, asm_label) and expr.name.offset is not None: + if isinstance(expr.name, AsmLabel) and expr.name.offset is not None: return z3.BitVecVal(expr.name.offset, expr.size) else: return z3.BitVec(str(expr), expr.size) diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py index 2503e104..9d005451 100644 --- a/miasm2/jitter/codegen.py +++ b/miasm2/jitter/codegen.py @@ -1,7 +1,7 @@ import miasm2.expression.expression as m2_expr -from miasm2.ir.ir import irbloc +from miasm2.ir.ir import IRBlock from miasm2.ir.translators import Translator -from miasm2.core.asmbloc import expr_is_label, asm_block_bad, asm_label +from miasm2.core.asmblock import expr_is_label, AsmBlockBad, AsmLabel # Miasm to C translator translator = Translator.to_language("C") @@ -134,7 +134,7 @@ class CGen(object): instr.offset + instr.l, self.ir_arch.IRDst.size) - return irbloc(self.ir_arch.get_instr_label(instr), [assignblk]) + return IRBlock(self.ir_arch.get_instr_label(instr), [assignblk]) def block2assignblks(self, block): irblocks_list = [] @@ -324,11 +324,11 @@ class CGen(object): return out def gen_goto_code(self, attrib, instr_offsets, dst): - if isinstance(dst, asm_label) and dst.offset is None: + if isinstance(dst, AsmLabel) and dst.offset is None: # Generate goto for local labels return ['goto %s;' % dst.name] offset = None - if isinstance(dst, asm_label) and dst.offset is not None: + if isinstance(dst, AsmLabel) and dst.offset is not None: offset = dst.offset elif isinstance(dst, (int, long)): offset = dst @@ -545,7 +545,7 @@ class CGen(object): @log_regs: log registers """ - if isinstance(block, asm_block_bad): + if isinstance(block, AsmBlockBad): return self.gen_bad_block() irblocks_list = self.block2assignblks(block) diff --git a/miasm2/jitter/emulatedsymbexec.py b/miasm2/jitter/emulatedsymbexec.py index 9ece5ff5..d4a67fe8 100644 --- a/miasm2/jitter/emulatedsymbexec.py +++ b/miasm2/jitter/emulatedsymbexec.py @@ -1,8 +1,8 @@ import miasm2.expression.expression as m2_expr -from miasm2.ir.symbexec import symbexec +from miasm2.ir.symbexec import SymbolicExecutionEngine -class EmulatedSymbExec(symbexec): +class EmulatedSymbExec(SymbolicExecutionEngine): """Symbolic exec instance linked with a jitter""" cpuid = { diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py index 7e831280..0ccbfcd7 100644 --- a/miasm2/jitter/jitcore.py +++ b/miasm2/jitter/jitcore.py @@ -15,7 +15,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # -from miasm2.core import asmbloc +from miasm2.core import asmblock from miasm2.core.interval import interval from miasm2.core.utils import BoundedDict from miasm2.jitter.csts import * @@ -55,13 +55,13 @@ class JitCore(object): "max_exec_per_call": 0 # 0 means no limit } - self.mdis = asmbloc.disasmEngine(ir_arch.arch, ir_arch.attrib, bs, - lines_wd=self.options["jit_maxline"], - symbol_pool=ir_arch.symbol_pool, - follow_call=False, - dontdis_retcall=False, - split_dis=self.split_dis, - dis_bloc_callback=self.disasm_cb) + self.mdis = asmblock.disasmEngine(ir_arch.arch, ir_arch.attrib, bs, + lines_wd=self.options["jit_maxline"], + symbol_pool=ir_arch.symbol_pool, + follow_call=False, + dontdis_retcall=False, + split_dis=self.split_dis, + dis_bloc_callback=self.disasm_cb) def set_options(self, **kwargs): @@ -88,52 +88,52 @@ class JitCore(object): "Initialise the Jitter" raise NotImplementedError("Abstract class") - def get_bloc_min_max(self, cur_bloc): - "Update cur_bloc to set min/max address" + def get_bloc_min_max(self, cur_block): + "Update cur_block to set min/max address" - if cur_bloc.lines: - cur_bloc.ad_min = cur_bloc.lines[0].offset - cur_bloc.ad_max = cur_bloc.lines[-1].offset + cur_bloc.lines[-1].l + if cur_block.lines: + cur_block.ad_min = cur_block.lines[0].offset + cur_block.ad_max = cur_block.lines[-1].offset + cur_block.lines[-1].l else: # 1 byte block for unknown mnemonic - cur_bloc.ad_min = cur_bloc.label.offset - cur_bloc.ad_max = cur_bloc.label.offset+1 + cur_block.ad_min = cur_block.label.offset + cur_block.ad_max = cur_block.label.offset+1 - def add_bloc_to_mem_interval(self, vm, bloc): - "Update vm to include bloc addresses in its memory range" + def add_bloc_to_mem_interval(self, vm, block): + "Update vm to include block addresses in its memory range" - self.blocs_mem_interval += interval([(bloc.ad_min, bloc.ad_max - 1)]) + self.blocs_mem_interval += interval([(block.ad_min, block.ad_max - 1)]) vm.reset_code_bloc_pool() for a, b in self.blocs_mem_interval: vm.add_code_bloc(a, b + 1) - def jitirblocs(self, label, irblocs): - """JiT a group of irblocs. - @label: the label of the irblocs - @irblocs: a gorup of irblocs + def jitirblocs(self, label, irblocks): + """JiT a group of irblocks. + @label: the label of the irblocks + @irblocks: a gorup of irblocks """ raise NotImplementedError("Abstract class") - def add_bloc(self, b): - """Add a bloc to JiT and JiT it. - @b: the bloc to add + def add_bloc(self, block): + """Add a block to JiT and JiT it. + @block: asm_bloc to add """ - irblocs = self.ir_arch.add_bloc(b, gen_pc_updt = True) - b.irblocs = irblocs - self.jitirblocs(b.label, irblocs) + irblocks = self.ir_arch.add_bloc(block, gen_pc_updt = True) + block.blocks = irblocks + self.jitirblocs(block.label, irblocks) def disbloc(self, addr, vm): - """Disassemble a new bloc and JiT it - @addr: address of the block to disassemble (asm_label or int) + """Disassemble a new block and JiT it + @addr: address of the block to disassemble (AsmLabel or int) @vm: VmMngr instance """ - # Get the bloc - if isinstance(addr, asmbloc.asm_label): + # Get the block + if isinstance(addr, asmblock.AsmLabel): addr = addr.offset # Prepare disassembler @@ -143,30 +143,30 @@ class JitCore(object): # Disassemble it try: - cur_bloc = self.mdis.dis_bloc(addr) + cur_block = self.mdis.dis_bloc(addr) except IOError: # vm_exception_flag is set label = self.ir_arch.symbol_pool.getby_offset_create(addr) - cur_bloc = asmbloc.asm_block_bad(label) + cur_block = asmblock.AsmBlockBad(label) # Logging if self.log_newbloc: - print cur_bloc + print cur_block - # Update label -> bloc - self.lbl2bloc[cur_bloc.label] = cur_bloc + # Update label -> block + self.lbl2bloc[cur_block.label] = cur_block - # Store min/max bloc address needed in jit automod code - self.get_bloc_min_max(cur_bloc) + # Store min/max block address needed in jit automod code + self.get_bloc_min_max(cur_block) # JiT it - self.add_bloc(cur_bloc) + self.add_bloc(cur_block) # Update jitcode mem range - self.add_bloc_to_mem_interval(vm, cur_bloc) + self.add_bloc_to_mem_interval(vm, cur_block) def runbloc(self, cpu, lbl, breakpoints): - """Run the bloc starting at lbl. + """Run the block starting at lbl. @cpu: JitCpu instance @lbl: target label """ @@ -175,80 +175,79 @@ class JitCore(object): lbl = getattr(cpu, self.ir_arch.pc.name) if not lbl in self.lbl2jitbloc: - # Need to JiT the bloc + # Need to JiT the block self.disbloc(lbl, cpu.vmmngr) - # Run the bloc and update cpu/vmmngr state + # Run the block and update cpu/vmmngr state return self.exec_wrapper(lbl, cpu, self.lbl2jitbloc.data, breakpoints, self.options["max_exec_per_call"]) - def blocs2memrange(self, blocs): - """Return an interval instance standing for blocs addresses - @blocs: list of asm_bloc instances + def blocs2memrange(self, blocks): + """Return an interval instance standing for blocks addresses + @blocks: list of asm_bloc instances """ mem_range = interval() - for b in blocs: - mem_range += interval([(b.ad_min, b.ad_max - 1)]) + for block in blocks: + mem_range += interval([(block.ad_min, block.ad_max - 1)]) return mem_range def __updt_jitcode_mem_range(self, vm): - """Rebuild the VM blocs address memory range + """Rebuild the VM blocks address memory range @vm: VmMngr instance """ # Reset the current pool vm.reset_code_bloc_pool() - # Add blocs in the pool - for a, b in self.blocs_mem_interval: - vm.add_code_bloc(a, b + 1) + # Add blocks in the pool + for start, stop in self.blocs_mem_interval: + vm.add_code_bloc(start, stop + 1) def del_bloc_in_range(self, ad1, ad2): - """Find and remove jitted bloc in range [ad1, ad2]. - Return the list of bloc removed. + """Find and remove jitted block in range [ad1, ad2]. + Return the list of block removed. @ad1: First address @ad2: Last address """ - # Find concerned blocs - modified_blocs = set() - for b in self.lbl2bloc.values(): - if not b.lines: + # Find concerned blocks + modified_blocks = set() + for block in self.lbl2bloc.values(): + if not block.lines: continue - if b.ad_max <= ad1 or b.ad_min >= ad2: - # Bloc not modified + if block.ad_max <= ad1 or block.ad_min >= ad2: + # Block not modified pass else: - # Modified blocs - modified_blocs.add(b) + # Modified blocks + modified_blocks.add(block) # Generate interval to delete - del_interval = self.blocs2memrange(modified_blocs) + del_interval = self.blocs2memrange(modified_blocks) # Remove interval from monitored interval list self.blocs_mem_interval -= del_interval - # Remove modified blocs - for b in modified_blocs: + # Remove modified blocks + for block in modified_blocks: try: - for irbloc in b.irblocs: - - # Remove offset -> jitted bloc link - if irbloc.label.offset in self.lbl2jitbloc: - del(self.lbl2jitbloc[irbloc.label.offset]) + for irblock in block.blocks: + # Remove offset -> jitted block link + if irblock.label.offset in self.lbl2jitbloc: + del(self.lbl2jitbloc[irblock.label.offset]) except AttributeError: - # The bloc has never been translated in IR - if b.label.offset in self.lbl2jitbloc: - del(self.lbl2jitbloc[b.label.offset]) + # The block has never been translated in IR + if block.label.offset in self.lbl2jitbloc: + del(self.lbl2jitbloc[block.label.offset]) - # Remove label -> bloc link - del(self.lbl2bloc[b.label]) + # Remove label -> block link + del(self.lbl2bloc[block.label]) - return modified_blocs + return modified_blocks def updt_automod_code_range(self, vm, mem_range): """Remove jitted code in range @mem_range diff --git a/miasm2/jitter/jitcore_cc_base.py b/miasm2/jitter/jitcore_cc_base.py index 2c2d3d52..ae8a5dc2 100644 --- a/miasm2/jitter/jitcore_cc_base.py +++ b/miasm2/jitter/jitcore_cc_base.py @@ -88,14 +88,14 @@ class JitCore_Cc_Base(JitCore): def label2fname(self, label): """ Generate function name from @label - @label: asm_label instance + @label: AsmLabel instance """ return "block_%s" % label.name def gen_c_code(self, label, block): """ Return the C code corresponding to the @irblocks - @label: asm_label of the block to jit + @label: AsmLabel of the block to jit @irblocks: list of irblocks """ f_name = self.label2fname(label) @@ -113,7 +113,7 @@ class JitCore_Cc_Base(JitCore): def hash_block(self, block): """ Build a hash of the block @block - @block: asmbloc + @block: asmblock """ block_raw = "".join(line.b for line in block.lines) block_hash = md5("%X_%s_%s_%s" % (block.label.offset, diff --git a/miasm2/jitter/jitcore_llvm.py b/miasm2/jitter/jitcore_llvm.py index 8f58f1da..d082dd79 100644 --- a/miasm2/jitter/jitcore_llvm.py +++ b/miasm2/jitter/jitcore_llvm.py @@ -121,7 +121,7 @@ class JitCore_LLVM(jitcore.JitCore): def hash_block(self, block): """ Build a hash of the block @block - @block: asmbloc + @block: asmblock """ block_raw = "".join(line.b for line in block.lines) block_hash = md5("%X_%s_%s_%s" % (block.label.offset, diff --git a/miasm2/jitter/jitcore_python.py b/miasm2/jitter/jitcore_python.py index a8ecc3d6..cbd582ab 100644 --- a/miasm2/jitter/jitcore_python.py +++ b/miasm2/jitter/jitcore_python.py @@ -34,10 +34,10 @@ class JitCore_Python(jitcore.JitCore): "Preload symbols according to current architecture" self.symbexec.reset_regs() - def jitirblocs(self, label, irblocs): - """Create a python function corresponding to an irblocs' group. - @label: the label of the irblocs - @irblocs: a gorup of irblocs + def jitirblocs(self, label, irblocks): + """Create a python function corresponding to an irblocks' group. + @label: the label of the irblocks + @irblocks: a gorup of irblocks """ def myfunc(cpu): @@ -47,7 +47,7 @@ class JitCore_Python(jitcore.JitCore): # Get virtual memory handler vmmngr = cpu.vmmngr - # Keep current location in irblocs + # Keep current location in irblocks cur_label = label # Required to detect new instructions @@ -57,15 +57,15 @@ class JitCore_Python(jitcore.JitCore): exec_engine = self.symbexec expr_simp = exec_engine.expr_simp - # For each irbloc inside irblocs + # For each irbloc inside irblocks while True: # Get the current bloc - for irb in irblocs: + for irb in irblocks: if irb.label == cur_label: break else: - raise RuntimeError("Irblocs must end with returning an " + raise RuntimeError("Irblocks must end with returning an " "ExprInt instance") # Refresh CPU values according to @cpu instance diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py index eaeae89a..693dd224 100644 --- a/miasm2/jitter/jitload.py +++ b/miasm2/jitter/jitload.py @@ -242,7 +242,7 @@ class jitter: "Add common exceptions handlers" def exception_automod(jitter): - "Tell the JiT backend to update blocs modified" + "Tell the JiT backend to update blocks modified" self.jit.updt_automod_code(jitter.vm) self.vm.set_exception(0) diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index 527dc733..226a1b8e 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -16,7 +16,7 @@ from llvmlite import binding as llvm from llvmlite import ir as llvm_ir import miasm2.expression.expression as m2_expr import miasm2.jitter.csts as m2_csts -import miasm2.core.asmbloc as m2_asmbloc +import miasm2.core.asmblock as m2_asmblock from miasm2.jitter.codegen import CGen from miasm2.expression.expression_helper import possible_values @@ -508,9 +508,9 @@ class LLVMFunction(): @label: str or asmlabel instance""" if isinstance(label, str): return label - elif isinstance(label, m2_asmbloc.asm_label): + elif isinstance(label, m2_asmblock.AsmLabel): return "label_%s" % label.name - elif m2_asmbloc.expr_is_label(label): + elif m2_asmblock.expr_is_label(label): return "label_%s" % label.name.name else: raise ValueError("label must either be str or asmlabel") @@ -1038,7 +1038,7 @@ class LLVMFunction(): index = dst2case.get(value, i) to_eval = to_eval.replace_expr({value: m2_expr.ExprInt(index, value.size)}) dst2case[value] = index - if m2_asmbloc.expr_is_int_or_label(value): + if m2_asmblock.expr_is_int_or_label(value): case2dst[i] = value else: case2dst[i] = self.add_ir(value) @@ -1068,7 +1068,7 @@ class LLVMFunction(): dst = m2_expr.ExprId(self.llvm_context.ir_arch.symbol_pool.getby_offset_create(int(dst)), dst.size) - if m2_asmbloc.expr_is_label(dst): + if m2_asmblock.expr_is_label(dst): bbl = self.get_basic_bloc_by_label(dst) offset = dst.name.offset if bbl is not None: @@ -1276,7 +1276,7 @@ class LLVMFunction(): self.init_fc() self.local_vars_pointers["status"] = self.local_vars["status"] - if isinstance(asmblock, m2_asmbloc.asm_block_bad): + if isinstance(asmblock, m2_asmblock.AsmBlockBad): self.gen_bad_block(asmblock) return diff --git a/test/analysis/depgraph.py b/test/analysis/depgraph.py index 0b8d97b6..24095c7b 100644 --- a/test/analysis/depgraph.py +++ b/test/analysis/depgraph.py @@ -1,9 +1,9 @@ """Regression test module for DependencyGraph""" from miasm2.expression.expression import ExprId, ExprInt32, ExprAff, ExprCond, \ ExprInt -from miasm2.core.asmbloc import asm_label +from miasm2.core.asmblock import AsmLabel from miasm2.ir.analysis import ira -from miasm2.ir.ir import ir, irbloc, AssignBlock +from miasm2.ir.ir import IRBlock, AssignBlock from miasm2.core.graph import DiGraph from miasm2.analysis.depgraph import DependencyNode, DependencyGraph from itertools import count @@ -42,15 +42,15 @@ CST33 = ExprInt32(0x33) CST35 = ExprInt32(0x35) CST37 = ExprInt32(0x37) -LBL0 = asm_label("lbl0") -LBL1 = asm_label("lbl1") -LBL2 = asm_label("lbl2") -LBL3 = asm_label("lbl3") -LBL4 = asm_label("lbl4") -LBL5 = asm_label("lbl5") -LBL6 = asm_label("lbl6") +LBL0 = AsmLabel("lbl0") +LBL1 = AsmLabel("lbl1") +LBL2 = AsmLabel("lbl2") +LBL3 = AsmLabel("lbl3") +LBL4 = AsmLabel("lbl4") +LBL5 = AsmLabel("lbl5") +LBL6 = AsmLabel("lbl6") -def gen_irbloc(label, exprs_list): +def gen_irblock(label, exprs_list): """ Returns an IRBlock with empty lines. Used only for tests purpose """ @@ -62,7 +62,7 @@ def gen_irbloc(label, exprs_list): else: irs.append(AssignBlock(exprs)) - irbl = irbloc(label, irs, lines) + irbl = IRBlock(label, irs, lines) return irbl @@ -114,16 +114,16 @@ def bloc2graph(irgraph, label=False, lines=True): # Generate basic blocks out_blocks = [] for label in irgraph.graph.nodes(): - if isinstance(label, asm_label): + if isinstance(label, AsmLabel): label_name = label.name else: label_name = str(label) - if hasattr(irgraph, 'blocs'): - irblock = irgraph.blocs[label] + if hasattr(irgraph, 'blocks'): + irblock = irgraph.blocks[label] else: irblock = None - if isinstance(label, asm_label): + if isinstance(label, AsmLabel): out_block = '%s [\n' % label.name else: out_block = '%s [\n' % label @@ -154,11 +154,11 @@ def bloc2graph(irgraph, label=False, lines=True): out += out_blocks # Generate links for src, dst in irgraph.graph.edges(): - if isinstance(src, asm_label): + if isinstance(src, AsmLabel): src_name = src.name else: src_name = str(src) - if isinstance(dst, asm_label): + if isinstance(dst, AsmLabel): dst_name = dst.name else: dst_name = str(dst) @@ -232,122 +232,122 @@ DNC3 = DependencyNode(LBL1, C, 0) G1_IRA = IRATest() -G1_IRB0 = gen_irbloc(LBL0, [[ExprAff(C, CST1)]]) -G1_IRB1 = gen_irbloc(LBL1, [[ExprAff(B, C)]]) -G1_IRB2 = gen_irbloc(LBL2, [[ExprAff(A, B)]]) +G1_IRB0 = gen_irblock(LBL0, [[ExprAff(C, CST1)]]) +G1_IRB1 = gen_irblock(LBL1, [[ExprAff(B, C)]]) +G1_IRB2 = gen_irblock(LBL2, [[ExprAff(A, B)]]) G1_IRA.graph.add_uniq_edge(G1_IRB0.label, G1_IRB1.label) G1_IRA.graph.add_uniq_edge(G1_IRB1.label, G1_IRB2.label) -G1_IRA.blocs = dict([(irb.label, irb) for irb in [G1_IRB0, G1_IRB1, G1_IRB2]]) +G1_IRA.blocks = dict([(irb.label, irb) for irb in [G1_IRB0, G1_IRB1, G1_IRB2]]) # graph 2 G2_IRA = IRATest() -G2_IRB0 = gen_irbloc(LBL0, [[ExprAff(C, CST1)]]) -G2_IRB1 = gen_irbloc(LBL1, [[ExprAff(B, CST2)]]) -G2_IRB2 = gen_irbloc(LBL2, [[ExprAff(A, B + C)]]) +G2_IRB0 = gen_irblock(LBL0, [[ExprAff(C, CST1)]]) +G2_IRB1 = gen_irblock(LBL1, [[ExprAff(B, CST2)]]) +G2_IRB2 = gen_irblock(LBL2, [[ExprAff(A, B + C)]]) G2_IRA.graph.add_uniq_edge(G2_IRB0.label, G2_IRB1.label) G2_IRA.graph.add_uniq_edge(G2_IRB1.label, G2_IRB2.label) -G2_IRA.blocs = dict([(irb.label, irb) for irb in [G2_IRB0, G2_IRB1, G2_IRB2]]) +G2_IRA.blocks = dict([(irb.label, irb) for irb in [G2_IRB0, G2_IRB1, G2_IRB2]]) # graph 3 G3_IRA = IRATest() -G3_IRB0 = gen_irbloc(LBL0, [[ExprAff(C, CST1)]]) -G3_IRB1 = gen_irbloc(LBL1, [[ExprAff(B, CST2)]]) -G3_IRB2 = gen_irbloc(LBL2, [[ExprAff(B, CST3)]]) -G3_IRB3 = gen_irbloc(LBL3, [[ExprAff(A, B + C)]]) +G3_IRB0 = gen_irblock(LBL0, [[ExprAff(C, CST1)]]) +G3_IRB1 = gen_irblock(LBL1, [[ExprAff(B, CST2)]]) +G3_IRB2 = gen_irblock(LBL2, [[ExprAff(B, CST3)]]) +G3_IRB3 = gen_irblock(LBL3, [[ExprAff(A, B + C)]]) G3_IRA.graph.add_uniq_edge(G3_IRB0.label, G3_IRB1.label) G3_IRA.graph.add_uniq_edge(G3_IRB0.label, G3_IRB2.label) G3_IRA.graph.add_uniq_edge(G3_IRB1.label, G3_IRB3.label) G3_IRA.graph.add_uniq_edge(G3_IRB2.label, G3_IRB3.label) -G3_IRA.blocs = dict([(irb.label, irb) for irb in [G3_IRB0, G3_IRB1, - G3_IRB2, G3_IRB3]]) +G3_IRA.blocks = dict([(irb.label, irb) for irb in [G3_IRB0, G3_IRB1, + G3_IRB2, G3_IRB3]]) # graph 4 G4_IRA = IRATest() -G4_IRB0 = gen_irbloc(LBL0, [[ExprAff(C, CST1)]]) -G4_IRB1 = gen_irbloc(LBL1, [[ExprAff(C, C + CST2)], - [ExprAff(G4_IRA.IRDst, - ExprCond(C, ExprId(LBL2), - ExprId(LBL1)))]]) +G4_IRB0 = gen_irblock(LBL0, [[ExprAff(C, CST1)]]) +G4_IRB1 = gen_irblock(LBL1, [[ExprAff(C, C + CST2)], + [ExprAff(G4_IRA.IRDst, + ExprCond(C, ExprId(LBL2), + ExprId(LBL1)))]]) -G4_IRB2 = gen_irbloc(LBL2, [[ExprAff(A, B)]]) +G4_IRB2 = gen_irblock(LBL2, [[ExprAff(A, B)]]) G4_IRA.graph.add_uniq_edge(G4_IRB0.label, G4_IRB1.label) G4_IRA.graph.add_uniq_edge(G4_IRB1.label, G4_IRB2.label) G4_IRA.graph.add_uniq_edge(G4_IRB1.label, G4_IRB1.label) -G4_IRA.blocs = dict([(irb.label, irb) for irb in [G4_IRB0, G4_IRB1, G4_IRB2]]) +G4_IRA.blocks = dict([(irb.label, irb) for irb in [G4_IRB0, G4_IRB1, G4_IRB2]]) # graph 5 G5_IRA = IRATest() -G5_IRB0 = gen_irbloc(LBL0, [[ExprAff(B, CST1)]]) -G5_IRB1 = gen_irbloc(LBL1, [[ExprAff(B, B + CST2)], - [ExprAff(G5_IRA.IRDst, - ExprCond(B, ExprId(LBL2), - ExprId(LBL1)))]]) +G5_IRB0 = gen_irblock(LBL0, [[ExprAff(B, CST1)]]) +G5_IRB1 = gen_irblock(LBL1, [[ExprAff(B, B + CST2)], + [ExprAff(G5_IRA.IRDst, + ExprCond(B, ExprId(LBL2), + ExprId(LBL1)))]]) -G5_IRB2 = gen_irbloc(LBL2, [[ExprAff(A, B)]]) +G5_IRB2 = gen_irblock(LBL2, [[ExprAff(A, B)]]) G5_IRA.graph.add_uniq_edge(G5_IRB0.label, G5_IRB1.label) G5_IRA.graph.add_uniq_edge(G5_IRB1.label, G5_IRB2.label) G5_IRA.graph.add_uniq_edge(G5_IRB1.label, G5_IRB1.label) -G5_IRA.blocs = dict([(irb.label, irb) for irb in [G5_IRB0, G5_IRB1, G5_IRB2]]) +G5_IRA.blocks = dict([(irb.label, irb) for irb in [G5_IRB0, G5_IRB1, G5_IRB2]]) # graph 6 G6_IRA = IRATest() -G6_IRB0 = gen_irbloc(LBL0, [[ExprAff(B, CST1)]]) -G6_IRB1 = gen_irbloc(LBL1, [[ExprAff(A, B)]]) +G6_IRB0 = gen_irblock(LBL0, [[ExprAff(B, CST1)]]) +G6_IRB1 = gen_irblock(LBL1, [[ExprAff(A, B)]]) G6_IRA.graph.add_uniq_edge(G6_IRB0.label, G6_IRB1.label) G6_IRA.graph.add_uniq_edge(G6_IRB1.label, G6_IRB1.label) -G6_IRA.blocs = dict([(irb.label, irb) for irb in [G6_IRB0, G6_IRB1]]) +G6_IRA.blocks = dict([(irb.label, irb) for irb in [G6_IRB0, G6_IRB1]]) # graph 7 G7_IRA = IRATest() -G7_IRB0 = gen_irbloc(LBL0, [[ExprAff(C, CST1)]]) -G7_IRB1 = gen_irbloc(LBL1, [[ExprAff(B, C)], [ExprAff(A, B)]]) -G7_IRB2 = gen_irbloc(LBL2, [[ExprAff(D, A)]]) +G7_IRB0 = gen_irblock(LBL0, [[ExprAff(C, CST1)]]) +G7_IRB1 = gen_irblock(LBL1, [[ExprAff(B, C)], [ExprAff(A, B)]]) +G7_IRB2 = gen_irblock(LBL2, [[ExprAff(D, A)]]) G7_IRA.graph.add_uniq_edge(G7_IRB0.label, G7_IRB1.label) G7_IRA.graph.add_uniq_edge(G7_IRB1.label, G7_IRB1.label) G7_IRA.graph.add_uniq_edge(G7_IRB1.label, G7_IRB2.label) -G7_IRA.blocs = dict([(irb.label, irb) for irb in [G7_IRB0, G7_IRB1, G7_IRB2]]) +G7_IRA.blocks = dict([(irb.label, irb) for irb in [G7_IRB0, G7_IRB1, G7_IRB2]]) # graph 8 G8_IRA = IRATest() -G8_IRB0 = gen_irbloc(LBL0, [[ExprAff(C, CST1)]]) -G8_IRB1 = gen_irbloc(LBL1, [[ExprAff(B, C)], [ExprAff(C, D)]]) -G8_IRB2 = gen_irbloc(LBL2, [[ExprAff(A, B)]]) +G8_IRB0 = gen_irblock(LBL0, [[ExprAff(C, CST1)]]) +G8_IRB1 = gen_irblock(LBL1, [[ExprAff(B, C)], [ExprAff(C, D)]]) +G8_IRB2 = gen_irblock(LBL2, [[ExprAff(A, B)]]) G8_IRA.graph.add_uniq_edge(G8_IRB0.label, G8_IRB1.label) G8_IRA.graph.add_uniq_edge(G8_IRB1.label, G8_IRB1.label) G8_IRA.graph.add_uniq_edge(G8_IRB1.label, G8_IRB2.label) -G8_IRA.blocs = dict([(irb.label, irb) for irb in [G8_IRB0, G8_IRB1, G8_IRB2]]) +G8_IRA.blocks = dict([(irb.label, irb) for irb in [G8_IRB0, G8_IRB1, G8_IRB2]]) # graph 9 is graph 8 @@ -355,131 +355,131 @@ G8_IRA.blocs = dict([(irb.label, irb) for irb in [G8_IRB0, G8_IRB1, G8_IRB2]]) G10_IRA = IRATest() -G10_IRB1 = gen_irbloc(LBL1, [[ExprAff(B, B + CST2)]]) -G10_IRB2 = gen_irbloc(LBL2, [[ExprAff(A, B)]]) +G10_IRB1 = gen_irblock(LBL1, [[ExprAff(B, B + CST2)]]) +G10_IRB2 = gen_irblock(LBL2, [[ExprAff(A, B)]]) G10_IRA.graph.add_uniq_edge(G10_IRB1.label, G10_IRB2.label) G10_IRA.graph.add_uniq_edge(G10_IRB1.label, G10_IRB1.label) -G10_IRA.blocs = dict([(irb.label, irb) for irb in [G10_IRB1, G10_IRB2]]) +G10_IRA.blocks = dict([(irb.label, irb) for irb in [G10_IRB1, G10_IRB2]]) # graph 11 G11_IRA = IRATest() -G11_IRB0 = gen_irbloc(LBL0, [[ExprAff(A, CST1), - ExprAff(B, CST2)]]) -G11_IRB1 = gen_irbloc(LBL1, [[ExprAff(A, B), - ExprAff(B, A)]]) -G11_IRB2 = gen_irbloc(LBL2, [[ExprAff(A, A - B)]]) +G11_IRB0 = gen_irblock(LBL0, [[ExprAff(A, CST1), + ExprAff(B, CST2)]]) +G11_IRB1 = gen_irblock(LBL1, [[ExprAff(A, B), + ExprAff(B, A)]]) +G11_IRB2 = gen_irblock(LBL2, [[ExprAff(A, A - B)]]) G11_IRA.graph.add_uniq_edge(G11_IRB0.label, G11_IRB1.label) G11_IRA.graph.add_uniq_edge(G11_IRB1.label, G11_IRB2.label) -G11_IRA.blocs = dict([(irb.label, irb) - for irb in [G11_IRB0, G11_IRB1, G11_IRB2]]) +G11_IRA.blocks = dict([(irb.label, irb) + for irb in [G11_IRB0, G11_IRB1, G11_IRB2]]) # graph 12 G12_IRA = IRATest() -G12_IRB0 = gen_irbloc(LBL0, [[ExprAff(B, CST1)]]) -G12_IRB1 = gen_irbloc(LBL1, [[ExprAff(A, B)], [ExprAff(B, B + CST2)]]) -G12_IRB2 = gen_irbloc(LBL2, [[ExprAff(B, A)]]) +G12_IRB0 = gen_irblock(LBL0, [[ExprAff(B, CST1)]]) +G12_IRB1 = gen_irblock(LBL1, [[ExprAff(A, B)], [ExprAff(B, B + CST2)]]) +G12_IRB2 = gen_irblock(LBL2, [[ExprAff(B, A)]]) G12_IRA.graph.add_uniq_edge(G12_IRB0.label, G12_IRB1.label) G12_IRA.graph.add_uniq_edge(G12_IRB1.label, G12_IRB2.label) G12_IRA.graph.add_uniq_edge(G12_IRB1.label, G12_IRB1.label) -G12_IRA.blocs = dict([(irb.label, irb) for irb in [G12_IRB0, G12_IRB1, - G12_IRB2]]) +G12_IRA.blocks = dict([(irb.label, irb) for irb in [G12_IRB0, G12_IRB1, + G12_IRB2]]) # graph 13 G13_IRA = IRATest() -G13_IRB0 = gen_irbloc(LBL0, [[ExprAff(A, CST1)], - #[ExprAff(B, A)], - [ExprAff(G13_IRA.IRDst, - ExprId(LBL1))]]) -G13_IRB1 = gen_irbloc(LBL1, [[ExprAff(C, A)], - #[ExprAff(A, A + CST1)], - [ExprAff(G13_IRA.IRDst, - ExprCond(R, ExprId(LBL2), - ExprId(LBL1)))]]) +G13_IRB0 = gen_irblock(LBL0, [[ExprAff(A, CST1)], + #[ExprAff(B, A)], + [ExprAff(G13_IRA.IRDst, + ExprId(LBL1))]]) +G13_IRB1 = gen_irblock(LBL1, [[ExprAff(C, A)], + #[ExprAff(A, A + CST1)], + [ExprAff(G13_IRA.IRDst, + ExprCond(R, ExprId(LBL2), + ExprId(LBL1)))]]) -G13_IRB2 = gen_irbloc(LBL2, [[ExprAff(B, A + CST3)], [ExprAff(A, B + CST3)], - [ExprAff(G13_IRA.IRDst, - ExprId(LBL1))]]) +G13_IRB2 = gen_irblock(LBL2, [[ExprAff(B, A + CST3)], [ExprAff(A, B + CST3)], + [ExprAff(G13_IRA.IRDst, + ExprId(LBL1))]]) -G13_IRB3 = gen_irbloc(LBL3, [[ExprAff(R, C)]]) +G13_IRB3 = gen_irblock(LBL3, [[ExprAff(R, C)]]) G13_IRA.graph.add_uniq_edge(G13_IRB0.label, G13_IRB1.label) G13_IRA.graph.add_uniq_edge(G13_IRB1.label, G13_IRB2.label) G13_IRA.graph.add_uniq_edge(G13_IRB2.label, G13_IRB1.label) G13_IRA.graph.add_uniq_edge(G13_IRB1.label, G13_IRB3.label) -G13_IRA.blocs = dict([(irb.label, irb) for irb in [G13_IRB0, G13_IRB1, - G13_IRB2, G13_IRB3]]) +G13_IRA.blocks = dict([(irb.label, irb) for irb in [G13_IRB0, G13_IRB1, + G13_IRB2, G13_IRB3]]) # graph 14 G14_IRA = IRATest() -G14_IRB0 = gen_irbloc(LBL0, [[ExprAff(A, CST1)], - [ExprAff(G14_IRA.IRDst, - ExprId(LBL1))] +G14_IRB0 = gen_irblock(LBL0, [[ExprAff(A, CST1)], + [ExprAff(G14_IRA.IRDst, + ExprId(LBL1))] ]) -G14_IRB1 = gen_irbloc(LBL1, [[ExprAff(B, A)], - [ExprAff(G14_IRA.IRDst, - ExprCond(C, ExprId(LBL2), - ExprId(LBL3)))] +G14_IRB1 = gen_irblock(LBL1, [[ExprAff(B, A)], + [ExprAff(G14_IRA.IRDst, + ExprCond(C, ExprId(LBL2), + ExprId(LBL3)))] ]) -G14_IRB2 = gen_irbloc(LBL2, [[ExprAff(D, A)], - [ExprAff(A, D + CST1)], - [ExprAff(G14_IRA.IRDst, - ExprId(LBL1))] +G14_IRB2 = gen_irblock(LBL2, [[ExprAff(D, A)], + [ExprAff(A, D + CST1)], + [ExprAff(G14_IRA.IRDst, + ExprId(LBL1))] ]) -G14_IRB3 = gen_irbloc(LBL3, [[ExprAff(R, D + B)]]) +G14_IRB3 = gen_irblock(LBL3, [[ExprAff(R, D + B)]]) G14_IRA.graph.add_uniq_edge(G14_IRB0.label, G14_IRB1.label) G14_IRA.graph.add_uniq_edge(G14_IRB1.label, G14_IRB2.label) G14_IRA.graph.add_uniq_edge(G14_IRB2.label, G14_IRB1.label) G14_IRA.graph.add_uniq_edge(G14_IRB1.label, G14_IRB3.label) -G14_IRA.blocs = dict([(irb.label, irb) for irb in [G14_IRB0, G14_IRB1, - G14_IRB2, G14_IRB3]]) +G14_IRA.blocks = dict([(irb.label, irb) for irb in [G14_IRB0, G14_IRB1, + G14_IRB2, G14_IRB3]]) # graph 16 G15_IRA = IRATest() -G15_IRB0 = gen_irbloc(LBL0, [[ExprAff(A, CST1)]]) -G15_IRB1 = gen_irbloc(LBL1, [[ExprAff(D, A + B)], - [ExprAff(C, D)], - [ExprAff(B, C)]]) -G15_IRB2 = gen_irbloc(LBL2, [[ExprAff(R, B)]]) +G15_IRB0 = gen_irblock(LBL0, [[ExprAff(A, CST1)]]) +G15_IRB1 = gen_irblock(LBL1, [[ExprAff(D, A + B)], + [ExprAff(C, D)], + [ExprAff(B, C)]]) +G15_IRB2 = gen_irblock(LBL2, [[ExprAff(R, B)]]) G15_IRA.graph.add_uniq_edge(G15_IRB0.label, G15_IRB1.label) G15_IRA.graph.add_uniq_edge(G15_IRB1.label, G15_IRB2.label) G15_IRA.graph.add_uniq_edge(G15_IRB1.label, G15_IRB1.label) -G15_IRA.blocs = dict([(irb.label, irb) for irb in [G15_IRB0, G15_IRB1, - G15_IRB2]]) +G15_IRA.blocks = dict([(irb.label, irb) for irb in [G15_IRB0, G15_IRB1, + G15_IRB2]]) # graph 16 G16_IRA = IRATest() -G16_IRB0 = gen_irbloc(LBL0, [[ExprAff(A, CST1)]]) -G16_IRB1 = gen_irbloc(LBL1, [[ExprAff(R, D)]]) -G16_IRB2 = gen_irbloc(LBL2, [[ExprAff(D, A)]]) -G16_IRB3 = gen_irbloc(LBL3, [[ExprAff(R, D)]]) -G16_IRB4 = gen_irbloc(LBL4, [[ExprAff(R, A)]]) -G16_IRB5 = gen_irbloc(LBL5, [[ExprAff(R, A)]]) +G16_IRB0 = gen_irblock(LBL0, [[ExprAff(A, CST1)]]) +G16_IRB1 = gen_irblock(LBL1, [[ExprAff(R, D)]]) +G16_IRB2 = gen_irblock(LBL2, [[ExprAff(D, A)]]) +G16_IRB3 = gen_irblock(LBL3, [[ExprAff(R, D)]]) +G16_IRB4 = gen_irblock(LBL4, [[ExprAff(R, A)]]) +G16_IRB5 = gen_irblock(LBL5, [[ExprAff(R, A)]]) G16_IRA.graph.add_uniq_edge(G16_IRB0.label, G16_IRB1.label) G16_IRA.graph.add_uniq_edge(G16_IRB1.label, G16_IRB2.label) @@ -490,25 +490,25 @@ G16_IRA.graph.add_uniq_edge(G16_IRB1.label, G16_IRB4.label) G16_IRA.graph.add_uniq_edge(G16_IRB4.label, G16_IRB1.label) G16_IRA.graph.add_uniq_edge(G16_IRB1.label, G16_IRB5.label) -G16_IRA.blocs = dict([(irb.label, irb) for irb in [G16_IRB0, G16_IRB1, - G16_IRB2, G16_IRB3, - G16_IRB4, G16_IRB5]]) +G16_IRA.blocks = dict([(irb.label, irb) for irb in [G16_IRB0, G16_IRB1, + G16_IRB2, G16_IRB3, + G16_IRB4, G16_IRB5]]) # graph 17 G17_IRA = IRATest() -G17_IRB0 = gen_irbloc(LBL0, [[ExprAff(A, CST1), - ExprAff(D, CST2)]]) -G17_IRB1 = gen_irbloc(LBL1, [[ExprAff(A, D), - ExprAff(B, D)]]) -G17_IRB2 = gen_irbloc(LBL2, [[ExprAff(A, A - B)]]) +G17_IRB0 = gen_irblock(LBL0, [[ExprAff(A, CST1), + ExprAff(D, CST2)]]) +G17_IRB1 = gen_irblock(LBL1, [[ExprAff(A, D), + ExprAff(B, D)]]) +G17_IRB2 = gen_irblock(LBL2, [[ExprAff(A, A - B)]]) G17_IRA.graph.add_uniq_edge(G17_IRB0.label, G17_IRB1.label) G17_IRA.graph.add_uniq_edge(G17_IRB1.label, G17_IRB2.label) -G17_IRA.blocs = dict([(irb.label, irb) for irb in [G17_IRB0, G17_IRB1, - G17_IRB2]]) +G17_IRA.blocks = dict([(irb.label, irb) for irb in [G17_IRB0, G17_IRB1, + G17_IRB2]]) # Test graph 1 G1_TEST1_DN1 = DependencyNode( diff --git a/test/arch/aarch64/unit/asm_test.py b/test/arch/aarch64/unit/asm_test.py index 54ab476d..ddb8a08c 100644 --- a/test/arch/aarch64/unit/asm_test.py +++ b/test/arch/aarch64/unit/asm_test.py @@ -5,7 +5,7 @@ from miasm2.core.cpu import ParseAst from miasm2.arch.aarch64.arch import mn_aarch64, base_expr, variable from miasm2.core import parse_asm from miasm2.expression.expression import * -from miasm2.core import asmbloc +from miasm2.core import asmblock from elfesteem.strpatchwork import StrPatchwork from miasm2.analysis.machine import Machine from miasm2.jitter.csts import * @@ -28,12 +28,12 @@ class Asm_Test(object): def asm(self): - blocs, symbol_pool = parse_asm.parse_txt(mn_aarch64, 'l', self.TXT, - symbol_pool = self.myjit.ir_arch.symbol_pool) + blocks, symbol_pool = parse_asm.parse_txt(mn_aarch64, 'l', self.TXT, + symbol_pool = self.myjit.ir_arch.symbol_pool) # fix shellcode addr symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0) s = StrPatchwork() - patches = asmbloc.asm_resolve_final(mn_aarch64, blocs, symbol_pool) + patches = asmblock.asm_resolve_final(mn_aarch64, blocks, symbol_pool) for offset, raw in patches.items(): s[offset] = raw diff --git a/test/arch/arm/sem.py b/test/arch/arm/sem.py index 3695fd29..01c536cd 100755 --- a/test/arch/arm/sem.py +++ b/test/arch/arm/sem.py @@ -4,7 +4,7 @@ import unittest import logging -from miasm2.ir.symbexec import symbexec +from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.arch.arm.arch import mn_arm as mn from miasm2.arch.arm.sem import ir_arml as ir_arch from miasm2.arch.arm.regs import * @@ -23,7 +23,7 @@ def compute(asm, inputstate={}, debug=False): sympool = dict(regs_init) sympool.update({k: ExprInt(v, k.size) for k, v in inputstate.iteritems()}) interm = ir_arch() - symexec = symbexec(interm, sympool) + symexec = SymbolicExecutionEngine(interm, sympool) instr = mn.fromstring(asm, "l") code = mn.asm(instr)[0] instr = mn.dis(code, "l") diff --git a/test/arch/mips32/unit/asm_test.py b/test/arch/mips32/unit/asm_test.py index 4425bb65..9281f1b6 100644 --- a/test/arch/mips32/unit/asm_test.py +++ b/test/arch/mips32/unit/asm_test.py @@ -5,7 +5,7 @@ from miasm2.core.cpu import ParseAst from miasm2.arch.mips32.arch import mn_mips32, base_expr, variable from miasm2.core import parse_asm from miasm2.expression.expression import * -from miasm2.core import asmbloc +from miasm2.core import asmblock from elfesteem.strpatchwork import StrPatchwork from miasm2.analysis.machine import Machine from miasm2.jitter.csts import * @@ -28,12 +28,12 @@ class Asm_Test(object): self.check() def asm(self): - blocs, symbol_pool = parse_asm.parse_txt(mn_mips32, 'l', self.TXT, - symbol_pool=self.myjit.ir_arch.symbol_pool) + blocks, symbol_pool = parse_asm.parse_txt(mn_mips32, 'l', self.TXT, + symbol_pool=self.myjit.ir_arch.symbol_pool) # fix shellcode addr symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0) s = StrPatchwork() - patches = asmbloc.asm_resolve_final(mn_mips32, blocs, symbol_pool) + patches = asmblock.asm_resolve_final(mn_mips32, blocks, symbol_pool) for offset, raw in patches.items(): s[offset] = raw diff --git a/test/arch/msp430/sem.py b/test/arch/msp430/sem.py index 433055e0..4b5b0c7d 100755 --- a/test/arch/msp430/sem.py +++ b/test/arch/msp430/sem.py @@ -4,7 +4,7 @@ import unittest import logging -from miasm2.ir.symbexec import symbexec +from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.arch.msp430.arch import mn_msp430 as mn, mode_msp430 as mode from miasm2.arch.msp430.sem import ir_msp430 as ir_arch from miasm2.arch.msp430.regs import * @@ -21,7 +21,7 @@ def compute(asm, inputstate={}, debug=False): sympool = dict(regs_init) sympool.update({k: ExprInt(v, k.size) for k, v in inputstate.iteritems()}) interm = ir_arch() - symexec = symbexec(interm, sympool) + symexec = SymbolicExecutionEngine(interm, sympool) instr = mn.fromstring(asm, mode) code = mn.asm(instr)[0] instr = mn.dis(code, mode) diff --git a/test/arch/x86/sem.py b/test/arch/x86/sem.py index d2198847..7b6a20b7 100755 --- a/test/arch/x86/sem.py +++ b/test/arch/x86/sem.py @@ -7,13 +7,13 @@ import unittest import logging import copy -from miasm2.ir.symbexec import symbexec +from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.arch.x86.arch import mn_x86 as mn from miasm2.arch.x86.sem import ir_x86_32 as ir_32, ir_x86_64 as ir_64 from miasm2.arch.x86.regs import * from miasm2.expression.expression import * from miasm2.expression.simplifications import expr_simp -from miasm2.core import parse_asm, asmbloc +from miasm2.core import parse_asm, asmblock logging.getLogger('cpuhelper').setLevel(logging.ERROR) @@ -25,7 +25,7 @@ m64 = 64 def symb_exec(interm, inputstate, debug): sympool = dict(regs_init) sympool.update(inputstate) - symexec = symbexec(interm, sympool) + symexec = SymbolicExecutionEngine(interm, sympool) symexec.emul_ir_blocks(0) if debug: for k, v in symexec.symbols.items(): @@ -45,11 +45,11 @@ def compute(ir, mode, asm, inputstate={}, debug=False): def compute_txt(ir, mode, txt, inputstate={}, debug=False): - blocs, symbol_pool = parse_asm.parse_txt(mn, mode, txt) + blocks, symbol_pool = parse_asm.parse_txt(mn, mode, txt) symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0) - patches = asmbloc.asm_resolve_final(mn, blocs, symbol_pool) + patches = asmblock.asm_resolve_final(mn, blocks, symbol_pool) interm = ir(symbol_pool) - for bbl in blocs: + for bbl in blocks: interm.add_bloc(bbl) return symb_exec(interm, inputstate, debug) diff --git a/test/arch/x86/unit/asm_test.py b/test/arch/x86/unit/asm_test.py index 524791ce..aba47df1 100644 --- a/test/arch/x86/unit/asm_test.py +++ b/test/arch/x86/unit/asm_test.py @@ -5,7 +5,7 @@ from miasm2.core.cpu import ParseAst from miasm2.arch.x86.arch import mn_x86, base_expr, variable from miasm2.core import parse_asm from miasm2.expression.expression import * -from miasm2.core import asmbloc +from miasm2.core import asmblock from elfesteem.strpatchwork import StrPatchwork from miasm2.analysis.machine import Machine from miasm2.jitter.csts import * @@ -44,12 +44,12 @@ class Asm_Test(object): assert(self.myjit.pc == self.ret_addr) def asm(self): - blocs, symbol_pool = parse_asm.parse_txt(mn_x86, self.arch_attrib, self.TXT, - symbol_pool = self.myjit.ir_arch.symbol_pool) + blocks, symbol_pool = parse_asm.parse_txt(mn_x86, self.arch_attrib, self.TXT, + symbol_pool = self.myjit.ir_arch.symbol_pool) # fix shellcode addr symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0) s = StrPatchwork() - patches = asmbloc.asm_resolve_final(mn_x86, blocs, symbol_pool) + patches = asmblock.asm_resolve_final(mn_x86, blocks, symbol_pool) for offset, raw in patches.items(): s[offset] = raw diff --git a/test/core/asmbloc.py b/test/core/asmblock.py index 5fbdca3e..79bf47be 100644 --- a/test/core/asmbloc.py +++ b/test/core/asmblock.py @@ -2,8 +2,8 @@ from pdb import pm from miasm2.arch.x86.disasm import dis_x86_32 from miasm2.analysis.binary import Container -from miasm2.core.asmbloc import AsmCFG, asm_constraint, asm_bloc, \ - asm_label, asm_block_bad, asm_constraint_to, asm_constraint_next, \ +from miasm2.core.asmblock import AsmCFG, AsmConstraint, AsmBlock, \ + AsmLabel, AsmBlockBad, AsmConstraintTo, AsmConstraintNext, \ bbl_simplifier from miasm2.core.graph import DiGraphSimplifier, MatchGraphJoker from miasm2.expression.expression import ExprId @@ -60,10 +60,10 @@ assert last_block in blocks for pred in blocks.predecessors(last_block): blocks.del_edge(pred, last_block) ### Link first and last block -blocks.add_edge(first_block, last_block, asm_constraint.c_next) +blocks.add_edge(first_block, last_block, AsmConstraint.c_next) ### Only one link between two blocks try: - blocks.add_edge(first_block, last_block, asm_constraint.c_to) + blocks.add_edge(first_block, last_block, AsmConstraint.c_to) good = False except AssertionError: good = True @@ -71,7 +71,7 @@ assert good ### Check final state assert len(first_block.bto) == 1 -assert list(first_block.bto)[0].c_t == asm_constraint.c_next +assert list(first_block.bto)[0].c_t == AsmConstraint.c_next ## Simplify the obtained graph to keep only blocks which reach a block ## finnishing with RET @@ -98,7 +98,7 @@ open("graph2.dot", "w").write(blocks.dot()) # Test helper methods ## Label2block should always be updated assert blocks.label2block(first_block.label) == first_block -my_block = asm_bloc(asm_label("testlabel")) +my_block = AsmBlock(AsmLabel("testlabel")) blocks.add_node(my_block) assert len(blocks) == 3 assert blocks.label2block(first_block.label) == first_block @@ -108,17 +108,17 @@ assert blocks.label2block(my_block.label) == my_block assert len(list(blocks.get_bad_blocks())) == 0 assert len(list(blocks.get_bad_blocks_predecessors())) == 0 ### Add a bad block, not linked -my_bad_block = asm_block_bad(asm_label("testlabel_bad")) +my_bad_block = AsmBlockBad(AsmLabel("testlabel_bad")) blocks.add_node(my_bad_block) assert list(blocks.get_bad_blocks()) == [my_bad_block] assert len(list(blocks.get_bad_blocks_predecessors())) == 0 ### Link the bad block and update edges ### Indeed, a sub-element has been modified (bto from a block from blocks) -my_block.bto.add(asm_constraint_to(my_bad_block.label)) +my_block.bto.add(AsmConstraintTo(my_bad_block.label)) blocks.rebuild_edges() assert list(blocks.get_bad_blocks_predecessors()) == [my_block] ### Test strict option -my_block.bto.add(asm_constraint_to(my_block.label)) +my_block.bto.add(AsmConstraintTo(my_block.label)) blocks.rebuild_edges() assert list(blocks.get_bad_blocks_predecessors(strict=False)) == [my_block] assert len(list(blocks.get_bad_blocks_predecessors(strict=True))) == 0 @@ -126,8 +126,8 @@ assert len(list(blocks.get_bad_blocks_predecessors(strict=True))) == 0 ## Sanity check blocks.sanity_check() ### Next on itself -my_block_ni = asm_bloc(asm_label("testlabel_nextitself")) -my_block_ni.bto.add(asm_constraint_next(my_block_ni.label)) +my_block_ni = AsmBlock(AsmLabel("testlabel_nextitself")) +my_block_ni.bto.add(AsmConstraintNext(my_block_ni.label)) blocks.add_node(my_block_ni) error_raised = False try: @@ -139,16 +139,16 @@ assert error_raised blocks.del_node(my_block_ni) blocks.sanity_check() ### Multiple next on the same node -my_block_target = asm_bloc(asm_label("testlabel_target")) +my_block_target = AsmBlock(AsmLabel("testlabel_target")) blocks.add_node(my_block_target) -my_block_src1 = asm_bloc(asm_label("testlabel_src1")) -my_block_src2 = asm_bloc(asm_label("testlabel_src2")) -my_block_src1.bto.add(asm_constraint_next(my_block_target.label)) +my_block_src1 = AsmBlock(AsmLabel("testlabel_src1")) +my_block_src2 = AsmBlock(AsmLabel("testlabel_src2")) +my_block_src1.bto.add(AsmConstraintNext(my_block_target.label)) blocks.add_node(my_block_src1) ### OK for now blocks.sanity_check() ### Add a second next from src2 to target (already src1 -> target) -my_block_src2.bto.add(asm_constraint_next(my_block_target.label)) +my_block_src2.bto.add(AsmConstraintNext(my_block_target.label)) blocks.add_node(my_block_src2) error_raised = False try: @@ -171,9 +171,9 @@ assert blocks.label2block(my_block_src1.label).max_size == 0 ## Check pendings ### Create a pending element -my_block_src = asm_bloc(asm_label("testlabel_pend_src")) -my_block_dst = asm_bloc(asm_label("testlabel_pend_dst")) -my_block_src.bto.add(asm_constraint_to(my_block_dst.label)) +my_block_src = AsmBlock(AsmLabel("testlabel_pend_src")) +my_block_dst = AsmBlock(AsmLabel("testlabel_pend_dst")) +my_block_src.bto.add(AsmConstraintTo(my_block_dst.label)) blocks.add_node(my_block_src) ### Check resulting state assert len(blocks) == 7 @@ -183,7 +183,7 @@ assert len(blocks.pendings[my_block_dst.label]) == 1 pending = list(blocks.pendings[my_block_dst.label])[0] assert isinstance(pending, blocks.AsmCFGPending) assert pending.waiter == my_block_src -assert pending.constraint == asm_constraint.c_to +assert pending.constraint == AsmConstraint.c_to ### Sanity check must fail error_raised = False try: @@ -219,7 +219,7 @@ assert len(list(blocks.get_bad_blocks())) == 1 ### Check "special" blocks entry_blocks = blocks.heads() bad_block = (block for block in entry_blocks - if isinstance(block, asm_block_bad)).next() + if isinstance(block, AsmBlockBad)).next() entry_blocks.remove(bad_block) alone_block = (block for block in entry_blocks if len(blocks.successors(block)) == 0).next() @@ -236,9 +236,9 @@ assert map(str, entry_block.lines) == ['XOR EAX, EAX', assert len(blocks.successors(entry_block)) == 2 assert len(entry_block.bto) == 2 nextb = blocks.label2block((cons.label for cons in entry_block.bto - if cons.c_t == asm_constraint.c_next).next()) + if cons.c_t == AsmConstraint.c_next).next()) tob = blocks.label2block((cons.label for cons in entry_block.bto - if cons.c_t == asm_constraint.c_to).next()) + if cons.c_t == AsmConstraint.c_to).next()) assert len(nextb.lines) == 4 assert map(str, nextb.lines) == ['XOR EDX, EDX', 'XOR ESI, ESI', @@ -257,7 +257,7 @@ blocks.apply_splitting(mdis.symbol_pool) assert blocks_bef == blocks ## Create conditions for a block split inside_firstbbl = mdis.symbol_pool.getby_offset(4) -tob.bto.add(asm_constraint_to(inside_firstbbl)) +tob.bto.add(AsmConstraintTo(inside_firstbbl)) blocks.rebuild_edges() assert len(blocks.pendings) == 1 assert inside_firstbbl in blocks.pendings @@ -277,8 +277,8 @@ preds = blocks.predecessors(newb) assert len(preds) == 2 assert entry_block in preds assert tob in preds -assert blocks.edges2constraint[(entry_block, newb)] == asm_constraint.c_next -assert blocks.edges2constraint[(tob, newb)] == asm_constraint.c_to +assert blocks.edges2constraint[(entry_block, newb)] == AsmConstraint.c_next +assert blocks.edges2constraint[(tob, newb)] == AsmConstraint.c_to # Check double block split diff --git a/test/core/parse_asm.py b/test/core/parse_asm.py index e91c8c8c..54f3be1d 100755 --- a/test/core/parse_asm.py +++ b/test/core/parse_asm.py @@ -38,7 +38,7 @@ class TestParseAsm(unittest.TestCase): def test_DirectiveDontSplit(self): from miasm2.arch.x86.arch import mn_x86 from miasm2.core.parse_asm import parse_txt - from miasm2.core.asmbloc import asm_resolve_final + from miasm2.core.asmblock import asm_resolve_final ASM0 = ''' lbl0: diff --git a/test/core/sembuilder.py b/test/core/sembuilder.py index 3a575727..d8fdb6c4 100644 --- a/test/core/sembuilder.py +++ b/test/core/sembuilder.py @@ -3,7 +3,7 @@ from pdb import pm from miasm2.core.sembuilder import SemBuilder import miasm2.expression.expression as m2_expr -from miasm2.core.asmbloc import asm_label +from miasm2.core.asmblock import AsmLabel # Test classes class IR(object): @@ -11,13 +11,13 @@ class IR(object): IRDst = m2_expr.ExprId("IRDst") def get_next_instr(self, _): - return asm_label("NEXT") + return AsmLabel("NEXT") def get_next_label(self, _): - return asm_label("NEXT") + return AsmLabel("NEXT") def gen_label(self): - return asm_label("GEN") + return AsmLabel("GEN") class Instr(object): mode = 32 diff --git a/test/ir/analysis.py b/test/ir/analysis.py index 913d9c56..6209b36b 100644 --- a/test/ir/analysis.py +++ b/test/ir/analysis.py @@ -1,8 +1,8 @@ """ Test cases for dead code elimination""" from miasm2.expression.expression import ExprId, ExprInt32, ExprAff, ExprMem -from miasm2.core.asmbloc import asm_label +from miasm2.core.asmblock import AsmLabel from miasm2.ir.analysis import ira -from miasm2.ir.ir import irbloc, AssignBlock +from miasm2.ir.ir import IRBlock, AssignBlock a = ExprId("a") b = ExprId("b") @@ -23,17 +23,17 @@ CST1 = ExprInt32(0x11) CST2 = ExprInt32(0x12) CST3 = ExprInt32(0x13) -LBL0 = asm_label("lbl0") -LBL1 = asm_label("lbl1") -LBL2 = asm_label("lbl2") -LBL3 = asm_label("lbl3") -LBL4 = asm_label("lbl4") -LBL5 = asm_label("lbl5") -LBL6 = asm_label("lbl6") +LBL0 = AsmLabel("lbl0") +LBL1 = AsmLabel("lbl1") +LBL2 = AsmLabel("lbl2") +LBL3 = AsmLabel("lbl3") +LBL4 = AsmLabel("lbl4") +LBL5 = AsmLabel("lbl5") +LBL6 = AsmLabel("lbl6") -def gen_irbloc(label, exprs_list): +def gen_irblock(label, exprs_list): lines = [None for _ in xrange(len(exprs_list))] irs = [] for exprs in exprs_list: @@ -42,7 +42,7 @@ def gen_irbloc(label, exprs_list): else: irs.append(AssignBlock(exprs)) - irbl = irbloc(label, irs, lines) + irbl = IRBlock(label, irs, lines) return irbl @@ -76,111 +76,111 @@ class IRATest(ira): G1_IRA = IRATest() -G1_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)], [ExprAff(b, CST2)]]) -G1_IRB1 = gen_irbloc(LBL1, [[ExprAff(a, b)]]) -G1_IRB2 = gen_irbloc(LBL2, [[ExprAff(r, a)]]) +G1_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)], [ExprAff(b, CST2)]]) +G1_IRB1 = gen_irblock(LBL1, [[ExprAff(a, b)]]) +G1_IRB2 = gen_irblock(LBL2, [[ExprAff(r, a)]]) G1_IRA.graph.add_uniq_edge(G1_IRB0.label, G1_IRB1.label) G1_IRA.graph.add_uniq_edge(G1_IRB1.label, G1_IRB2.label) -G1_IRA.blocs = {irb.label : irb for irb in [G1_IRB0, G1_IRB1, G1_IRB2]} +G1_IRA.blocks = {irb.label : irb for irb in [G1_IRB0, G1_IRB1, G1_IRB2]} # Expected output for graph 1 G1_EXP_IRA = IRATest() -G1_EXP_IRB0 = gen_irbloc(LBL0, [[], [ExprAff(b, CST2)]]) -G1_EXP_IRB1 = gen_irbloc(LBL1, [[ExprAff(a, b)]]) -G1_EXP_IRB2 = gen_irbloc(LBL2, [[ExprAff(r, a)]]) +G1_EXP_IRB0 = gen_irblock(LBL0, [[], [ExprAff(b, CST2)]]) +G1_EXP_IRB1 = gen_irblock(LBL1, [[ExprAff(a, b)]]) +G1_EXP_IRB2 = gen_irblock(LBL2, [[ExprAff(r, a)]]) -G1_EXP_IRA.blocs = {irb.label : irb for irb in [G1_EXP_IRB0, G1_EXP_IRB1, - G1_EXP_IRB2]} +G1_EXP_IRA.blocks = {irb.label : irb for irb in [G1_EXP_IRB0, G1_EXP_IRB1, + G1_EXP_IRB2]} # graph 2 : Natural loop with dead variable G2_IRA = IRATest() -G2_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)], [ExprAff(r, CST1)]]) -G2_IRB1 = gen_irbloc(LBL1, [[ExprAff(a, a+CST1)]]) -G2_IRB2 = gen_irbloc(LBL2, [[ExprAff(a, r)]]) +G2_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)], [ExprAff(r, CST1)]]) +G2_IRB1 = gen_irblock(LBL1, [[ExprAff(a, a+CST1)]]) +G2_IRB2 = gen_irblock(LBL2, [[ExprAff(a, r)]]) G2_IRA.graph.add_uniq_edge(G2_IRB0.label, G2_IRB1.label) G2_IRA.graph.add_uniq_edge(G2_IRB1.label, G2_IRB2.label) G2_IRA.graph.add_uniq_edge(G2_IRB1.label, G2_IRB1.label) -G2_IRA.blocs = {irb.label : irb for irb in [G2_IRB0, G2_IRB1, G2_IRB2]} +G2_IRA.blocks = {irb.label : irb for irb in [G2_IRB0, G2_IRB1, G2_IRB2]} # Expected output for graph 2 G2_EXP_IRA = IRATest() -G2_EXP_IRB0 = gen_irbloc(LBL0, [[], [ExprAff(r, CST1)]]) -G2_EXP_IRB1 = gen_irbloc(LBL1, [[]]) -G2_EXP_IRB2 = gen_irbloc(LBL2, [[]]) +G2_EXP_IRB0 = gen_irblock(LBL0, [[], [ExprAff(r, CST1)]]) +G2_EXP_IRB1 = gen_irblock(LBL1, [[]]) +G2_EXP_IRB2 = gen_irblock(LBL2, [[]]) -G2_EXP_IRA.blocs = {irb.label : irb for irb in [G2_EXP_IRB0, G2_EXP_IRB1, - G2_EXP_IRB2]} +G2_EXP_IRA.blocks = {irb.label : irb for irb in [G2_EXP_IRB0, G2_EXP_IRB1, + G2_EXP_IRB2]} # graph 3 : Natural loop with alive variables G3_IRA = IRATest() -G3_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)]]) -G3_IRB1 = gen_irbloc(LBL1, [[ExprAff(a, a+CST1)]]) -G3_IRB2 = gen_irbloc(LBL2, [[ExprAff(r, a)]]) +G3_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)]]) +G3_IRB1 = gen_irblock(LBL1, [[ExprAff(a, a+CST1)]]) +G3_IRB2 = gen_irblock(LBL2, [[ExprAff(r, a)]]) G3_IRA.graph.add_uniq_edge(G3_IRB0.label, G3_IRB1.label) G3_IRA.graph.add_uniq_edge(G3_IRB1.label, G3_IRB2.label) G3_IRA.graph.add_uniq_edge(G3_IRB1.label, G3_IRB1.label) -G3_IRA.blocs = {irb.label : irb for irb in [G3_IRB0, G3_IRB1, G3_IRB2]} +G3_IRA.blocks = {irb.label : irb for irb in [G3_IRB0, G3_IRB1, G3_IRB2]} # Expected output for graph 3 G3_EXP_IRA = IRATest() -G3_EXP_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)]]) -G3_EXP_IRB1 = gen_irbloc(LBL1, [[ExprAff(a, a+CST1)]]) -G3_EXP_IRB2 = gen_irbloc(LBL2, [[ExprAff(r, a)]]) +G3_EXP_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)]]) +G3_EXP_IRB1 = gen_irblock(LBL1, [[ExprAff(a, a+CST1)]]) +G3_EXP_IRB2 = gen_irblock(LBL2, [[ExprAff(r, a)]]) -G3_EXP_IRA.blocs = {irb.label : irb for irb in [G3_EXP_IRB0, G3_EXP_IRB1, - G3_EXP_IRB2]} +G3_EXP_IRA.blocks = {irb.label : irb for irb in [G3_EXP_IRB0, G3_EXP_IRB1, + G3_EXP_IRB2]} # graph 4 : If/else with dead variables G4_IRA = IRATest() -G4_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)]]) -G4_IRB1 = gen_irbloc(LBL1, [[ExprAff(a, a+CST1)]]) -G4_IRB2 = gen_irbloc(LBL2, [[ExprAff(a, a+CST2)]]) -G4_IRB3 = gen_irbloc(LBL3, [[ExprAff(a, CST3)], [ExprAff(r, a)]]) +G4_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)]]) +G4_IRB1 = gen_irblock(LBL1, [[ExprAff(a, a+CST1)]]) +G4_IRB2 = gen_irblock(LBL2, [[ExprAff(a, a+CST2)]]) +G4_IRB3 = gen_irblock(LBL3, [[ExprAff(a, CST3)], [ExprAff(r, a)]]) G4_IRA.graph.add_uniq_edge(G4_IRB0.label, G4_IRB1.label) G4_IRA.graph.add_uniq_edge(G4_IRB0.label, G4_IRB2.label) G4_IRA.graph.add_uniq_edge(G4_IRB1.label, G4_IRB3.label) G4_IRA.graph.add_uniq_edge(G4_IRB2.label, G4_IRB3.label) -G4_IRA.blocs = {irb.label : irb for irb in [G4_IRB0, G4_IRB1, G4_IRB2, - G4_IRB3]} +G4_IRA.blocks = {irb.label : irb for irb in [G4_IRB0, G4_IRB1, G4_IRB2, + G4_IRB3]} # Expected output for graph 4 G4_EXP_IRA = IRATest() -G4_EXP_IRB0 = gen_irbloc(LBL0, [[]]) -G4_EXP_IRB1 = gen_irbloc(LBL1, [[]]) -G4_EXP_IRB2 = gen_irbloc(LBL2, [[]]) -G4_EXP_IRB3 = gen_irbloc(LBL3, [[ExprAff(a, CST3)], [ExprAff(r, a)]]) +G4_EXP_IRB0 = gen_irblock(LBL0, [[]]) +G4_EXP_IRB1 = gen_irblock(LBL1, [[]]) +G4_EXP_IRB2 = gen_irblock(LBL2, [[]]) +G4_EXP_IRB3 = gen_irblock(LBL3, [[ExprAff(a, CST3)], [ExprAff(r, a)]]) -G4_EXP_IRA.blocs = {irb.label : irb for irb in [G4_EXP_IRB0, G4_EXP_IRB1, - G4_EXP_IRB2, G4_EXP_IRB3]} +G4_EXP_IRA.blocks = {irb.label : irb for irb in [G4_EXP_IRB0, G4_EXP_IRB1, + G4_EXP_IRB2, G4_EXP_IRB3]} # graph 5 : Loop and If/else with dead variables G5_IRA = IRATest() -G5_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)]]) -G5_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, CST2)]]) -G5_IRB2 = gen_irbloc(LBL2, [[ExprAff(a, a+CST2)]]) -G5_IRB3 = gen_irbloc(LBL3, [[ExprAff(a, a+CST3)]]) -G5_IRB4 = gen_irbloc(LBL4, [[ExprAff(a, a+CST1)]]) -G5_IRB5 = gen_irbloc(LBL5, [[ExprAff(a, r)]]) +G5_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)]]) +G5_IRB1 = gen_irblock(LBL1, [[ExprAff(r, CST2)]]) +G5_IRB2 = gen_irblock(LBL2, [[ExprAff(a, a+CST2)]]) +G5_IRB3 = gen_irblock(LBL3, [[ExprAff(a, a+CST3)]]) +G5_IRB4 = gen_irblock(LBL4, [[ExprAff(a, a+CST1)]]) +G5_IRB5 = gen_irblock(LBL5, [[ExprAff(a, r)]]) G5_IRA.graph.add_uniq_edge(G5_IRB0.label, G5_IRB1.label) G5_IRA.graph.add_uniq_edge(G5_IRB1.label, G5_IRB2.label) @@ -190,32 +190,32 @@ G5_IRA.graph.add_uniq_edge(G5_IRB3.label, G5_IRB4.label) G5_IRA.graph.add_uniq_edge(G5_IRB4.label, G5_IRB5.label) G5_IRA.graph.add_uniq_edge(G5_IRB4.label, G5_IRB1.label) -G5_IRA.blocs = {irb.label : irb for irb in [G5_IRB0, G5_IRB1, G5_IRB2, G5_IRB3, - G5_IRB4, G5_IRB5]} +G5_IRA.blocks = {irb.label : irb for irb in [G5_IRB0, G5_IRB1, G5_IRB2, G5_IRB3, + G5_IRB4, G5_IRB5]} # Expected output for graph 5 G5_EXP_IRA = IRATest() -G5_EXP_IRB0 = gen_irbloc(LBL0, [[]]) -G5_EXP_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, CST2)]]) -G5_EXP_IRB2 = gen_irbloc(LBL2, [[]]) -G5_EXP_IRB3 = gen_irbloc(LBL3, [[]]) -G5_EXP_IRB4 = gen_irbloc(LBL4, [[]]) -G5_EXP_IRB5 = gen_irbloc(LBL5, [[]]) +G5_EXP_IRB0 = gen_irblock(LBL0, [[]]) +G5_EXP_IRB1 = gen_irblock(LBL1, [[ExprAff(r, CST2)]]) +G5_EXP_IRB2 = gen_irblock(LBL2, [[]]) +G5_EXP_IRB3 = gen_irblock(LBL3, [[]]) +G5_EXP_IRB4 = gen_irblock(LBL4, [[]]) +G5_EXP_IRB5 = gen_irblock(LBL5, [[]]) -G5_EXP_IRA.blocs = {irb.label : irb for irb in [G5_EXP_IRB0, G5_EXP_IRB1, - G5_EXP_IRB2, G5_EXP_IRB3, - G5_EXP_IRB4, G5_EXP_IRB5]} +G5_EXP_IRA.blocks = {irb.label : irb for irb in [G5_EXP_IRB0, G5_EXP_IRB1, + G5_EXP_IRB2, G5_EXP_IRB3, + G5_EXP_IRB4, G5_EXP_IRB5]} # graph 6 : Natural loop with dead variables symetric affectation # (a = b <-> b = a ) G6_IRA = IRATest() -G6_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)]]) -G6_IRB1 = gen_irbloc(LBL1, [[ExprAff(b, a)]]) -G6_IRB2 = gen_irbloc(LBL2, [[ExprAff(a, b)]]) -G6_IRB3 = gen_irbloc(LBL3, [[ExprAff(r, CST2)]]) +G6_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)]]) +G6_IRB1 = gen_irblock(LBL1, [[ExprAff(b, a)]]) +G6_IRB2 = gen_irblock(LBL2, [[ExprAff(a, b)]]) +G6_IRB3 = gen_irblock(LBL3, [[ExprAff(r, CST2)]]) G6_IRA.graph.add_uniq_edge(G6_IRB0.label, G6_IRB1.label) @@ -223,28 +223,28 @@ G6_IRA.graph.add_uniq_edge(G6_IRB1.label, G6_IRB2.label) G6_IRA.graph.add_uniq_edge(G6_IRB2.label, G6_IRB1.label) G6_IRA.graph.add_uniq_edge(G6_IRB2.label, G6_IRB3.label) -G6_IRA.blocs = {irb.label : irb for irb in [G6_IRB0, G6_IRB1, G6_IRB2, - G6_IRB3]} +G6_IRA.blocks = {irb.label : irb for irb in [G6_IRB0, G6_IRB1, G6_IRB2, + G6_IRB3]} # Expected output for graph 6 G6_EXP_IRA = IRATest() -G6_EXP_IRB0 = gen_irbloc(LBL0, [[]]) -G6_EXP_IRB1 = gen_irbloc(LBL1, [[]]) -G6_EXP_IRB2 = gen_irbloc(LBL2, [[]]) -G6_EXP_IRB3 = gen_irbloc(LBL3, [[ExprAff(r, CST2)]]) +G6_EXP_IRB0 = gen_irblock(LBL0, [[]]) +G6_EXP_IRB1 = gen_irblock(LBL1, [[]]) +G6_EXP_IRB2 = gen_irblock(LBL2, [[]]) +G6_EXP_IRB3 = gen_irblock(LBL3, [[ExprAff(r, CST2)]]) -G6_EXP_IRA.blocs = {irb.label : irb for irb in [G6_EXP_IRB0, G6_EXP_IRB1, - G6_EXP_IRB2, G6_EXP_IRB3]} +G6_EXP_IRA.blocks = {irb.label : irb for irb in [G6_EXP_IRB0, G6_EXP_IRB1, + G6_EXP_IRB2, G6_EXP_IRB3]} # graph 7 : Double entry loop with dead variables G7_IRA = IRATest() -G7_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)], [ExprAff(r, CST1)]]) -G7_IRB1 = gen_irbloc(LBL1, [[ExprAff(a, a+CST1)]]) -G7_IRB2 = gen_irbloc(LBL2, [[ExprAff(a, a+CST2)]]) -G7_IRB3 = gen_irbloc(LBL3, [[ExprAff(a, r)]]) +G7_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)], [ExprAff(r, CST1)]]) +G7_IRB1 = gen_irblock(LBL1, [[ExprAff(a, a+CST1)]]) +G7_IRB2 = gen_irblock(LBL2, [[ExprAff(a, a+CST2)]]) +G7_IRB3 = gen_irblock(LBL3, [[ExprAff(a, r)]]) G7_IRA.graph.add_uniq_edge(G7_IRB0.label, G7_IRB1.label) @@ -254,28 +254,28 @@ G7_IRA.graph.add_uniq_edge(G7_IRB2.label, G7_IRB3.label) G7_IRA.graph.add_uniq_edge(G7_IRB0.label, G7_IRB2.label) -G7_IRA.blocs = {irb.label : irb for irb in [G7_IRB0, G7_IRB1, G7_IRB2, - G7_IRB3]} +G7_IRA.blocks = {irb.label : irb for irb in [G7_IRB0, G7_IRB1, G7_IRB2, + G7_IRB3]} # Expected output for graph 7 G7_EXP_IRA = IRATest() -G7_EXP_IRB0 = gen_irbloc(LBL0, [[], [ExprAff(r, CST1)]]) -G7_EXP_IRB1 = gen_irbloc(LBL1, [[]]) -G7_EXP_IRB2 = gen_irbloc(LBL2, [[]]) -G7_EXP_IRB3 = gen_irbloc(LBL3, [[]]) +G7_EXP_IRB0 = gen_irblock(LBL0, [[], [ExprAff(r, CST1)]]) +G7_EXP_IRB1 = gen_irblock(LBL1, [[]]) +G7_EXP_IRB2 = gen_irblock(LBL2, [[]]) +G7_EXP_IRB3 = gen_irblock(LBL3, [[]]) -G7_EXP_IRA.blocs = {irb.label : irb for irb in [G7_EXP_IRB0, G7_EXP_IRB1, - G7_EXP_IRB2, G7_EXP_IRB3]} +G7_EXP_IRA.blocks = {irb.label : irb for irb in [G7_EXP_IRB0, G7_EXP_IRB1, + G7_EXP_IRB2, G7_EXP_IRB3]} # graph 8 : Nested loops with dead variables G8_IRA = IRATest() -G8_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)], [ExprAff(b, CST1)]]) -G8_IRB1 = gen_irbloc(LBL1, [[ExprAff(a, a+CST1)]]) -G8_IRB2 = gen_irbloc(LBL2, [[ExprAff(b, b+CST2)]]) -G8_IRB3 = gen_irbloc(LBL3, [[ExprAff(a, b)]]) +G8_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)], [ExprAff(b, CST1)]]) +G8_IRB1 = gen_irblock(LBL1, [[ExprAff(a, a+CST1)]]) +G8_IRB2 = gen_irblock(LBL2, [[ExprAff(b, b+CST2)]]) +G8_IRB3 = gen_irblock(LBL3, [[ExprAff(a, b)]]) G8_IRA.graph.add_uniq_edge(G8_IRB0.label, G8_IRB1.label) @@ -285,30 +285,30 @@ G8_IRA.graph.add_uniq_edge(G8_IRB2.label, G8_IRB3.label) G8_IRA.graph.add_uniq_edge(G8_IRB3.label, G8_IRB2.label) -G8_IRA.blocs = {irb.label : irb for irb in [G8_IRB0, G8_IRB1, G8_IRB2, - G8_IRB3]} +G8_IRA.blocks = {irb.label : irb for irb in [G8_IRB0, G8_IRB1, G8_IRB2, + G8_IRB3]} # Expected output for graph 8 G8_EXP_IRA = IRATest() -G8_EXP_IRB0 = gen_irbloc(LBL0, [[], []]) -G8_EXP_IRB1 = gen_irbloc(LBL1, [[]]) -G8_EXP_IRB2 = gen_irbloc(LBL2, [[]]) -G8_EXP_IRB3 = gen_irbloc(LBL3, [[]]) +G8_EXP_IRB0 = gen_irblock(LBL0, [[], []]) +G8_EXP_IRB1 = gen_irblock(LBL1, [[]]) +G8_EXP_IRB2 = gen_irblock(LBL2, [[]]) +G8_EXP_IRB3 = gen_irblock(LBL3, [[]]) -G8_EXP_IRA.blocs = {irb.label : irb for irb in [G8_EXP_IRB0, G8_EXP_IRB1, - G8_EXP_IRB2, G8_EXP_IRB3]} +G8_EXP_IRA.blocks = {irb.label : irb for irb in [G8_EXP_IRB0, G8_EXP_IRB1, + G8_EXP_IRB2, G8_EXP_IRB3]} # graph 9 : Miultiple-exits loops with dead variables G9_IRA = IRATest() -G9_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)], [ExprAff(b, CST1)]]) -G9_IRB1 = gen_irbloc(LBL1, [[ExprAff(a, a+CST1)], [ExprAff(b, b+CST1)]]) -G9_IRB2 = gen_irbloc(LBL2, [[ExprAff(a, a+CST2)], [ExprAff(b, b+CST2)]]) -G9_IRB3 = gen_irbloc(LBL3, [[ExprAff(a, b)]]) -G9_IRB4 = gen_irbloc(LBL4, [[ExprAff(r, a)], [ExprAff(r, b)]]) +G9_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)], [ExprAff(b, CST1)]]) +G9_IRB1 = gen_irblock(LBL1, [[ExprAff(a, a+CST1)], [ExprAff(b, b+CST1)]]) +G9_IRB2 = gen_irblock(LBL2, [[ExprAff(a, a+CST2)], [ExprAff(b, b+CST2)]]) +G9_IRB3 = gen_irblock(LBL3, [[ExprAff(a, b)]]) +G9_IRB4 = gen_irblock(LBL4, [[ExprAff(r, a)], [ExprAff(r, b)]]) G9_IRA.graph.add_uniq_edge(G9_IRB0.label, G9_IRB4.label) @@ -321,32 +321,32 @@ G9_IRA.graph.add_uniq_edge(G9_IRB2.label, G9_IRB3.label) G9_IRA.graph.add_uniq_edge(G9_IRB3.label, G9_IRB4.label) -G9_IRA.blocs = {irb.label : irb for irb in [G9_IRB0, G9_IRB1, G9_IRB2, - G9_IRB3, G9_IRB4]} +G9_IRA.blocks = {irb.label : irb for irb in [G9_IRB0, G9_IRB1, G9_IRB2, + G9_IRB3, G9_IRB4]} # Expected output for graph 9 G9_EXP_IRA = IRATest() -G9_EXP_IRB0 = gen_irbloc(LBL0, [[], [ExprAff(b, CST1)]]) -G9_EXP_IRB1 = gen_irbloc(LBL1, [[], [ExprAff(b, b+CST1)]]) -G9_EXP_IRB2 = gen_irbloc(LBL2, [[], [ExprAff(b, b+CST2)]]) -G9_EXP_IRB3 = gen_irbloc(LBL3, [[]]) -G9_EXP_IRB4 = gen_irbloc(LBL4, [[], [ExprAff(r, b)]]) +G9_EXP_IRB0 = gen_irblock(LBL0, [[], [ExprAff(b, CST1)]]) +G9_EXP_IRB1 = gen_irblock(LBL1, [[], [ExprAff(b, b+CST1)]]) +G9_EXP_IRB2 = gen_irblock(LBL2, [[], [ExprAff(b, b+CST2)]]) +G9_EXP_IRB3 = gen_irblock(LBL3, [[]]) +G9_EXP_IRB4 = gen_irblock(LBL4, [[], [ExprAff(r, b)]]) -G9_EXP_IRA.blocs = {irb.label : irb for irb in [G9_EXP_IRB0, G9_EXP_IRB1, - G9_EXP_IRB2, G9_EXP_IRB3, - G9_EXP_IRB4]} +G9_EXP_IRA.blocks = {irb.label : irb for irb in [G9_EXP_IRB0, G9_EXP_IRB1, + G9_EXP_IRB2, G9_EXP_IRB3, + G9_EXP_IRB4]} # graph 10 : Natural loop with alive variables symetric affectation # (a = b <-> b = a ) G10_IRA = IRATest() -G10_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)]]) -G10_IRB1 = gen_irbloc(LBL1, [[ExprAff(b, a)]]) -G10_IRB2 = gen_irbloc(LBL2, [[ExprAff(a, b)]]) -G10_IRB3 = gen_irbloc(LBL3, [[ExprAff(r, CST1)]]) +G10_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)]]) +G10_IRB1 = gen_irblock(LBL1, [[ExprAff(b, a)]]) +G10_IRB2 = gen_irblock(LBL2, [[ExprAff(a, b)]]) +G10_IRB3 = gen_irblock(LBL3, [[ExprAff(r, CST1)]]) G10_IRA.graph.add_uniq_edge(G10_IRB0.label, G10_IRB1.label) @@ -354,29 +354,29 @@ G10_IRA.graph.add_uniq_edge(G10_IRB1.label, G10_IRB2.label) G10_IRA.graph.add_uniq_edge(G10_IRB2.label, G10_IRB1.label) G10_IRA.graph.add_uniq_edge(G10_IRB2.label, G10_IRB3.label) -G10_IRA.blocs = {irb.label : irb for irb in [G10_IRB0, G10_IRB1, - G10_IRB2, G10_IRB3]} +G10_IRA.blocks = {irb.label : irb for irb in [G10_IRB0, G10_IRB1, + G10_IRB2, G10_IRB3]} # Expected output for graph 10 G10_EXP_IRA = IRATest() -G10_EXP_IRB0 = gen_irbloc(LBL0, [[]]) -G10_EXP_IRB1 = gen_irbloc(LBL1, [[]]) -G10_EXP_IRB2 = gen_irbloc(LBL2, [[]]) -G10_EXP_IRB3 = gen_irbloc(LBL3, [[ExprAff(r, CST1)]]) +G10_EXP_IRB0 = gen_irblock(LBL0, [[]]) +G10_EXP_IRB1 = gen_irblock(LBL1, [[]]) +G10_EXP_IRB2 = gen_irblock(LBL2, [[]]) +G10_EXP_IRB3 = gen_irblock(LBL3, [[ExprAff(r, CST1)]]) -G10_EXP_IRA.blocs = {irb.label : irb for irb in [G10_EXP_IRB0, G10_EXP_IRB1, - G10_EXP_IRB2, G10_EXP_IRB3]} +G10_EXP_IRA.blocks = {irb.label : irb for irb in [G10_EXP_IRB0, G10_EXP_IRB1, + G10_EXP_IRB2, G10_EXP_IRB3]} # graph 11 : If/Else conditions with alive variables G11_IRA = IRATest() -G11_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, b)]]) -G11_IRB1 = gen_irbloc(LBL1, [[ExprAff(b, a)]]) -G11_IRB2 = gen_irbloc(LBL2, [[ExprAff(r, a)]]) -G11_IRB3 = gen_irbloc(LBL3, [[ExprAff(a, a+CST1)]]) -G11_IRB4 = gen_irbloc(LBL4, [[ExprAff(b, b+CST1)]]) +G11_IRB0 = gen_irblock(LBL0, [[ExprAff(a, b)]]) +G11_IRB1 = gen_irblock(LBL1, [[ExprAff(b, a)]]) +G11_IRB2 = gen_irblock(LBL2, [[ExprAff(r, a)]]) +G11_IRB3 = gen_irblock(LBL3, [[ExprAff(a, a+CST1)]]) +G11_IRB4 = gen_irblock(LBL4, [[ExprAff(b, b+CST1)]]) G11_IRA.graph.add_uniq_edge(G11_IRB0.label, G11_IRB1.label) @@ -385,31 +385,31 @@ G11_IRA.graph.add_uniq_edge(G11_IRB1.label, G11_IRB0.label) #G11_IRA.graph.add_uniq_edge(G11_IRB4.label, G11_IRB0.label) G11_IRA.graph.add_uniq_edge(G11_IRB1.label, G11_IRB2.label) -G11_IRA.blocs = {irb.label : irb for irb in [G11_IRB0, G11_IRB1, G11_IRB2]} +G11_IRA.blocks = {irb.label : irb for irb in [G11_IRB0, G11_IRB1, G11_IRB2]} # Expected output for graph 11 G11_EXP_IRA = IRATest() -G11_EXP_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, b)]]) -G11_EXP_IRB1 = gen_irbloc(LBL1, [[ExprAff(b, a)]]) -G11_EXP_IRB2 = gen_irbloc(LBL2, [[ExprAff(r, a)]]) -#G11_EXP_IRB3 = gen_irbloc(LBL3, [[ExprAff(a, a+CST1)]]) -#G11_EXP_IRB4 = gen_irbloc(LBL4, [[ExprAff(b, b+CST1)]]) +G11_EXP_IRB0 = gen_irblock(LBL0, [[ExprAff(a, b)]]) +G11_EXP_IRB1 = gen_irblock(LBL1, [[ExprAff(b, a)]]) +G11_EXP_IRB2 = gen_irblock(LBL2, [[ExprAff(r, a)]]) +#G11_EXP_IRB3 = gen_irblock(LBL3, [[ExprAff(a, a+CST1)]]) +#G11_EXP_IRB4 = gen_irblock(LBL4, [[ExprAff(b, b+CST1)]]) -G11_EXP_IRA.blocs = {irb.label : irb for irb in [G11_EXP_IRB0, G11_EXP_IRB1, - G11_EXP_IRB2]} +G11_EXP_IRA.blocks = {irb.label : irb for irb in [G11_EXP_IRB0, G11_EXP_IRB1, + G11_EXP_IRB2]} # graph 12 : Graph with multiple out points and useless definitions # of return register G12_IRA = IRATest() -G12_IRB0 = gen_irbloc(LBL0, [[ExprAff(r, CST1)], [ExprAff(a, CST2)]]) -G12_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, CST2)]]) -G12_IRB2 = gen_irbloc(LBL2, [[ExprAff(r, a)], [ExprAff(b, CST3)]]) -G12_IRB3 = gen_irbloc(LBL3, [[ExprAff(r, CST3)]]) -G12_IRB4 = gen_irbloc(LBL4, [[ExprAff(r, CST2)]]) -G12_IRB5 = gen_irbloc(LBL5, [[ExprAff(r, b)]]) +G12_IRB0 = gen_irblock(LBL0, [[ExprAff(r, CST1)], [ExprAff(a, CST2)]]) +G12_IRB1 = gen_irblock(LBL1, [[ExprAff(r, CST2)]]) +G12_IRB2 = gen_irblock(LBL2, [[ExprAff(r, a)], [ExprAff(b, CST3)]]) +G12_IRB3 = gen_irblock(LBL3, [[ExprAff(r, CST3)]]) +G12_IRB4 = gen_irblock(LBL4, [[ExprAff(r, CST2)]]) +G12_IRB5 = gen_irblock(LBL5, [[ExprAff(r, b)]]) G12_IRA.graph.add_uniq_edge(G12_IRB0.label, G12_IRB1.label) G12_IRA.graph.add_uniq_edge(G12_IRB0.label, G12_IRB2.label) @@ -417,55 +417,55 @@ G12_IRA.graph.add_uniq_edge(G12_IRB2.label, G12_IRB3.label) G12_IRA.graph.add_uniq_edge(G12_IRB2.label, G12_IRB4.label) G12_IRA.graph.add_uniq_edge(G12_IRB4.label, G12_IRB5.label) -G12_IRA.blocs = {irb.label : irb for irb in [G12_IRB0, G12_IRB1, G12_IRB2, - G12_IRB3, G12_IRB4, G12_IRB5]} +G12_IRA.blocks = {irb.label : irb for irb in [G12_IRB0, G12_IRB1, G12_IRB2, + G12_IRB3, G12_IRB4, G12_IRB5]} # Expected output for graph 12 G12_EXP_IRA = IRATest() -G12_EXP_IRB0 = gen_irbloc(LBL0, [[], []]) -G12_EXP_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, CST2)]]) -G12_EXP_IRB2 = gen_irbloc(LBL2, [[], [ExprAff(b, CST3)]]) -G12_EXP_IRB3 = gen_irbloc(LBL3, [[ExprAff(r, CST3)]]) -G12_EXP_IRB4 = gen_irbloc(LBL4, [[]]) -G12_EXP_IRB5 = gen_irbloc(LBL5, [[ExprAff(r, b)]]) +G12_EXP_IRB0 = gen_irblock(LBL0, [[], []]) +G12_EXP_IRB1 = gen_irblock(LBL1, [[ExprAff(r, CST2)]]) +G12_EXP_IRB2 = gen_irblock(LBL2, [[], [ExprAff(b, CST3)]]) +G12_EXP_IRB3 = gen_irblock(LBL3, [[ExprAff(r, CST3)]]) +G12_EXP_IRB4 = gen_irblock(LBL4, [[]]) +G12_EXP_IRB5 = gen_irblock(LBL5, [[ExprAff(r, b)]]) -G12_EXP_IRA.blocs = {irb.label : irb for irb in [G12_EXP_IRB0, G12_EXP_IRB1, - G12_EXP_IRB2, G12_EXP_IRB3, - G12_EXP_IRB4, G12_EXP_IRB5]} +G12_EXP_IRA.blocks = {irb.label : irb for irb in [G12_EXP_IRB0, G12_EXP_IRB1, + G12_EXP_IRB2, G12_EXP_IRB3, + G12_EXP_IRB4, G12_EXP_IRB5]} # graph 13 : Graph where a leaf has lost its son G13_IRA = IRATest() -G13_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)], [ExprAff(b, CST2)]]) -G13_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, b)]]) -G13_IRB2 = gen_irbloc(LBL2, [[ExprAff(d, CST2)], [ExprAff(a, b+CST1), +G13_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)], [ExprAff(b, CST2)]]) +G13_IRB1 = gen_irblock(LBL1, [[ExprAff(r, b)]]) +G13_IRB2 = gen_irblock(LBL2, [[ExprAff(d, CST2)], [ExprAff(a, b+CST1), ExprAff(c, a+b)]]) -G13_IRB3 = gen_irbloc(LBL3, [[]]) # lost son -G13_IRB4 = gen_irbloc(LBL4, [[ExprAff(b, CST2)]]) +G13_IRB3 = gen_irblock(LBL3, [[]]) # lost son +G13_IRB4 = gen_irblock(LBL4, [[ExprAff(b, CST2)]]) G13_IRA.graph.add_uniq_edge(G13_IRB0.label, G13_IRB1.label) G13_IRA.graph.add_uniq_edge(G13_IRB0.label, G13_IRB4.label) G13_IRA.graph.add_uniq_edge(G13_IRB2.label, G13_IRB3.label) G13_IRA.graph.add_uniq_edge(G13_IRB4.label, G13_IRB2.label) -G13_IRA.blocs = {irb.label : irb for irb in [G13_IRB0, G13_IRB1, G13_IRB2, - G13_IRB4]} +G13_IRA.blocks = {irb.label : irb for irb in [G13_IRB0, G13_IRB1, G13_IRB2, + G13_IRB4]} # Expected output for graph 13 G13_EXP_IRA = IRATest() -G13_EXP_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)], [ExprAff(b, CST2)]]) -G13_EXP_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, b)]]) -G13_EXP_IRB2 = gen_irbloc(LBL2, [[ExprAff(d, CST2)], [ExprAff(a, b+CST1), - ExprAff(c, a+b)]]) -G13_EXP_IRB3 = gen_irbloc(LBL3, [[]]) -G13_EXP_IRB4 = gen_irbloc(LBL4, [[ExprAff(b, CST2)]]) +G13_EXP_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)], [ExprAff(b, CST2)]]) +G13_EXP_IRB1 = gen_irblock(LBL1, [[ExprAff(r, b)]]) +G13_EXP_IRB2 = gen_irblock(LBL2, [[ExprAff(d, CST2)], [ExprAff(a, b+CST1), + ExprAff(c, a+b)]]) +G13_EXP_IRB3 = gen_irblock(LBL3, [[]]) +G13_EXP_IRB4 = gen_irblock(LBL4, [[ExprAff(b, CST2)]]) -G13_EXP_IRA.blocs = {irb.label: irb for irb in [G13_EXP_IRB0, G13_EXP_IRB1, - G13_EXP_IRB2, G13_EXP_IRB4]} +G13_EXP_IRA.blocks = {irb.label: irb for irb in [G13_EXP_IRB0, G13_EXP_IRB1, + G13_EXP_IRB2, G13_EXP_IRB4]} #G13_EXP_IRA = G13_IRA @@ -474,74 +474,74 @@ G13_EXP_IRA.blocs = {irb.label: irb for irb in [G13_EXP_IRB0, G13_EXP_IRB1, G14_IRA = IRATest() -G14_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)], [ExprAff(c, a)], - [ExprAff(a, CST2)]]) -G14_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, a+c)]]) +G14_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)], [ExprAff(c, a)], + [ExprAff(a, CST2)]]) +G14_IRB1 = gen_irblock(LBL1, [[ExprAff(r, a+c)]]) G14_IRA.graph.add_uniq_edge(G14_IRB0.label, G14_IRB1.label) -G14_IRA.blocs = {irb.label : irb for irb in [G14_IRB0, G14_IRB1]} +G14_IRA.blocks = {irb.label : irb for irb in [G14_IRB0, G14_IRB1]} # Expected output for graph 1 G14_EXP_IRA = IRATest() -G14_EXP_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1)], [ExprAff(c, a)], - [ExprAff(a, CST2)]]) -G14_EXP_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, a+c)]]) +G14_EXP_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1)], [ExprAff(c, a)], + [ExprAff(a, CST2)]]) +G14_EXP_IRB1 = gen_irblock(LBL1, [[ExprAff(r, a+c)]]) -G14_EXP_IRA.blocs = {irb.label: irb for irb in [G14_EXP_IRB0, G14_EXP_IRB1]} +G14_EXP_IRA.blocks = {irb.label: irb for irb in [G14_EXP_IRB0, G14_EXP_IRB1]} # graph 15 : Graph where variable assigned multiple and read at the same time, # but useless G15_IRA = IRATest() -G15_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST2)], [ExprAff(a, CST1), - ExprAff(b, a+CST2), - ExprAff(c, CST1)]]) -G15_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, a)]]) +G15_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST2)], [ExprAff(a, CST1), + ExprAff(b, a+CST2), + ExprAff(c, CST1)]]) +G15_IRB1 = gen_irblock(LBL1, [[ExprAff(r, a)]]) G15_IRA.graph.add_uniq_edge(G15_IRB0.label, G15_IRB1.label) -G15_IRA.blocs = {irb.label : irb for irb in [G15_IRB0, G15_IRB1]} +G15_IRA.blocks = {irb.label : irb for irb in [G15_IRB0, G15_IRB1]} # Expected output for graph 1 G15_EXP_IRA = IRATest() -G15_EXP_IRB0 = gen_irbloc(LBL0, [[], [ExprAff(a, CST1)]]) -G15_EXP_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, a)]]) +G15_EXP_IRB0 = gen_irblock(LBL0, [[], [ExprAff(a, CST1)]]) +G15_EXP_IRB1 = gen_irblock(LBL1, [[ExprAff(r, a)]]) -G15_EXP_IRA.blocs = {irb.label: irb for irb in [G15_EXP_IRB0, G15_EXP_IRB1]} +G15_EXP_IRA.blocks = {irb.label: irb for irb in [G15_EXP_IRB0, G15_EXP_IRB1]} # graph 16 : Graph where variable assigned multiple times in the same bloc G16_IRA = IRATest() -G16_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, CST1), ExprAff(b, CST2), - ExprAff(c, CST3)], [ExprAff(a, c+CST1), - ExprAff(b, c+CST2)]]) -G16_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, a+b)], [ExprAff(r, c+r)]]) -G16_IRB2 = gen_irbloc(LBL2, [[]]) +G16_IRB0 = gen_irblock(LBL0, [[ExprAff(a, CST1), ExprAff(b, CST2), + ExprAff(c, CST3)], [ExprAff(a, c+CST1), + ExprAff(b, c+CST2)]]) +G16_IRB1 = gen_irblock(LBL1, [[ExprAff(r, a+b)], [ExprAff(r, c+r)]]) +G16_IRB2 = gen_irblock(LBL2, [[]]) G16_IRA.graph.add_uniq_edge(G16_IRB0.label, G16_IRB1.label) G16_IRA.graph.add_uniq_edge(G16_IRB1.label, G16_IRB2.label) -G16_IRA.blocs = {irb.label : irb for irb in [G16_IRB0, G16_IRB1]} +G16_IRA.blocks = {irb.label : irb for irb in [G16_IRB0, G16_IRB1]} # Expected output for graph 1 G16_EXP_IRA = IRATest() -G16_EXP_IRB0 = gen_irbloc(LBL0, [[ExprAff(c, CST3)], [ExprAff(a, c + CST1), - ExprAff(b, c + CST2)]]) -G16_EXP_IRB1 = gen_irbloc(LBL1, [[ExprAff(r, a+b)], [ExprAff(r, c+r)]]) +G16_EXP_IRB0 = gen_irblock(LBL0, [[ExprAff(c, CST3)], [ExprAff(a, c + CST1), + ExprAff(b, c + CST2)]]) +G16_EXP_IRB1 = gen_irblock(LBL1, [[ExprAff(r, a+b)], [ExprAff(r, c+r)]]) -G16_EXP_IRA.blocs = {irb.label: irb for irb in [G16_EXP_IRB0, G16_EXP_IRB1]} +G16_EXP_IRA.blocks = {irb.label: irb for irb in [G16_EXP_IRB0, G16_EXP_IRB1]} # graph 17 : parallel ir G17_IRA = IRATest() -G17_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, a*b), +G17_IRB0 = gen_irblock(LBL0, [[ExprAff(a, a*b), ExprAff(b, c), ExprAff(c, CST1)], @@ -595,49 +595,49 @@ G17_IRB0 = gen_irbloc(LBL0, [[ExprAff(a, a*b), ]) -G17_IRA.blocs = {irb.label : irb for irb in [G17_IRB0]} +G17_IRA.blocks = {irb.label : irb for irb in [G17_IRB0]} G17_IRA.graph.add_node(G17_IRB0.label) # Expected output for graph 17 G17_EXP_IRA = IRATest() -G17_EXP_IRB0 = gen_irbloc(LBL0, [[], +G17_EXP_IRB0 = gen_irblock(LBL0, [[], - [ExprAff(d, d+ CST2)], + [ExprAff(d, d+ CST2)], - [ExprAff(a, CST1)], + [ExprAff(a, CST1)], - [ExprAff(ExprMem(d+CST1), a)], + [ExprAff(ExprMem(d+CST1), a)], - [ExprAff(a, CST1)], + [ExprAff(a, CST1)], - [ExprAff(ExprMem(d+CST2), a)], + [ExprAff(ExprMem(d+CST2), a)], - [ExprAff(a, CST2)], + [ExprAff(a, CST2)], - [ExprAff(a, a+CST1)], + [ExprAff(a, a+CST1)], - [ExprAff(d, a)], + [ExprAff(d, a)], - [ExprAff(d, d+CST1)], + [ExprAff(d, d+CST1)], - [ExprAff(a, CST2)], + [ExprAff(a, CST2)], - [ExprAff(a, a+CST2)], + [ExprAff(a, a+CST2)], - [ExprAff(a, CST2), - ExprAff(b, a)], + [ExprAff(a, CST2), + ExprAff(b, a)], - [ExprAff(a, CST1), - ExprAff(b, a), - ExprAff(c, b)], + [ExprAff(a, CST1), + ExprAff(b, a), + ExprAff(c, b)], - G17_IRB0.irs[14] - # Trick because a+b+c != ((a+b)+c) - ]) + G17_IRB0.irs[14] + # Trick because a+b+c != ((a+b)+c) + ]) -G17_EXP_IRA.blocs = {irb.label : irb for irb in [G17_EXP_IRB0]} +G17_EXP_IRA.blocks = {irb.label : irb for irb in [G17_EXP_IRB0]} # Begining of tests @@ -674,8 +674,8 @@ for test_nb, test in enumerate([(G1_IRA, G1_EXP_IRA), open("simp_graph_%02d.dot" % (test_nb+1), "w").write(g_ira.graph.dot()) # Same number of blocks - assert len(g_ira.blocs) == len(g_exp_ira.blocs) - # Check that each expr in the blocs are the same - for lbl, irb in g_ira.blocs.iteritems(): - exp_irb = g_exp_ira.blocs[lbl] + assert len(g_ira.blocks) == len(g_exp_ira.blocks) + # Check that each expr in the blocks are the same + for lbl, irb in g_ira.blocks.iteritems(): + exp_irb = g_exp_ira.blocks[lbl] assert exp_irb.irs == irb.irs diff --git a/test/ir/symbexec.py b/test/ir/symbexec.py index 2e776f74..48de6573 100755 --- a/test/ir/symbexec.py +++ b/test/ir/symbexec.py @@ -10,7 +10,7 @@ class TestSymbExec(unittest.TestCase): from miasm2.expression.expression import ExprInt32, ExprId, ExprMem, \ ExprCompose, ExprAff from miasm2.arch.x86.sem import ir_x86_32 - from miasm2.ir.symbexec import symbexec + from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.ir.ir import AssignBlock addrX = ExprInt32(-1) @@ -35,10 +35,10 @@ class TestSymbExec(unittest.TestCase): id_a = ExprId('a') id_eax = ExprId('eax_init') - e = symbexec(ir_x86_32(), - {mem0: id_x, mem1: id_y, mem9: id_x, - mem40w: id_x[:16], mem50v: id_y, - id_a: addr0, id_eax: addr0}) + e = SymbolicExecutionEngine(ir_x86_32(), + {mem0: id_x, mem1: id_y, mem9: id_x, + mem40w: id_x[:16], mem50v: id_y, + id_a: addr0, id_eax: addr0}) self.assertEqual(e.find_mem_by_addr(addr0), mem0) self.assertEqual(e.find_mem_by_addr(addrX), None) self.assertEqual(e.eval_expr(ExprMem(addr1 - addr1)), id_x) diff --git a/test/ir/translators/z3_ir.py b/test/ir/translators/z3_ir.py index 5fcfe25e..0251c2fe 100644 --- a/test/ir/translators/z3_ir.py +++ b/test/ir/translators/z3_ir.py @@ -1,6 +1,6 @@ import z3 -from miasm2.core.asmbloc import asm_label +from miasm2.core.asmblock import AsmLabel from miasm2.expression.expression import * from miasm2.ir.translators.translator import Translator from miasm2.ir.translators.z3_ir import Z3Mem @@ -139,13 +139,13 @@ for miasm_int, res in [(five, -5), (four, -4)]: assert equiv(ez3, z3_e6) # -------------------------------------------------------------------------- -e7 = ExprId(asm_label("label_histoire", 0xdeadbeef), 32) +e7 = ExprId(AsmLabel("label_histoire", 0xdeadbeef), 32) ez3 = Translator.to_language('z3').from_expr(e7) z3_e7 = z3.BitVecVal(0xdeadbeef, 32) assert equiv(ez3, z3_e7) # Should just not throw anything to pass -e8 = ExprId(asm_label("label_jambe"), 32) +e8 = ExprId(AsmLabel("label_jambe"), 32) ez3 = Translator.to_language('z3').from_expr(e8) assert not equiv(ez3, z3_e7) diff --git a/test/test_all.py b/test/test_all.py index 0c9a0c08..4f3ea760 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -230,7 +230,7 @@ for script in ["interval.py", "test_types.py", ]: testset += RegressionTest([script], base_dir="core") -testset += RegressionTest(["asmbloc.py"], base_dir="core", +testset += RegressionTest(["asmblock.py"], base_dir="core", products=["graph.dot", "graph2.dot", "graph3.dot", "graph4.dot"]) ## Expression |