All Downloads are FREE. Search and download functionalities are using the official Maven repository.

aliasing.SparseAliasManager Maven / Gradle / Ivy

The newest version!
package aliasing;

import boomerang.BackwardQuery;
import boomerang.Boomerang;
import boomerang.DefaultBoomerangOptions;
import boomerang.results.BackwardBoomerangResults;
import boomerang.scene.*;
import boomerang.scene.jimple.*;
import boomerang.scene.sparse.SparseCFGCache;
import boomerang.util.AccessPath;
import com.google.common.base.Stopwatch;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.ExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import soot.*;
import soot.jimple.Stmt;
import wpds.impl.Weight;

public class SparseAliasManager {

  private static Logger log = LoggerFactory.getLogger(SparseAliasManager.class);

  private static SparseAliasManager INSTANCE;

  private LoadingCache> queryCache;

  private Boomerang boomerangSolver;

  private SootCallGraph sootCallGraph;
  private DataFlowScope dataFlowScope;

  private boolean disableAliasing = false;
  private SparseCFGCache.SparsificationStrategy sparsificationStrategy;
  private boolean ignoreAfterQuery;

  static class BoomerangOptions extends DefaultBoomerangOptions {

    private SparseCFGCache.SparsificationStrategy sparsificationStrategy;
    private boolean ignoreAfterQuery;

    public BoomerangOptions(
        SparseCFGCache.SparsificationStrategy sparsificationStrategy, boolean ignoreAfterQuery) {
      this.sparsificationStrategy = sparsificationStrategy;
      this.ignoreAfterQuery = ignoreAfterQuery;
    }

    @Override
    public SparseCFGCache.SparsificationStrategy getSparsificationStrategy() {
      if (this.sparsificationStrategy == null) {
        return SparseCFGCache.SparsificationStrategy.NONE;
      }
      return this.sparsificationStrategy;
    }

    @Override
    public boolean ignoreSparsificationAfterQuery() {
      return this.ignoreAfterQuery;
    }

    @Override
    public int analysisTimeoutMS() {
      return Integer.MAX_VALUE;
    }

    @Override
    public boolean onTheFlyCallGraph() {
      return false;
    }

    @Override
    public StaticFieldStrategy getStaticFieldStrategy() {
      return StaticFieldStrategy.FLOW_SENSITIVE;
    }

    @Override
    public boolean allowMultipleQueries() {
      return true;
    }

    @Override
    public boolean throwFlows() {
      return true;
    }

    @Override
    public boolean trackAnySubclassOfThrowable() {
      return true;
    }
  }

  private static Duration totalAliasingDuration;

  private SparseAliasManager(
      SparseCFGCache.SparsificationStrategy sparsificationStrategy, boolean ignoreAfterQuery) {
    this.sparsificationStrategy = sparsificationStrategy;
    this.ignoreAfterQuery = ignoreAfterQuery;
    totalAliasingDuration = Duration.ZERO;
    sootCallGraph = new SootCallGraph();
    dataFlowScope = SootDataFlowScope.make(Scene.v());
    setupQueryCache();
  }

  public static Duration getTotalDuration() {
    return totalAliasingDuration;
  }

  public static synchronized SparseAliasManager getInstance(
      SparseCFGCache.SparsificationStrategy sparsificationStrategy, boolean ignoreAfterQuery) {
    if (INSTANCE == null
        || INSTANCE.sparsificationStrategy != sparsificationStrategy
        || INSTANCE.ignoreAfterQuery != ignoreAfterQuery) {
      INSTANCE = new SparseAliasManager(sparsificationStrategy, ignoreAfterQuery);
    }
    return INSTANCE;
  }

  private void setupQueryCache() {
    queryCache =
        CacheBuilder.newBuilder()
            .build(
                new CacheLoader>() {
                  @Override
                  public Set load(BackwardQuery query) throws Exception {
                    Set aliases = queryCache.getIfPresent(query);
                    if (aliases == null) {
                      boomerangSolver =
                          new Boomerang(
                              sootCallGraph,
                              dataFlowScope,
                              new BoomerangOptions(
                                  INSTANCE.sparsificationStrategy, INSTANCE.ignoreAfterQuery));
                      BackwardBoomerangResults results =
                          boomerangSolver.solve(query);
                      aliases = results.getAllAliases();
                      boolean debug = false;
                      if (debug) {
                        System.out.println(query);
                        System.out.println("alloc:" + results.getAllocationSites());
                        System.out.println("aliases:" + aliases);
                      } // boomerangSolver.unregisterAllListeners();
                      // boomerangSolver.unregisterAllListeners();
                      queryCache.put(query, aliases);
                    }
                    return aliases;
                  }
                });
  }

  /**
   * @param stmt Statement that contains the value. E.g. Value can be the leftOp
   * @param method Method that contains the Stmt
   * @param value We actually want to find this local's aliases
   * @return
   */
  public synchronized Set getAliases(Stmt stmt, SootMethod method, Value value) {
    // log.info(method.getActiveBody().toString());
    // log.info("getAliases call for: " + stmt + " in " + method);
    if (disableAliasing) {
      return Collections.emptySet();
    }
    Stopwatch stopwatch = Stopwatch.createStarted();
    BackwardQuery query = createQuery(stmt, method, value);
    Set aliases = getAliases(query);
    Duration elapsed = stopwatch.elapsed();
    totalAliasingDuration = totalAliasingDuration.plus(elapsed);
    return aliases;
  }

  private BackwardQuery createQuery(Stmt stmt, SootMethod method, Value value) {
    JimpleMethod jimpleMethod = JimpleMethod.of(method);
    Statement statement = JimpleStatement.create(stmt, jimpleMethod);
    JimpleVal val = new JimpleVal(value, jimpleMethod);
    Optional first =
        statement.getMethod().getControlFlowGraph().getSuccsOf(statement).stream().findFirst();
    if (first.isPresent()) {
      return BackwardQuery.make(new ControlFlowGraph.Edge(statement, first.get()), val);
    }
    throw new RuntimeException("No successors for: " + statement);
  }

  private Set getAliases(BackwardQuery query) {
    try {
      return queryCache.get(query);
    } catch (ExecutionException e) {
      e.printStackTrace();
    }
    return Collections.emptySet();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy