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

qilin.stat.CallGraphStat Maven / Gradle / Ivy

/* Qilin - a Java Pointer Analysis Framework
 * Copyright (C) 2021-2030 Qilin developers
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3.0 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 */

package qilin.stat;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import qilin.CoreConfig;
import qilin.core.PTA;
import qilin.core.PTAScene;
import qilin.core.builder.FakeMainFactory;
import qilin.core.builder.callgraph.Edge;
import qilin.core.builder.callgraph.OnFlyCallGraph;
import qilin.core.pag.ContextMethod;
import qilin.core.pag.ContextVarNode;
import qilin.core.pag.LocalVarNode;
import sootup.core.model.SootClass;
import sootup.core.model.SootMethod;

public class CallGraphStat implements AbstractStat {
  private final PTA pta;

  private final Set reachableMethods = new HashSet<>();
  private int reachableStatic = 0;
  private final Set reachableParameterizedMethods = new HashSet<>();
  private final Set reachableAppParameterizedMethods = new HashSet<>();
  private final Set reachableAppMethods = new HashSet<>();
  private int reachableAppStatic = 0;
  private int CSCallEdges = 0;
  private int CSStaticToStatic = 0;
  private int CSStaticToInstance = 0;
  private int CSInstanceToStatic = 0;
  private int CSInstancetoInstance = 0;
  private int CSApp2lib = 0;
  private int CSApp2app = 0;
  private int CSLib2lib = 0;
  private int CSLib2app = 0;
  private int CICallEdges = 0;
  private int CIApp2lib = 0;
  private int CIApp2app = 0;
  private int CILib2lib = 0;
  private int CILib2app = 0;
  private int CIStaticToStatic = 0;
  private int CIStaticToInstance = 0;
  private int CIInstanceToStatic = 0;
  private int CIInstancetoInstance = 0;
  private int allMethods = 0;

  public CallGraphStat(PTA pta) {
    this.pta = pta;
    init();
  }

  private void init() {
    // stat method numbers
    Collection clazzs = pta.getView().getClasses();
    for (SootClass clazz : clazzs) {
      allMethods += clazz.getMethods().size();
    }
    //
    OnFlyCallGraph csCallGraph = pta.getCgb().getCallGraph();
    CSCallEdges = csCallGraph.size();
    PTAScene scene = pta.getScene();
    for (final ContextMethod momc : pta.getCgb().getReachableMethods()) {
      final SootMethod m = momc.method();
      boolean toApp = scene.isApplicationMethod(m);
      reachableParameterizedMethods.add(momc);
      reachableMethods.add(m);
      //      if (m.toString().equals("")) {
      //        System.out.println(PTAUtils.getMethodBody(m));
      //      }

      if (toApp) {
        reachableAppParameterizedMethods.add(momc);
        reachableAppMethods.add(momc.method());
      }

      for (Iterator iterator = csCallGraph.edgesInto(momc); iterator.hasNext(); ) {
        Edge e = iterator.next();
        final SootMethod srcm = e.getSrc().method();
        boolean fromApp = scene.isApplicationMethod(srcm);
        if (fromApp && toApp) {
          CSApp2app++;
        } else if (fromApp) {
          CSApp2lib++;
        } else if (!toApp) {
          CSLib2lib++;
        } else {
          CSLib2app++;
        }
        if (e.src().isStatic()) {
          if (e.isStatic()) {
            CSStaticToStatic++;
          } else {
            CSStaticToInstance++;
          }
        } else if (e.isStatic()) {
          CSInstanceToStatic++;
        } else {
          CSInstancetoInstance++;
        }
      }
    }
    OnFlyCallGraph ciCallGraph = pta.getCallGraph();
    CICallEdges = ciCallGraph.size();
    for (SootMethod sm : reachableMethods) {
      boolean toApp = scene.isApplicationMethod(sm);
      if (sm.isStatic()) {
        reachableStatic++;
        if (toApp) {
          reachableAppStatic++;
        }
      }
      for (Iterator iterator =
              ciCallGraph.edgesInto(new ContextMethod(sm, pta.emptyContext()));
          iterator.hasNext(); ) {
        Edge e = iterator.next();
        final SootMethod srcm = e.getSrc().method();
        boolean fromApp = scene.isApplicationMethod(srcm);
        if (fromApp && toApp) {
          CIApp2app++;
        } else if (fromApp) {
          CIApp2lib++;
        } else if (!toApp) {
          CILib2lib++;
        } else {
          CILib2app++;
        }

        if (e.src().isStatic()) {
          if (e.isStatic()) {
            CIStaticToStatic++;
          } else {
            CIStaticToInstance++;
          }
        } else if (e.isStatic()) {
          CIInstanceToStatic++;
        } else {
          CIInstancetoInstance++;
        }
      }
    }
  }

