def set_input(trace, inbufs): inbufs = set(inbufs) for i, te in trace: uses_set = set(uses(te)) if uses_set & inbufs: defs = defines(te) assert len(defs) == 1 te.op = "IFLO_SET_INPUT" te.args = [defs[0], 0]
def multislice(insns, worklist, output_track=False, debug=False): wlist = worklist[:] wlist.sort() start, bufs = wlist.pop() if wlist: next_i, next_bufs = wlist.pop() else: next_i = -1 if start == -1: start = len(insns) - 1 if output_track: outbufs = set(bufs) if not quiet: widgets = ['Slicing: ', Percentage(), ' ', Bar(marker=RotatingMarker()), ' ', ETA()] pbar = ProgressBar(widgets=widgets, maxval=start+1).start() work = set(bufs) if debug: print "Initial working set:", work for i in range(start, -1, -1): #print "Examining instruction",i,"(working set: %d)" % len(work) if not quiet: pbar.update(start-i+1) insn = insns[i] if i == next_i: work |= set(next_bufs) if wlist: next_i, next_bufs = wlist.pop() defs_set = set(defines(insn)) uses_set = set(uses(insn)) if debug: print repr(insn) if defs_set & work: if debug: print "Overlap with working set: %s" % (defs_set & work) work -= defs_set work |= uses_set if debug: print "Adding to slice: %s" % repr(insn) if debug: print "Current WS:", work # TODO: allow multiple outputs by separating outbufs into # a dict of (label => memrange) pairs if output_track and defs_set & outbufs: if debug: print "Accounted for %d of %d output bytes" % (len(defs_set & outbufs), len(outbufs)) if debug: print "Instruction: %s" % repr(insn) outbufs -= defs_set insn.set_output_label("out") insn.mark() if debug: print "Working set at end:", work
def dynslice(insns, bufs, start=-1, output_track=False, debug=False): """Perform a dynamic data slice. Perform a dynamic data slice of a trace with respect to a set of buffers. This is basically the algorithm described in the K-Tracer paper. insns: a list of tuples: (index, TraceEntry) bufs: a list of outputs to be tracked start: an optional point in the trace at which to begin analysis. By default, analysis begins at the last instruction in the trace. ouput_track: mark instructions that define data in the output set. This calls TraceEntry.set_output_label(). debug: enable debugging information Returns: a list of tuples: (index, TraceEntry) """ if start == -1: start = len(insns) - 1 if output_track: outbufs = set(bufs) work = set(bufs) slice = [] for i, insn in reversed(insns[:start + 1]): defs_set = set(defines(insn)) uses_set = set(uses(insn)) if debug: print repr(insn) if defs_set & work: if debug: print "Overlap with working set: %s" % (defs_set & work) work = (work - defs_set) | uses_set if debug: print "Adding to slice: %s" % repr(insn) # TODO: allow multiple outputs by separating outbufs into # a dict of (label => memrange) pairs if output_track and defs_set & outbufs: outbufs -= defs_set insn.set_output_label("out") slice.insert(0, (i, insn)) if debug: print "Working set at end:", work return slice
def linked_vars(insns, sink, source, start=-1, end=0, debug=False): if debug: print "Linking vars sink: %s source: %s between trace positions %d and %d" % (sink, source, end, start) if start == -1: start = len(insns) - 1 work = set([sink]) for i,insn in reversed(insns[end:start+1]): defs_set = set(defines(insn)) uses_set = set(uses(insn)) # For this one special case we DON'T want to track # the derivation of the address of a buffer. if is_memop(insn): uses_set -= set(["A0"]) if defs_set & work: work = (work - defs_set) | uses_set if debug: print i,repr(insn) if debug: print "Working set at end:", work return source in work
def linked_vars(insns, sink, source, start=-1, end=0, debug=False): if debug: print "Linking vars sink: %s source: %s between trace positions %d and %d" % ( sink, source, end, start) if start == -1: start = len(insns) - 1 work = set([sink]) for i, insn in reversed(insns[end:start + 1]): defs_set = set(defines(insn)) uses_set = set(uses(insn)) # For this one special case we DON'T want to track # the derivation of the address of a buffer. if is_memop(insn): uses_set -= set(["A0"]) if defs_set & work: work = (work - defs_set) | uses_set if debug: print i, repr(insn) if debug: print "Working set at end:", work return source in work
for i in xrange(len(trace) - 1, -1, -1): idx, insn = trace[i] if (insn.op == 'IFLO_OPS_MEM_LDL_T0_A0' or insn.op == 'IFLO_OPS_MEM_LDL_T1_A0'): memb_addr = insn.args[1] memb_val = insn.args[2] #print "Pointer dereference => Read 4 bytes at %#x = %#x" % (memb_addr,memb_val) # Tiny version of dynamic slicing -- track A0 until it comes from somewhere else j = i work = set(['A0']) slice = [] while True: j -= 1 _, trcent = trace[j] defs_set = set(defines(trcent)) uses_set = set(uses(trcent)) if defs_set & work: work = (work - defs_set) | uses_set slice.append((j, trcent)) if 'A0' not in work: break valid = False objbase = UInt(memb_addr) for i, s in slice[:-1]: if s.op == "IFLO_ADDL_A0_IM": objbase -= UInt(s.args[0]) elif s.op == "IFLO_ADDL_A0_SEG": pass elif s.op == "IFLO_MOVL_A0_IM": objbase -= UInt(s.args[0])
for i in xrange(len(trace)-1,-1,-1): idx, insn = trace[i] if (insn.op == 'IFLO_OPS_MEM_LDL_T0_A0' or insn.op == 'IFLO_OPS_MEM_LDL_T1_A0'): memb_addr = insn.args[1] memb_val = insn.args[2] #print "Pointer dereference => Read 4 bytes at %#x = %#x" % (memb_addr,memb_val) # Tiny version of dynamic slicing -- track A0 until it comes from somewhere else j = i work = set(['A0']) slice = [] while True: j -= 1 _ , trcent = trace[j] defs_set = set(defines(trcent)) uses_set = set(uses(trcent)) if defs_set & work: work = (work - defs_set) | uses_set slice.append((j,trcent)) if 'A0' not in work: break valid = False objbase = UInt(memb_addr) for i,s in slice[:-1]: if s.op == "IFLO_ADDL_A0_IM": objbase -= UInt(s.args[0]) elif s.op == "IFLO_ADDL_A0_SEG": pass elif s.op == "IFLO_MOVL_A0_IM": objbase -= UInt(s.args[0])