/****************************************************************************** * Copyright (c) 2002 - 2016 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Brian Pfretzschner - initial implementation *****************************************************************************/ package com.ibm.wala.cast.js.nodejs; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Collections; import com.ibm.wala.cast.ipa.callgraph.CAstAnalysisScope; import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil; import com.ibm.wala.cast.ipa.callgraph.StandardFunctionTargetSelector; import com.ibm.wala.cast.ir.ssa.AstIRFactory; import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions; import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder; import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil; import com.ibm.wala.cast.js.ipa.callgraph.JSZeroOrOneXCFABuilder; import com.ibm.wala.cast.js.ipa.callgraph.JavaScriptEntryPoints; import com.ibm.wala.cast.js.ipa.callgraph.PropertyNameContextSelector; import com.ibm.wala.cast.js.loader.JavaScriptLoader; import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory; import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory; import com.ibm.wala.cast.js.translator.JavaScriptTranslatorFactory; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.classLoader.Language; import com.ibm.wala.classLoader.Module; import com.ibm.wala.classLoader.SourceFileModule; import com.ibm.wala.ipa.callgraph.AnalysisCacheImpl; import com.ibm.wala.ipa.callgraph.ContextSelector; import com.ibm.wala.ipa.callgraph.Entrypoint; import com.ibm.wala.ipa.callgraph.IAnalysisCacheView; import com.ibm.wala.ipa.callgraph.MethodTargetSelector; import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder; import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys; import com.ibm.wala.ipa.cha.ClassHierarchyFactory; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ssa.IRFactory; import com.ibm.wala.util.WalaException; /** * @author Brian Pfretzschner <brian.pfretzschner@gmail.com> */ public class NodejsCallGraphBuilderUtil extends JSCallGraphUtil { public static PropagationCallGraphBuilder makeCGBuilder(File mainFile) throws IOException, IllegalArgumentException, WalaException { return makeCGBuilder(mainFile.getParentFile(), mainFile); } public static PropagationCallGraphBuilder makeCGBuilder(File workingDir, File mainFile) throws IOException, IllegalArgumentException, WalaException { JavaScriptTranslatorFactory translatorFactory = new CAstRhinoTranslatorFactory(); JSCallGraphUtil.setTranslatorFactory(translatorFactory); Language language = JavaScriptLoader.JS; Collection languages = Collections.singleton(language); IRFactory irFactory = new AstIRFactory.AstDefaultIRFactory<>(); IAnalysisCacheView cache = new AnalysisCacheImpl(irFactory); JavaScriptLoaderFactory loaders = new JavaScriptLoaderFactory(translatorFactory, null); SourceFileModule mainSourceModule = CAstCallGraphUtil.makeSourceModule(mainFile.toURI().toURL(), mainFile.getName()); String mainFileClassName = NodejsRequiredSourceModule.convertFileToClassName(workingDir, mainFile); Module[] files = new Module[] { JSCallGraphUtil.getPrologueFile("prologue.js"), JSCallGraphUtil.getPrologueFile("extended-prologue.js"), new NodejsRequiredSourceModule(mainFileClassName, mainFile, mainSourceModule) }; CAstAnalysisScope scope = new CAstAnalysisScope(files, loaders, languages); IClassHierarchy cha = ClassHierarchyFactory.make(scope, loaders, language, null); com.ibm.wala.cast.util.Util.checkForFrontEndErrors(cha); // Make Script Roots Iterable roots = new JavaScriptEntryPoints(cha, loaders.getTheLoader()); // Make Options JSAnalysisOptions options = new JSAnalysisOptions(scope, roots); options.setUseConstantSpecificKeys(true); options.setUseStacksForLexicalScoping(true); options.setHandleCallApply(true); // Important to be able to identify what file are required options.setTraceStringConstants(true); com.ibm.wala.ipa.callgraph.impl.Util.addDefaultSelectors(options, cha); MethodTargetSelector baseSelector = new StandardFunctionTargetSelector(cha, options.getMethodTargetSelector()); NodejsRequireTargetSelector requireTargetSelector = new NodejsRequireTargetSelector(workingDir, baseSelector); options.setSelector(requireTargetSelector); JSCFABuilder builder = new JSZeroOrOneXCFABuilder(cha, options, cache, null, null, ZeroXInstanceKeys.ALLOCATIONS, true); // A little hacky, but the instance of RequireTargetSelector is required to build the CallGraphBuilder // and the RequireTargetSelector also needs the CallGraphBuilder instance. requireTargetSelector.setCallGraphBuilder(builder); ContextSelector contextSelector = new PropertyNameContextSelector(cache, 2, builder.getContextSelector()); builder.setContextSelector(contextSelector); return builder; } }