Package org.jakstab.analysis.explicit

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

/*
* VpcTrackingAnalysis.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.HashSet;
import java.util.Map;
import java.util.Set;

import org.jakstab.AnalysisProperties;
import org.jakstab.JOption;
import org.jakstab.StatsTracker;
import org.jakstab.analysis.AbstractState;
import org.jakstab.analysis.CPAOperators;
import org.jakstab.analysis.ConfigurableProgramAnalysis;
import org.jakstab.analysis.MemoryRegion;
import org.jakstab.analysis.PartitionedMemory;
import org.jakstab.analysis.Precision;
import org.jakstab.analysis.ReachedSet;
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.Logger;
import org.jakstab.util.Pair;
import org.jakstab.util.MapMap.EntryIterator;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;

public class VpcTrackingAnalysis implements ConfigurableProgramAnalysis {
 
  private final static Logger logger = Logger.getLogger(VpcTrackingAnalysis.class);

  public static void register(AnalysisProperties p) {
    p.setShortHand('v');
    p.setName("BAT-VPC");
    p.setDescription("VPC-sensitive version of Bounded Address Tracking.");
    p.setExplicit(true);
  }
  public static JOption<String> vpcName = JOption.create("vpc", "r", "esi", "Register to be used as virtual program counter.");
 
  private RTLVariable vpc;
 
  public VpcTrackingAnalysis() {
    vpc = ExpressionFactory.createVariable(vpcName.getValue().toLowerCase());
    StatsTracker.getInstance().record("VPC", VpcTrackingAnalysis.vpcName.getValue());
    logger.debug("Using VPC " + vpc);
  }
 
  @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) {
    BasedNumberValuation b = (BasedNumberValuation)state;
    return ((BasedNumberValuation)state).abstractPost((RTLStatement)cfaEdge.getTransformer(), ((VpcPrecision)precision).getPrecision(b.getValue(vpc)));
  }
 
  @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
   
    VpcPrecision vprec = (VpcPrecision)precision;
    BasedNumberValuation widenedState = (BasedNumberValuation)s;
    ExplicitPrecision eprec = vprec.getPrecision(widenedState.getValue(vpc));

    // Only check value counts if we have at least enough states to reach it
    if (reached.size() > Math.min(BoundedAddressTracking.varThreshold.getValue(), BoundedAddressTracking.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) {
   
    return new VpcPrecision();
  }
 
  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.VpcTrackingAnalysis

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.