package jayhorn;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.log4j.Level;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import com.google.common.base.Stopwatch;
import jayhorn.checker.EldaricaChecker;
import jayhorn.checker.SpacerChecker;
import jayhorn.solver.ProverFactory;
import jayhorn.solver.princess.PrincessProverFactory;
import jayhorn.solver.spacer.SpacerProverFactory;
import jayhorn.utils.Stats;
import soottocfg.cfg.Program;
import soottocfg.soot.SootToCfg;
import soottocfg.soot.SootToCfg.MemModel;
public class Main {
private static String parseResult(String solver, boolean result)
{
if (result){
return "SAFE";
}else{
return "UNSAFE";
}
}
/**
* Safety Analysis with JayHorn
* @param options
* @param factory
*/
public static void safetyAnalysis(ProverFactory factory){
Log.info("Building CFG ... ");
SootToCfg soot2cfg = new SootToCfg();
soottocfg.Options.v().setBuiltInSpecs(Options.v().useSpecs);
soottocfg.Options.v().setResolveVirtualCalls(true);
soottocfg.Options.v().setMemModel(MemModel.PullPush);
if (Options.v().getOut()!=null) {
Path outDir = Paths.get(Options.v().getOut());
String in = Options.v().getJavaInput();
String outName = in.substring(in.lastIndexOf('/') + 1, in.length()).replace(".java", "").replace(".class", "");
soottocfg.Options.v().setOutDir(outDir);
soottocfg.Options.v().setOutBaseName(outName);
}
Stopwatch sootTocfgTimer = Stopwatch.createStarted();
soot2cfg.run(Options.v().getJavaInput(), Options.v().getClasspath());
Program program = soot2cfg.getProgram();
Stats.stats().add("SootToCFG", String.valueOf(sootTocfgTimer.stop()));
Log.info("Safety Verification ... ");
boolean result;
if ("spacer".equals(Options.v().getSolver())){
SpacerChecker spacer = new SpacerChecker(factory);
result = spacer.checkProgram(program);
} else{
EldaricaChecker eldarica = new EldaricaChecker(factory);
result = eldarica.checkProgram(program);
}
String prettyResult = parseResult(Options.v().getSolver(), result);
Stats.stats().add("FinalResult", prettyResult);
Log.info("Safety Result ... " + prettyResult);
if (Options.v().stats){ Stats.stats().printStats(); }
}
public static void main(String[] args) {
Options options = Options.v();
CmdLineParser parser = new CmdLineParser(options);
try {
// parse command-line arguments
parser.parseArgument(args);
options.updateSootToCfgOptions();
ProverFactory factory = null;
if ("spacer".equals(Options.v().getSolver())) {
factory = new SpacerProverFactory();
} else if ("eldarica".equals(Options.v().getSolver())) {
factory = new PrincessProverFactory();
} else {
throw new RuntimeException("Don't know solver " + Options.v().getSolver() + ". Using Eldarica instead.");
}
if (Options.v().verbose) Log.v().setLevel(Level.INFO);
Log.info("\t\t --- JAYHORN : Static Analayzer for Java Programs ---- ");
Log.info("\t Verification : " + Options.v().getChecker());
Log.info("\t Solver : " + Options.v().getSolver());
if ("safety".equals(Options.v().getChecker())) {
safetyAnalysis(factory);
} else {
Log.error(String.format("Checker %s is unknown", Options.v().getChecker()) );
}
} catch (CmdLineException e) {
Log.error(e.toString());
Log.error("java -jar jayhorn.jar [options...] -j [JAR, DIR]");
parser.printUsage(System.err);
} catch (Throwable t) {
Log.error(t.toString());
Stats.stats().add("Result", "UNKNOWN");
if (Options.v().stats){ Stats.stats().printStats(); }
throw t;
} finally {
Options.resetInstance();
soot.G.reset();
}
}
}