Package org.jakstab.analysis.explicit

Source Code of org.jakstab.analysis.explicit.BoundedAddressTracking

/*
* BoundedAddressTracking.java - This file is part of the Jakstab project.
* Copyright 2007-2012 Johannes Kinder <jk@jakstab.org>
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
*/

package org.jakstab.analysis.explicit;

import java.util.*;

import org.jakstab.AnalysisProperties;
import org.jakstab.JOption;
import org.jakstab.Program;
import org.jakstab.analysis.*;
import org.jakstab.asm.AbsoluteAddress;
import org.jakstab.asm.x86.X86Instruction;
import org.jakstab.cfa.CFAEdge;
import org.jakstab.cfa.Location;
import org.jakstab.cfa.StateTransformer;
import org.jakstab.rtl.expressions.ExpressionFactory;
import org.jakstab.rtl.expressions.RTLVariable;
import org.jakstab.rtl.statements.RTLStatement;
import org.jakstab.util.*;
import org.jakstab.util.MapMap.EntryIterator;

import com.google.common.collect.*;

/**
* @author Johannes Kinder
*/
public class BoundedAddressTracking implements ConfigurableProgramAnalysis {

  @SuppressWarnings("unused")
  private final static Logger logger = Logger.getLogger(BoundedAddressTracking.class);

  public static void register(AnalysisProperties p) {
    p.setShortHand('x');
    p.setName("Bounded Address Tracking");
    p.setDescription("Enumerate region-based addresses up to a bound per variable per location.");
    p.setExplicit(true);
  }
 
  public static JOption<Integer> varThreshold = JOption.create("explicit-threshold", "k", 5, "Set the maximum number of values tracked per variable per location.");
  public static JOption<Integer> heapThreshold = JOption.create("heap-threshold", "k", 5, "Explicit threshold for data stored on the heap.");
  public static JOption<Boolean> repPrecBoost = JOption.create("rep-prec-boost", "Increase precision for rep-prefixed instructions.");
  public static JOption<Boolean> keepDeadStack = JOption.create("keep-dead-stack", "Do not discard stack contents below current stack pointer.");
 
  public BoundedAddressTracking() {
  }

  @Override
  public AbstractState merge(AbstractState s1, AbstractState s2, Precision precision) {
    // Reduces states, but makes it harder to reconstruct the trace that lead to a certain state
    if (s2.lessOrEqual(s1)) return s1;
    return CPAOperators.mergeSep(s1, s2, precision);
  }

  @Override
  public boolean stop(AbstractState s, ReachedSet reached, Precision precision) {
    return CPAOperators.stopSep(s, reached, precision);
  }

  @Override
  public Set<AbstractState> post(AbstractState state, CFAEdge cfaEdge, Precision precision) {
    return ((BasedNumberValuation)state).abstractPost((RTLStatement)cfaEdge.getTransformer(), precision);
  }
 
  @Override
  public AbstractState strengthen(AbstractState s, Iterable<AbstractState> otherStates,
      CFAEdge cfaEdge, Precision precision) {
    return s;
  }

  @Override
  public Pair<AbstractState, Precision> prec(AbstractState s, Precision precision, ReachedSet reached) {
   
    // This method uses the fact that there is only 1 precision per location
   
    ExplicitPrecision eprec = (ExplicitPrecision)precision;
    BasedNumberValuation widenedState = (BasedNumberValuation)s;

    // Only check value counts if we have at least enough states to reach it
    if (reached.size() > Math.min(varThreshold.getValue(), heapThreshold.getValue())) {
     
      boolean changed = false;

      // Check value counts for variables
      for (RTLVariable v : eprec.varMap.keySet()) {
        //BasedNumberElement currentValue = ((BasedNumberValuation)s).getValue(v);
        Set<BasedNumberElement> existingValues = eprec.varMap.get(v);
        int threshold = eprec.getThreshold(v);
        if (existingValues.size() > threshold) {
          // Lower precisions and widen the value in this state, too.
          // This avoids values accumulating at join points (where they are not
          // intercepted by the precision-aware setValue)
          if (countRegions(existingValues) > threshold) {
            eprec.stopTracking(v);
            if (!changed) {
              widenedState = new BasedNumberValuation(widenedState);
              changed = true;
            }
            widenedState.setValue(v, BasedNumberElement.getTop(v.getBitWidth()));
          } else {
            eprec.trackRegionOnly(v);
            if (!changed) {
              widenedState = new BasedNumberValuation(widenedState);
              changed = true;
            }
            logger.debug("Only tracking region of " + v + ", values were " + existingValues);
            widenedState.setValue(v, new BasedNumberElement(
                widenedState.getValue(v).getRegion(),
                NumberElement.getTop(v.getBitWidth())));
          }
        }
      }

     
      // Check value counts for store
      PartitionedMemory<BasedNumberElement> sStore = ((BasedNumberValuation)s).getStore();
      for (EntryIterator<MemoryRegion, Long, BasedNumberElement> entryIt = sStore.entryIterator(); entryIt.hasEntry(); entryIt.next()) {
        MemoryRegion region = entryIt.getLeftKey();
        Long offset = entryIt.getRightKey();
        BasedNumberElement value = entryIt.getValue();
        SetMultimap<Long, BasedNumberElement> memoryMap = eprec.regionMaps.get(region);
        if (memoryMap == null) continue;
       
        //BasedNumberElement currentValue = entry.getValue();
        Set<BasedNumberElement> existingValues = memoryMap.get(offset);

        int threshold = eprec.getStoreThreshold(region, offset);
        if (existingValues.size() > threshold) {
          if (countRegions(existingValues) > 5*threshold) {
            eprec.stopTracking(region, offset);
            if (!changed) {
              widenedState = new BasedNumberValuation(widenedState);
              changed = true;
            }
            widenedState.getStore().set(region,
                offset, value.getBitWidth(),
                BasedNumberElement.getTop(value.getBitWidth()));
          } else {
            eprec.trackRegionOnly(region, offset);
            if (!changed) {
              widenedState = new BasedNumberValuation(widenedState);
              changed = true;
            }
            widenedState.getStore().set(region, offset, value.getBitWidth(),
                new BasedNumberElement(value.getRegion(), NumberElement.getTop(value.getBitWidth())));
          }
        }
      }
    }
   
    // Collect all values for all variables
    for (Map.Entry<RTLVariable, BasedNumberElement> entry : widenedState.getVariableValuation()) {
      eprec.varMap.put(entry.getKey(), entry.getValue());
    }

    // Collect all values for all memory areas
    PartitionedMemory<BasedNumberElement> store = widenedState.getStore();
    for (EntryIterator<MemoryRegion, Long, BasedNumberElement> entryIt = store.entryIterator(); entryIt.hasEntry(); entryIt.next()) {
      SetMultimap<Long, BasedNumberElement> memoryMap = eprec.regionMaps.get(entryIt.getLeftKey());
      if (memoryMap == null) {
        memoryMap = HashMultimap.create();
        eprec.regionMaps.put(entryIt.getLeftKey(), memoryMap);
      }
      memoryMap.put(entryIt.getRightKey(), entryIt.getValue());
    }


    // If it was changed, widenedState is now a new state
    return Pair.create((AbstractState)widenedState, precision);
  }

  @Override
  public AbstractState initStartState(Location label) {
    return BasedNumberValuation.createInitialState();
  }

  @Override
  public Precision initPrecision(Location location, StateTransformer transformer) {
    ExplicitPrecision p = new ExplicitPrecision(varThreshold.getValue());
   
    // Increase precision of ecx, esi, edi for REP prefixed instructions
    Program program = Program.getProgram();
    if (BoundedAddressTracking.repPrecBoost.getValue()) {
      AbsoluteAddress addr = location.getAddress();
      X86Instruction instr = (X86Instruction)program.getInstruction(addr);
      if (instr != null && (instr.hasPrefixREPZ() || instr.hasPrefixREPNZ())) {
        logger.debug("boost-rep: REP instruction at " + location + ", increasing precision of loop registers.");
        p.setThreshold(ExpressionFactory.createVariable("%ecx"), 1000);
        p.setThreshold(ExpressionFactory.createVariable("%esi"), 1000);
        p.setThreshold(ExpressionFactory.createVariable("%edi"), 1000);
      }
    }
   
    return p;
  }
 
  private int countRegions(Set<BasedNumberElement> values) {
    Set<MemoryRegion> regions = new HashSet<MemoryRegion>();
    for (BasedNumberElement e : values)
      regions.add(e.getRegion());
    return regions.size();
  }

}
TOP

Related Classes of org.jakstab.analysis.explicit.BoundedAddressTracking

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.