  private long thisReceiverCount() {
    return pta.getCgb().getReceiverToSitesMap().entrySet().stream()
        .filter(e -> e.getKey() instanceof ContextVarNode)
        .filter(e -> e.getKey().base() instanceof LocalVarNode)
        .filter(e -> ((LocalVarNode) e.getKey().base()).isThis())
        .count();
  }

  @Override
  public void export(Exporter exporter) {
    exporter.collectMetric("#Method (Static):", String.valueOf(allMethods - 1)); // -fakeMain
    exporter.collectMetric(
        "#Reachable Method (CI):", String.valueOf(reachableMethods.size() - 1)); // -fakeMain
    exporter.collectMetric(
        "\t#Reachable-Static Method (CI):", String.valueOf(reachableStatic - 1)); // -fakeMain
    exporter.collectMetric(
        "#Reachable Method (CS):",
        String.valueOf(reachableParameterizedMethods.size() - 1)); // -fakeMain
    exporter.collectMetric(
        "#Reachable App Method (CI):", String.valueOf(reachableAppMethods.size()));
    exporter.collectMetric(
        "\t#Reachable-App-Static Method (CI):", String.valueOf(reachableAppStatic));
    exporter.collectMetric(
        "#Reachable App Method (CS):", String.valueOf(reachableAppParameterizedMethods.size()));
    exporter.collectMetric(
        "#Call Edge(CI):", String.valueOf(CICallEdges - FakeMainFactory.implicitCallEdges));
    exporter.collectMetric(
        "\t#Static-Static Call Edge(CI):",
        String.valueOf(CIStaticToStatic - FakeMainFactory.implicitCallEdges));
    exporter.collectMetric("\t#Static-Instance Call Edge(CI):", String.valueOf(CIStaticToInstance));
    exporter.collectMetric("\t#Instance-Static Call Edge(CI):", String.valueOf(CIInstanceToStatic));
    exporter.collectMetric(
        "\t#Instance-Instance Call Edge(CI):", String.valueOf(CIInstancetoInstance));
    exporter.collectMetric("\t#Application-Application Call Edge(CI):", String.valueOf(CIApp2app));
    exporter.collectMetric("\t#Application-Library Call Edge(CI):", String.valueOf(CIApp2lib));
    exporter.collectMetric("\t#Library-Application Call Edge(CI):", String.valueOf(CILib2app));
    exporter.collectMetric("\t#Library-Library Call Edge(CI):", String.valueOf(CILib2lib));
    exporter.collectMetric(
        "#Call Edge(CS):", String.valueOf(CSCallEdges - FakeMainFactory.implicitCallEdges));
    exporter.collectMetric(
        "\t#Static-Static Call Edge(CS):",
        String.valueOf(CSStaticToStatic - FakeMainFactory.implicitCallEdges));
    exporter.collectMetric("\t#Static-Instance Call Edge(CS):", String.valueOf(CSStaticToInstance));
    exporter.collectMetric("\t#Instance-Static Call Edge(CS):", String.valueOf(CSInstanceToStatic));
    exporter.collectMetric(
        "\t#Instance-Instance Call Edge(CS):", String.valueOf(CSInstancetoInstance));
    exporter.collectMetric("\t#Application-Application Call Edge(CS):", String.valueOf(CSApp2app));
    exporter.collectMetric("\t#Application-Library Call Edge(CS):", String.valueOf(CSApp2lib));
    exporter.collectMetric("\t#Library-Application Call Edge(CS):", String.valueOf(CSLib2app));
    exporter.collectMetric("\t#Library-Library Call Edge(CS):", String.valueOf(CSLib2lib));
    exporter.collectMetric(
        "#receivers:", String.valueOf(pta.getCgb().getReceiverToSitesMap().size()));
    exporter.collectMetric("\t#thisreceivers:", String.valueOf(thisReceiverCount()));
    exporter.collectMetric(
        "#avg p2s size for virtualcalls:",
        String.valueOf(
            (CSCallEdges - CSStaticToStatic - CSInstanceToStatic)
                * 1.0
                / pta.getCgb().getReceiverToSitesMap().size()));
    if (CoreConfig.v().getOutConfig().dumpStats) {
      exporter.dumpReachableMethods(reachableMethods);
      exporter.dumpAppReachableMethods(reachableAppMethods);
      exporter.dumpInsensCallGraph(pta.getCallGraph());
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy