attempt to introduce tags and trunk
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@490 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
commit
df97f42b7e
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="dat"/>
|
||||
<classpathentry kind="src" path="lib"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.ibm.wala.core</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,12 @@
|
|||
#Mon Oct 02 08:58:10 EDT 2006
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
|
@ -0,0 +1,3 @@
|
|||
#Mon Oct 02 08:58:11 EDT 2006
|
||||
eclipse.preferences.version=1
|
||||
internal.default.compliance=default
|
|
@ -0,0 +1,68 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: WALA Core Plug-in
|
||||
Bundle-SymbolicName: com.ibm.wala.core
|
||||
Bundle-Version: 1.0.0
|
||||
Bundle-Activator: com.ibm.wala.core.plugin.CorePlugin
|
||||
Bundle-Vendor: IBM
|
||||
Bundle-Localization: plugin
|
||||
Require-Bundle: com.ibm.wala.emf;visibility:=reexport,
|
||||
com.ibm.wala.shrike;visibility:=reexport,
|
||||
org.eclipse.core.resources,
|
||||
org.eclipse.jface,
|
||||
org.eclipse.jdt.core
|
||||
Eclipse-LazyStart: true
|
||||
Export-Package: .,
|
||||
com.ibm.wala.analysis.pointers,
|
||||
com.ibm.wala.analysis.reflection,
|
||||
com.ibm.wala.analysis.stackMachine,
|
||||
com.ibm.wala.analysis.typeInference,
|
||||
com.ibm.wala.cfg,
|
||||
com.ibm.wala.cfg.cdg,
|
||||
com.ibm.wala.classLoader,
|
||||
com.ibm.wala.client,
|
||||
com.ibm.wala.client.impl,
|
||||
com.ibm.wala.core.plugin,
|
||||
com.ibm.wala.dataflow.IFDS,
|
||||
com.ibm.wala.dataflow.graph,
|
||||
com.ibm.wala.dataflow.ssa,
|
||||
com.ibm.wala.dynamic,
|
||||
com.ibm.wala.emf.wrappers,
|
||||
com.ibm.wala.escape,
|
||||
com.ibm.wala.fixedpoint.impl,
|
||||
com.ibm.wala.fixpoint,
|
||||
com.ibm.wala.ipa.callgraph,
|
||||
com.ibm.wala.ipa.callgraph.impl,
|
||||
com.ibm.wala.ipa.callgraph.propagation,
|
||||
com.ibm.wala.ipa.callgraph.propagation.cfa,
|
||||
com.ibm.wala.ipa.callgraph.propagation.rta,
|
||||
com.ibm.wala.ipa.cfg,
|
||||
com.ibm.wala.ipa.cha,
|
||||
com.ibm.wala.ipa.modref,
|
||||
com.ibm.wala.ipa.slicer,
|
||||
com.ibm.wala.ipa.summaries,
|
||||
com.ibm.wala.model,
|
||||
com.ibm.wala.model.java.lang,
|
||||
com.ibm.wala.properties,
|
||||
com.ibm.wala.ssa,
|
||||
com.ibm.wala.ssa.analysis,
|
||||
com.ibm.wala.types,
|
||||
com.ibm.wala.util,
|
||||
com.ibm.wala.util.bytecode,
|
||||
com.ibm.wala.util.collections,
|
||||
com.ibm.wala.util.config,
|
||||
com.ibm.wala.util.debug,
|
||||
com.ibm.wala.util.graph,
|
||||
com.ibm.wala.util.graph.impl,
|
||||
com.ibm.wala.util.graph.traverse,
|
||||
com.ibm.wala.util.heapTrace,
|
||||
com.ibm.wala.util.internationalization,
|
||||
com.ibm.wala.util.intset,
|
||||
com.ibm.wala.util.io,
|
||||
com.ibm.wala.util.logging,
|
||||
com.ibm.wala.util.math,
|
||||
com.ibm.wala.util.perf,
|
||||
com.ibm.wala.util.scope,
|
||||
com.ibm.wala.util.system,
|
||||
com.ibm.wala.util.warnings,
|
||||
com.ibm.wala.viz
|
|
@ -0,0 +1,13 @@
|
|||
bin.includes = lib/primordial.jar.model,\
|
||||
plugin.properties,\
|
||||
dat/J2SEClassHierarchyExclusions.xml,\
|
||||
dat/SyntheticJ2SEModel.xml,\
|
||||
dat/benign.xml,\
|
||||
dat/natives.xml,\
|
||||
META-INF/,\
|
||||
.
|
||||
jars.compile.order = .
|
||||
output.. = bin/
|
||||
source.. = dat/,\
|
||||
src/,\
|
||||
lib/
|
|
@ -0,0 +1,202 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="com.ibm.wala.core" default="build.jars" basedir=".">
|
||||
|
||||
<property name="basews" value="${ws}"/>
|
||||
<property name="baseos" value="${os}"/>
|
||||
<property name="basearch" value="${arch}"/>
|
||||
<property name="basenl" value="${nl}"/>
|
||||
|
||||
<!-- Compiler settings. -->
|
||||
<property name="javacFailOnError" value="true"/>
|
||||
<property name="javacDebugInfo" value="on"/>
|
||||
<property name="javacVerbose" value="false"/>
|
||||
<property name="logExtension" value=".log"/>
|
||||
<property name="compilerArg" value=""/>
|
||||
<property name="javacSource" value="1.5"/>
|
||||
<property name="javacTarget" value="1.5"/>
|
||||
<path id="path_bootclasspath">
|
||||
<fileset dir="${java.home}/lib">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
<property name="bootclasspath" refid="path_bootclasspath"/>
|
||||
<property name="bundleJavacSource" value="${javacSource}"/>
|
||||
<property name="bundleJavacTarget" value="${javacTarget}"/>
|
||||
<property name="bundleBootClasspath" value="${bootclasspath}"/>
|
||||
|
||||
<target name="init" depends="properties">
|
||||
<condition property="pluginTemp" value="${buildTempFolder}/plugins">
|
||||
<isset property="buildTempFolder"/>
|
||||
</condition>
|
||||
<property name="pluginTemp" value="${basedir}"/>
|
||||
<condition property="build.result.folder" value="${pluginTemp}/com.ibm.wala.core">
|
||||
<isset property="buildTempFolder"/>
|
||||
</condition>
|
||||
<property name="build.result.folder" value="${basedir}"/>
|
||||
<property name="temp.folder" value="${basedir}/temp.folder"/>
|
||||
<property name="plugin.destination" value="${basedir}/output"/>
|
||||
<property name="eclipse.root" value="c:/eclipse"/>
|
||||
</target>
|
||||
|
||||
<target name="properties" if="eclipse.running">
|
||||
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
|
||||
|
||||
</target>
|
||||
|
||||
<target name="build.update.jar" depends="init" description="Build the plug-in: com.ibm.wala.core for an update site.">
|
||||
<delete dir="${temp.folder}"/>
|
||||
<mkdir dir="${temp.folder}"/>
|
||||
<delete dir="${plugin.destination}"/>
|
||||
<mkdir dir="${plugin.destination}"/>
|
||||
<antcall target="build.jars"/>
|
||||
<antcall target="gather.bin.parts">
|
||||
<param name="destination.temp.folder" value="${temp.folder}/"/>
|
||||
</antcall>
|
||||
<copy todir="${temp.folder}/com.ibm.wala.core_1.0.0" failonerror="true" overwrite="false">
|
||||
<fileset dir="src/" includes="**/*.java" />
|
||||
</copy>
|
||||
<zip destfile="${plugin.destination}/com.ibm.wala.core_1.0.0.jar" basedir="${temp.folder}/com.ibm.wala.core_1.0.0" filesonly="false" whenempty="skip" update="false"/>
|
||||
<delete dir="${temp.folder}"/>
|
||||
</target>
|
||||
|
||||
<target name="@dot" depends="init" description="Create jar: com.ibm.wala.core @dot.">
|
||||
<delete dir="${temp.folder}/@dot.bin"/>
|
||||
<mkdir dir="${temp.folder}/@dot.bin"/>
|
||||
<path id="@dot.classpath">
|
||||
<pathelement path="../com.ibm.wala.emf/bin/"/>
|
||||
<pathelement path="../com.ibm.wala.emf/@dot"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.osgi_3.2.0.v20060601.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.equinox.common_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.jobs_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0.v20060603/runtime_registry_compatibility.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0.v20060603"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.equinox.registry_3.2.0.v20060601.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.apache.xerces_2.8.0.v200606131651/resolver.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.apache.xerces_2.8.0.v200606131651/xercesImpl.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.apache.xerces_2.8.0.v200606131651/xml-apis.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.equinox.preferences_3.2.0.v20060601.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0.v20060603/@dot"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.contenttype_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime.compatibility.auth_3.2.0.v20060601.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.emf.ecore_2.2.0.v200606271057.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.emf.common_2.2.0.v200606271057.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.resources_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.resources.compatibility_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.resources.win32_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime.compatibility_3.1.100.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.update.configurator_3.2.0.v20060605.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.ant.core_3.1.100.v20060531.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.variables_3.1.100.v20060605.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.expressions_3.2.0.v20060605-1400.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.filesystem_1.0.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.filesystem.win32.x86_1.0.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.emf.ecore.xmi_2.2.0.v200606271057.jar"/>
|
||||
<pathelement path="../com.ibm.wala.shrike/bin/"/>
|
||||
<pathelement path="../com.ibm.wala.shrike/@dot"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.jface_3.2.0.I20060605-1400.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.swt_3.2.0.v3232o.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.swt.win32.win32.x86_3.2.0.v3232m.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.commands_3.2.0.I20060605-1400.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.jdt.core_3.2.0.v_671.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.text_3.2.0.v20060605-1400.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/com.ibm.icu_3.4.4.1.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.team.core_3.2.0.I200606051140.jar"/>
|
||||
</path>
|
||||
<!-- compile the source code -->
|
||||
<javac destdir="${temp.folder}/@dot.bin" failonerror="${javacFailOnError}" verbose="${javacVerbose}" debug="${javacDebugInfo}" includeAntRuntime="no" bootclasspath="${bundleBootClasspath}" source="${bundleJavacSource}" target="${bundleJavacTarget}" >
|
||||
<compilerarg line="${compilerArg}" compiler="${build.compiler}"/>
|
||||
<classpath refid="@dot.classpath" />
|
||||
<src path="dat/" />
|
||||
<src path="src/" />
|
||||
<src path="lib/" />
|
||||
<compilerarg value="@${basedir}/javaCompiler...args" compiler="org.eclipse.jdt.core.JDTCompilerAdapter"/>
|
||||
<compilerarg line="-log '${temp.folder}/@dot.bin${logExtension}'" compiler="org.eclipse.jdt.core.JDTCompilerAdapter"/>
|
||||
</javac>
|
||||
<!-- Copy necessary resources -->
|
||||
<copy todir="${temp.folder}/@dot.bin" failonerror="true" overwrite="false">
|
||||
<fileset dir="dat/" excludes="**/*.java, **/package.htm*" />
|
||||
<fileset dir="src/" excludes="**/*.java, **/package.htm*" />
|
||||
<fileset dir="lib/" excludes="**/*.java, **/package.htm*" />
|
||||
</copy>
|
||||
<mkdir dir="${build.result.folder}"/>
|
||||
<copy todir="${build.result.folder}/@dot" failonerror="true" overwrite="false">
|
||||
<fileset dir="${temp.folder}/@dot.bin" />
|
||||
</copy>
|
||||
<delete dir="${temp.folder}/@dot.bin"/>
|
||||
</target>
|
||||
|
||||
<target name="src.zip" depends="init" unless="src.zip">
|
||||
<mkdir dir="${build.result.folder}"/>
|
||||
<zip destfile="${build.result.folder}/src.zip" filesonly="false" whenempty="skip" update="false">
|
||||
<fileset dir="dat/" includes="**/*.java" />
|
||||
<fileset dir="src/" includes="**/*.java" />
|
||||
<fileset dir="lib/" includes="**/*.java" />
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<target name="build.jars" depends="init" description="Build all the jars for the plug-in: com.ibm.wala.core.">
|
||||
<available property="@dot" file="${build.result.folder}/@dot"/>
|
||||
<antcall target="@dot"/>
|
||||
</target>
|
||||
|
||||
<target name="build.sources" depends="init">
|
||||
<available property="src.zip" file="${build.result.folder}/src.zip"/>
|
||||
<antcall target="src.zip"/>
|
||||
</target>
|
||||
|
||||
<target name="gather.bin.parts" depends="init" if="destination.temp.folder">
|
||||
<mkdir dir="${destination.temp.folder}/com.ibm.wala.core_1.0.0"/>
|
||||
<copy todir="${destination.temp.folder}/com.ibm.wala.core_1.0.0" failonerror="true" overwrite="false">
|
||||
<fileset dir="${build.result.folder}/@dot" includes="**" />
|
||||
</copy>
|
||||
<copy todir="${destination.temp.folder}/com.ibm.wala.core_1.0.0" failonerror="true" overwrite="false">
|
||||
<fileset dir="${basedir}" includes="lib/primordial.jar.model,plugin.properties,lib/extension.jar.model,dat/J2SEClassHierarchyExclusions.xml,dat/SyntheticJ2SEModel.xml,dat/benign.xml,dat/natives.xml,META-INF/" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="build.zips" depends="init">
|
||||
</target>
|
||||
|
||||
<target name="gather.sources" depends="init" if="destination.temp.folder">
|
||||
<mkdir dir="${destination.temp.folder}/com.ibm.wala.core_1.0.0"/>
|
||||
<copy file="${build.result.folder}/src.zip" todir="${destination.temp.folder}/com.ibm.wala.core_1.0.0" failonerror="false" overwrite="false"/>
|
||||
</target>
|
||||
|
||||
<target name="gather.logs" depends="init" if="destination.temp.folder">
|
||||
<mkdir dir="${destination.temp.folder}/com.ibm.wala.core_1.0.0"/>
|
||||
<copy file="${temp.folder}/@dot.bin${logExtension}" todir="${destination.temp.folder}/com.ibm.wala.core_1.0.0" failonerror="false" overwrite="false"/>
|
||||
</target>
|
||||
|
||||
<target name="clean" depends="init" description="Clean the plug-in: com.ibm.wala.core of all the zips, jars and logs created.">
|
||||
<delete dir="${build.result.folder}/@dot"/>
|
||||
<delete file="${build.result.folder}/src.zip"/>
|
||||
<delete file="${plugin.destination}/com.ibm.wala.core_1.0.0.jar"/>
|
||||
<delete file="${plugin.destination}/com.ibm.wala.core_1.0.0.zip"/>
|
||||
<delete dir="${temp.folder}"/>
|
||||
</target>
|
||||
|
||||
<target name="refresh" depends="init" if="eclipse.running" description="Refresh this folder.">
|
||||
<eclipse.convertPath fileSystemPath="C:/temp/walaWorkspace/com.ibm.wala.core" property="resourcePath"/>
|
||||
<eclipse.refreshLocal resource="${resourcePath}" depth="infinite"/>
|
||||
</target>
|
||||
|
||||
<target name="zip.plugin" depends="init" description="Create a zip containing all the elements for the plug-in: com.ibm.wala.core.">
|
||||
<delete dir="${temp.folder}"/>
|
||||
<mkdir dir="${temp.folder}"/>
|
||||
<antcall target="build.jars"/>
|
||||
<antcall target="build.sources"/>
|
||||
<antcall target="gather.bin.parts">
|
||||
<param name="destination.temp.folder" value="${temp.folder}/"/>
|
||||
</antcall>
|
||||
<antcall target="gather.sources">
|
||||
<param name="destination.temp.folder" value="${temp.folder}/"/>
|
||||
</antcall>
|
||||
<delete>
|
||||
<fileset dir="${temp.folder}" includes="**/*.bin${logExtension}" />
|
||||
</delete>
|
||||
<zip destfile="${plugin.destination}/com.ibm.wala.core_1.0.0.zip" basedir="${temp.folder}" filesonly="true" whenempty="skip" update="false"/>
|
||||
<delete dir="${temp.folder}"/>
|
||||
</target>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="dat"/>
|
||||
<classpathentry kind="src" path="lib"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.ibm.wala.core</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,7 @@
|
|||
#Tue Nov 21 13:03:57 EST 2006
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
|
@ -0,0 +1,3 @@
|
|||
#Mon Oct 02 08:58:11 EDT 2006
|
||||
eclipse.preferences.version=1
|
||||
internal.default.compliance=default
|
|
@ -0,0 +1,68 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: WALA Core Plug-in
|
||||
Bundle-SymbolicName: com.ibm.wala.core
|
||||
Bundle-Version: 1.0.0
|
||||
Bundle-Activator: com.ibm.wala.core.plugin.CorePlugin
|
||||
Bundle-Vendor: IBM
|
||||
Bundle-Localization: plugin
|
||||
Require-Bundle: com.ibm.wala.emf;visibility:=reexport,
|
||||
com.ibm.wala.shrike;visibility:=reexport,
|
||||
org.eclipse.core.resources,
|
||||
org.eclipse.jface,
|
||||
org.eclipse.jdt.core
|
||||
Eclipse-LazyStart: true
|
||||
Export-Package: .,
|
||||
com.ibm.wala.analysis.pointers,
|
||||
com.ibm.wala.analysis.reflection,
|
||||
com.ibm.wala.analysis.stackMachine,
|
||||
com.ibm.wala.analysis.typeInference,
|
||||
com.ibm.wala.cfg,
|
||||
com.ibm.wala.cfg.cdg,
|
||||
com.ibm.wala.classLoader,
|
||||
com.ibm.wala.client,
|
||||
com.ibm.wala.client.impl,
|
||||
com.ibm.wala.core.plugin,
|
||||
com.ibm.wala.dataflow.IFDS,
|
||||
com.ibm.wala.dataflow.graph,
|
||||
com.ibm.wala.dataflow.ssa,
|
||||
com.ibm.wala.dynamic,
|
||||
com.ibm.wala.emf.wrappers,
|
||||
com.ibm.wala.escape,
|
||||
com.ibm.wala.fixedpoint.impl,
|
||||
com.ibm.wala.fixpoint,
|
||||
com.ibm.wala.ipa.callgraph,
|
||||
com.ibm.wala.ipa.callgraph.impl,
|
||||
com.ibm.wala.ipa.callgraph.propagation,
|
||||
com.ibm.wala.ipa.callgraph.propagation.cfa,
|
||||
com.ibm.wala.ipa.callgraph.propagation.rta,
|
||||
com.ibm.wala.ipa.cfg,
|
||||
com.ibm.wala.ipa.cha,
|
||||
com.ibm.wala.ipa.modref,
|
||||
com.ibm.wala.ipa.slicer,
|
||||
com.ibm.wala.ipa.summaries,
|
||||
com.ibm.wala.model,
|
||||
com.ibm.wala.model.java.lang,
|
||||
com.ibm.wala.properties,
|
||||
com.ibm.wala.ssa,
|
||||
com.ibm.wala.ssa.analysis,
|
||||
com.ibm.wala.types,
|
||||
com.ibm.wala.util,
|
||||
com.ibm.wala.util.bytecode,
|
||||
com.ibm.wala.util.collections,
|
||||
com.ibm.wala.util.config,
|
||||
com.ibm.wala.util.debug,
|
||||
com.ibm.wala.util.graph,
|
||||
com.ibm.wala.util.graph.impl,
|
||||
com.ibm.wala.util.graph.traverse,
|
||||
com.ibm.wala.util.heapTrace,
|
||||
com.ibm.wala.util.internationalization,
|
||||
com.ibm.wala.util.intset,
|
||||
com.ibm.wala.util.io,
|
||||
com.ibm.wala.util.logging,
|
||||
com.ibm.wala.util.math,
|
||||
com.ibm.wala.util.perf,
|
||||
com.ibm.wala.util.scope,
|
||||
com.ibm.wala.util.system,
|
||||
com.ibm.wala.util.warnings,
|
||||
com.ibm.wala.viz
|
|
@ -0,0 +1,13 @@
|
|||
bin.includes = lib/primordial.jar.model,\
|
||||
plugin.properties,\
|
||||
dat/J2SEClassHierarchyExclusions.xml,\
|
||||
dat/SyntheticJ2SEModel.xml,\
|
||||
dat/benign.xml,\
|
||||
dat/natives.xml,\
|
||||
META-INF/,\
|
||||
.
|
||||
jars.compile.order = .
|
||||
output.. = bin/
|
||||
source.. = dat/,\
|
||||
src/,\
|
||||
lib/
|
|
@ -0,0 +1,202 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="com.ibm.wala.core" default="build.jars" basedir=".">
|
||||
|
||||
<property name="basews" value="${ws}"/>
|
||||
<property name="baseos" value="${os}"/>
|
||||
<property name="basearch" value="${arch}"/>
|
||||
<property name="basenl" value="${nl}"/>
|
||||
|
||||
<!-- Compiler settings. -->
|
||||
<property name="javacFailOnError" value="true"/>
|
||||
<property name="javacDebugInfo" value="on"/>
|
||||
<property name="javacVerbose" value="false"/>
|
||||
<property name="logExtension" value=".log"/>
|
||||
<property name="compilerArg" value=""/>
|
||||
<property name="javacSource" value="1.5"/>
|
||||
<property name="javacTarget" value="1.5"/>
|
||||
<path id="path_bootclasspath">
|
||||
<fileset dir="${java.home}/lib">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
<property name="bootclasspath" refid="path_bootclasspath"/>
|
||||
<property name="bundleJavacSource" value="${javacSource}"/>
|
||||
<property name="bundleJavacTarget" value="${javacTarget}"/>
|
||||
<property name="bundleBootClasspath" value="${bootclasspath}"/>
|
||||
|
||||
<target name="init" depends="properties">
|
||||
<condition property="pluginTemp" value="${buildTempFolder}/plugins">
|
||||
<isset property="buildTempFolder"/>
|
||||
</condition>
|
||||
<property name="pluginTemp" value="${basedir}"/>
|
||||
<condition property="build.result.folder" value="${pluginTemp}/com.ibm.wala.core">
|
||||
<isset property="buildTempFolder"/>
|
||||
</condition>
|
||||
<property name="build.result.folder" value="${basedir}"/>
|
||||
<property name="temp.folder" value="${basedir}/temp.folder"/>
|
||||
<property name="plugin.destination" value="${basedir}/output"/>
|
||||
<property name="eclipse.root" value="c:/eclipse"/>
|
||||
</target>
|
||||
|
||||
<target name="properties" if="eclipse.running">
|
||||
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
|
||||
|
||||
</target>
|
||||
|
||||
<target name="build.update.jar" depends="init" description="Build the plug-in: com.ibm.wala.core for an update site.">
|
||||
<delete dir="${temp.folder}"/>
|
||||
<mkdir dir="${temp.folder}"/>
|
||||
<delete dir="${plugin.destination}"/>
|
||||
<mkdir dir="${plugin.destination}"/>
|
||||
<antcall target="build.jars"/>
|
||||
<antcall target="gather.bin.parts">
|
||||
<param name="destination.temp.folder" value="${temp.folder}/"/>
|
||||
</antcall>
|
||||
<copy todir="${temp.folder}/com.ibm.wala.core_1.0.0" failonerror="true" overwrite="false">
|
||||
<fileset dir="src/" includes="**/*.java" />
|
||||
</copy>
|
||||
<zip destfile="${plugin.destination}/com.ibm.wala.core_1.0.0.jar" basedir="${temp.folder}/com.ibm.wala.core_1.0.0" filesonly="false" whenempty="skip" update="false"/>
|
||||
<delete dir="${temp.folder}"/>
|
||||
</target>
|
||||
|
||||
<target name="@dot" depends="init" description="Create jar: com.ibm.wala.core @dot.">
|
||||
<delete dir="${temp.folder}/@dot.bin"/>
|
||||
<mkdir dir="${temp.folder}/@dot.bin"/>
|
||||
<path id="@dot.classpath">
|
||||
<pathelement path="../com.ibm.wala.emf/bin/"/>
|
||||
<pathelement path="../com.ibm.wala.emf/@dot"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.osgi_3.2.0.v20060601.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.equinox.common_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.jobs_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0.v20060603/runtime_registry_compatibility.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0.v20060603"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.equinox.registry_3.2.0.v20060601.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.apache.xerces_2.8.0.v200606131651/resolver.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.apache.xerces_2.8.0.v200606131651/xercesImpl.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.apache.xerces_2.8.0.v200606131651/xml-apis.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.equinox.preferences_3.2.0.v20060601.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0.v20060603/@dot"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.contenttype_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime.compatibility.auth_3.2.0.v20060601.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.emf.ecore_2.2.0.v200606271057.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.emf.common_2.2.0.v200606271057.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.resources_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.resources.compatibility_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.resources.win32_3.2.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.runtime.compatibility_3.1.100.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.update.configurator_3.2.0.v20060605.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.ant.core_3.1.100.v20060531.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.variables_3.1.100.v20060605.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.expressions_3.2.0.v20060605-1400.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.filesystem_1.0.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.filesystem.win32.x86_1.0.0.v20060603.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.emf.ecore.xmi_2.2.0.v200606271057.jar"/>
|
||||
<pathelement path="../com.ibm.wala.shrike/bin/"/>
|
||||
<pathelement path="../com.ibm.wala.shrike/@dot"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.jface_3.2.0.I20060605-1400.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.swt_3.2.0.v3232o.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.swt.win32.win32.x86_3.2.0.v3232m.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.core.commands_3.2.0.I20060605-1400.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.jdt.core_3.2.0.v_671.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.text_3.2.0.v20060605-1400.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/com.ibm.icu_3.4.4.1.jar"/>
|
||||
<pathelement path="${eclipse.root}/plugins/org.eclipse.team.core_3.2.0.I200606051140.jar"/>
|
||||
</path>
|
||||
<!-- compile the source code -->
|
||||
<javac destdir="${temp.folder}/@dot.bin" failonerror="${javacFailOnError}" verbose="${javacVerbose}" debug="${javacDebugInfo}" includeAntRuntime="no" bootclasspath="${bundleBootClasspath}" source="${bundleJavacSource}" target="${bundleJavacTarget}" >
|
||||
<compilerarg line="${compilerArg}" compiler="${build.compiler}"/>
|
||||
<classpath refid="@dot.classpath" />
|
||||
<src path="dat/" />
|
||||
<src path="src/" />
|
||||
<src path="lib/" />
|
||||
<compilerarg value="@${basedir}/javaCompiler...args" compiler="org.eclipse.jdt.core.JDTCompilerAdapter"/>
|
||||
<compilerarg line="-log '${temp.folder}/@dot.bin${logExtension}'" compiler="org.eclipse.jdt.core.JDTCompilerAdapter"/>
|
||||
</javac>
|
||||
<!-- Copy necessary resources -->
|
||||
<copy todir="${temp.folder}/@dot.bin" failonerror="true" overwrite="false">
|
||||
<fileset dir="dat/" excludes="**/*.java, **/package.htm*" />
|
||||
<fileset dir="src/" excludes="**/*.java, **/package.htm*" />
|
||||
<fileset dir="lib/" excludes="**/*.java, **/package.htm*" />
|
||||
</copy>
|
||||
<mkdir dir="${build.result.folder}"/>
|
||||
<copy todir="${build.result.folder}/@dot" failonerror="true" overwrite="false">
|
||||
<fileset dir="${temp.folder}/@dot.bin" />
|
||||
</copy>
|
||||
<delete dir="${temp.folder}/@dot.bin"/>
|
||||
</target>
|
||||
|
||||
<target name="src.zip" depends="init" unless="src.zip">
|
||||
<mkdir dir="${build.result.folder}"/>
|
||||
<zip destfile="${build.result.folder}/src.zip" filesonly="false" whenempty="skip" update="false">
|
||||
<fileset dir="dat/" includes="**/*.java" />
|
||||
<fileset dir="src/" includes="**/*.java" />
|
||||
<fileset dir="lib/" includes="**/*.java" />
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<target name="build.jars" depends="init" description="Build all the jars for the plug-in: com.ibm.wala.core.">
|
||||
<available property="@dot" file="${build.result.folder}/@dot"/>
|
||||
<antcall target="@dot"/>
|
||||
</target>
|
||||
|
||||
<target name="build.sources" depends="init">
|
||||
<available property="src.zip" file="${build.result.folder}/src.zip"/>
|
||||
<antcall target="src.zip"/>
|
||||
</target>
|
||||
|
||||
<target name="gather.bin.parts" depends="init" if="destination.temp.folder">
|
||||
<mkdir dir="${destination.temp.folder}/com.ibm.wala.core_1.0.0"/>
|
||||
<copy todir="${destination.temp.folder}/com.ibm.wala.core_1.0.0" failonerror="true" overwrite="false">
|
||||
<fileset dir="${build.result.folder}/@dot" includes="**" />
|
||||
</copy>
|
||||
<copy todir="${destination.temp.folder}/com.ibm.wala.core_1.0.0" failonerror="true" overwrite="false">
|
||||
<fileset dir="${basedir}" includes="lib/primordial.jar.model,plugin.properties,lib/extension.jar.model,dat/J2SEClassHierarchyExclusions.xml,dat/SyntheticJ2SEModel.xml,dat/benign.xml,dat/natives.xml,META-INF/" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="build.zips" depends="init">
|
||||
</target>
|
||||
|
||||
<target name="gather.sources" depends="init" if="destination.temp.folder">
|
||||
<mkdir dir="${destination.temp.folder}/com.ibm.wala.core_1.0.0"/>
|
||||
<copy file="${build.result.folder}/src.zip" todir="${destination.temp.folder}/com.ibm.wala.core_1.0.0" failonerror="false" overwrite="false"/>
|
||||
</target>
|
||||
|
||||
<target name="gather.logs" depends="init" if="destination.temp.folder">
|
||||
<mkdir dir="${destination.temp.folder}/com.ibm.wala.core_1.0.0"/>
|
||||
<copy file="${temp.folder}/@dot.bin${logExtension}" todir="${destination.temp.folder}/com.ibm.wala.core_1.0.0" failonerror="false" overwrite="false"/>
|
||||
</target>
|
||||
|
||||
<target name="clean" depends="init" description="Clean the plug-in: com.ibm.wala.core of all the zips, jars and logs created.">
|
||||
<delete dir="${build.result.folder}/@dot"/>
|
||||
<delete file="${build.result.folder}/src.zip"/>
|
||||
<delete file="${plugin.destination}/com.ibm.wala.core_1.0.0.jar"/>
|
||||
<delete file="${plugin.destination}/com.ibm.wala.core_1.0.0.zip"/>
|
||||
<delete dir="${temp.folder}"/>
|
||||
</target>
|
||||
|
||||
<target name="refresh" depends="init" if="eclipse.running" description="Refresh this folder.">
|
||||
<eclipse.convertPath fileSystemPath="C:/temp/walaWorkspace/com.ibm.wala.core" property="resourcePath"/>
|
||||
<eclipse.refreshLocal resource="${resourcePath}" depth="infinite"/>
|
||||
</target>
|
||||
|
||||
<target name="zip.plugin" depends="init" description="Create a zip containing all the elements for the plug-in: com.ibm.wala.core.">
|
||||
<delete dir="${temp.folder}"/>
|
||||
<mkdir dir="${temp.folder}"/>
|
||||
<antcall target="build.jars"/>
|
||||
<antcall target="build.sources"/>
|
||||
<antcall target="gather.bin.parts">
|
||||
<param name="destination.temp.folder" value="${temp.folder}/"/>
|
||||
</antcall>
|
||||
<antcall target="gather.sources">
|
||||
<param name="destination.temp.folder" value="${temp.folder}/"/>
|
||||
</antcall>
|
||||
<delete>
|
||||
<fileset dir="${temp.folder}" includes="**/*.bin${logExtension}" />
|
||||
</delete>
|
||||
<zip destfile="${plugin.destination}/com.ibm.wala.core_1.0.0.zip" basedir="${temp.folder}" filesonly="true" whenempty="skip" update="false"/>
|
||||
<delete dir="${temp.folder}"/>
|
||||
</target>
|
||||
|
||||
</project>
|
|
@ -0,0 +1 @@
|
|||
wala.properties
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="ASCII"?>
|
||||
<com.ibm.wala.common:EContainer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:com.ibm.wala.common="http:///com/ibm/wala/wala.ecore.common" xmlns:com.ibm.wala.regex="http:///com/ibm/wala/wala.ecore.regex">
|
||||
<contents xsi:type="com.ibm.wala.regex:EPattern" pattern="java\/awt\/.*"/>
|
||||
<contents xsi:type="com.ibm.wala.regex:EPattern" pattern="java\/lang\/Boolean"/>
|
||||
<contents xsi:type="com.ibm.wala.regex:EPattern" pattern="java\/lang\/Integer"/>
|
||||
<contents xsi:type="com.ibm.wala.regex:EPattern" pattern="java\/lang\/StringBuffer"/>
|
||||
<contents xsi:type="com.ibm.wala.regex:EPattern" pattern="java\/lang\/SecurityManager"/>
|
||||
<contents xsi:type="com.ibm.wala.regex:EPattern" pattern="java\/lang\/Float"/>
|
||||
<contents xsi:type="com.ibm.wala.regex:EPattern" pattern="java\/net\/.*"/>
|
||||
<contents xsi:type="com.ibm.wala.regex:EPattern" pattern="java\/util\/.*"/>
|
||||
<contents xsi:type="com.ibm.wala.regex:EPattern" pattern="javax\/.*"/>
|
||||
<contents xsi:type="com.ibm.wala.regex:EPattern" pattern="sun\/.*"/>
|
||||
</com.ibm.wala.common:EContainer>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<com.ibm.wala.java.scope:EJavaAnalysisScope xmlns:com.ibm.wala.java.scope="http:///com/ibm/wala/wala.ecore.java.scope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<loaders loaderName="Primordial">
|
||||
<modules xsi:type="com.ibm.wala.java.scope:EBuiltInModule" id="primordial_jar_model"/>
|
||||
</loaders>
|
||||
</com.ibm.wala.java.scope:EJavaAnalysisScope>
|
|
@ -0,0 +1,15 @@
|
|||
########## General messages
|
||||
|
||||
########## Error messages
|
||||
|
||||
AbstractPropertyReader.invalid_property_value=Value for property ''{0}'' is invalid.
|
||||
AbstractPropertyReader.location_error=Path for file ''{0}'' do not exist and can''t be constructed.
|
||||
AbstractPropertyReader.no_string_value=Property ''{0}'' is not mapped to a string as expected.
|
||||
AbstractPropertyReader.incorrect_boolean_value=Boolean property ''{0}'' should not be mapped to a string.
|
||||
AbstractPropertyReader.incorrect_int_value=Integer property ''{0}'' should be mapped to an Integer object.
|
||||
AbstractPropertyReader.int_conversion_failed=Integer property ''{0}'' cannot convert ''{1}'' to an integer.
|
||||
|
||||
CancelCHAConstructionException.cancelation_message=ClassHierarchy construction has been cancelled by progress monitor.
|
||||
|
||||
PersistentPropertiesManager.property_file_unreadable=Unable to read property file named ''{0}''.
|
||||
PersistentPropertiesManager.reading_failure=Failed to load ''{0}''.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><templates><template autoinsert="true" context="gettercomment_context" deleted="false" description="Comment for getter method" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name="gettercomment">/**
|
||||
* @return the ${bare_field_name}
|
||||
*/</template><template autoinsert="true" context="settercomment_context" deleted="false" description="Comment for setter method" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.settercomment" name="settercomment">/**
|
||||
* @param ${param} the ${bare_field_name} to set
|
||||
*/</template><template autoinsert="true" context="constructorcomment_context" deleted="false" description="Comment for created constructors" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name="constructorcomment">/**
|
||||
* ${tags}
|
||||
*/</template><template autoinsert="true" context="filecomment_context" deleted="false" description="Comment for created Java files" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.filecomment" name="filecomment">/**
|
||||
*
|
||||
*/</template><template autoinsert="true" context="typecomment_context" deleted="false" description="Comment for created types" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.typecomment" name="typecomment">/**
|
||||
* @author ${user}
|
||||
*
|
||||
* ${tags}
|
||||
*/</template><template autoinsert="true" context="fieldcomment_context" deleted="false" description="Comment for fields" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name="fieldcomment">/**
|
||||
*
|
||||
*/</template><template autoinsert="true" context="methodcomment_context" deleted="false" description="Comment for non-overriding methods" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name="methodcomment">/**
|
||||
* ${tags}
|
||||
*/</template><template autoinsert="true" context="overridecomment_context" deleted="false" description="Comment for overriding methods" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name="overridecomment">/* (non-Javadoc)
|
||||
* ${see_to_overridden}
|
||||
*/</template><template autoinsert="true" context="delegatecomment_context" deleted="false" description="Comment for delegate methods" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name="delegatecomment">/**
|
||||
* ${tags}
|
||||
* ${see_to_target}
|
||||
*/</template><template autoinsert="false" context="newtype_context" deleted="false" description="Newly created files" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.newtype" name="newtype">/*******************************************************************************
|
||||
* Copyright (c) 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
${package_declaration}
|
||||
|
||||
${typecomment}
|
||||
${type_declaration}</template><template autoinsert="true" context="classbody_context" deleted="false" description="Code in new class type bodies" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.classbody" name="classbody">
|
||||
</template><template autoinsert="true" context="interfacebody_context" deleted="false" description="Code in new interface type bodies" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name="interfacebody">
|
||||
</template><template autoinsert="true" context="enumbody_context" deleted="false" description="Code in new enum type bodies" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.enumbody" name="enumbody">
|
||||
</template><template autoinsert="true" context="annotationbody_context" deleted="false" description="Code in new annotation type bodies" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name="annotationbody">
|
||||
</template><template autoinsert="true" context="catchblock_context" deleted="false" description="Code in new catch blocks" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.catchblock" name="catchblock">// ${todo} Auto-generated catch block
|
||||
${exception_var}.printStackTrace();</template><template autoinsert="true" context="methodbody_context" deleted="false" description="Code in created method stubs" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.methodbody" name="methodbody">// ${todo} Auto-generated method stub
|
||||
${body_statement}</template><template autoinsert="true" context="constructorbody_context" deleted="false" description="Code in created constructor stubs" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name="constructorbody">${body_statement}
|
||||
// ${todo} Auto-generated constructor stub</template><template autoinsert="true" context="getterbody_context" deleted="false" description="Code in created getters" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.getterbody" name="getterbody">return ${field};</template><template autoinsert="true" context="setterbody_context" deleted="false" description="Code in created setters" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.setterbody" name="setterbody">${field} = ${param};</template></templates>
|
|
@ -0,0 +1,251 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<profiles version="10">
|
||||
<profile name="WALA" version="10">
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="132"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
</profile>
|
||||
</profiles>
|
|
@ -0,0 +1,16 @@
|
|||
# Handlers installed for the root logger
|
||||
handlers= java.util.logging.ConsoleHandler java.util.logging.FileHandler
|
||||
|
||||
### Configure FileHandler
|
||||
# Logging file name in temporary directory of the machine.
|
||||
java.util.logging.FileHandler.pattern = %t/safeLogFile%g.log
|
||||
# Write 100 kbytes before rotating this file
|
||||
java.util.logging.FileHandler.limit = 100000
|
||||
# Number of rotating files to be used
|
||||
java.util.logging.FileHandler.count = 3
|
||||
# Formatter to be used with this FileHandler
|
||||
java.util.logging.FileHandler.formatter = com.ibm.wala.util.logging.SimplifiedFormatter
|
||||
|
||||
# Configure ConsoleHandler
|
||||
java.util.logging.ConsoleHandler.level = WARNING
|
||||
java.util.logging.ConsoleHandler.formatter = com.ibm.wala.util.logging.SimplifiedFormatter
|
|
@ -0,0 +1,784 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!-- native methods in the IBM Windows DK 1.3.1 -->
|
||||
<summary-spec>
|
||||
<classloader name="Primordial">
|
||||
|
||||
<package name="com/ibm/wala/model">
|
||||
<class name="SyntheticFactory">
|
||||
<method name="getObject"
|
||||
descriptor="()Ljava/lang/Object;" factory="true" static="true">
|
||||
<new def="x" class="Lcom/ibm/wala/Malleable" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
</class>
|
||||
</package>
|
||||
|
||||
<package name="com/ibm/jvm">
|
||||
<class name="ExtendedSystem">
|
||||
<method name="isResettableJVM" descriptor="()Z"
|
||||
static="true">
|
||||
</method>
|
||||
<method name="setJVMUnresettableConditionally"
|
||||
descriptor="(ILjava/lang/String;)V" static="true">
|
||||
</method>
|
||||
<method name="resizeArray"
|
||||
descriptor="(ILjava/lang/Object;II)Ljava/lang/Object;"
|
||||
factory="true" static="true">
|
||||
<new def="x" class="Lcom/ibm/wala/Malleable" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
</class>
|
||||
|
||||
</package>
|
||||
|
||||
<package name="java/io">
|
||||
<class name="FileDescriptor">
|
||||
<method name="sync" descriptor="()V"></method>
|
||||
</class>
|
||||
<class name="FileInputStream">
|
||||
<method name="available" descriptor="()I">
|
||||
<constant name="yes" type="int" value="1" />
|
||||
<constant name="no" type="int" value="0" />
|
||||
<return value="yes" />
|
||||
<return value="no" />
|
||||
<new def="x" class="Ljava/io/IOException" />
|
||||
<throw value="x" />
|
||||
</method>
|
||||
<method name="close" descriptor="()V">
|
||||
<new def="x" class="Ljava/io/IOException" />
|
||||
<throw value="x" />
|
||||
</method>
|
||||
<method name="open"
|
||||
descriptor="(Ljava/lang/String;)V">
|
||||
<new def="x" class="Ljava/io/IOException" />
|
||||
<throw value="x" />
|
||||
</method>
|
||||
<method name="read" descriptor="()I">
|
||||
<constant name="yes" type="int" value="1" />
|
||||
<constant name="no" type="int" value="0" />
|
||||
<return value="yes" />
|
||||
<return value="no" />
|
||||
<new def="x" class="Ljava/io/IOException" />
|
||||
<throw value="x" />
|
||||
</method>
|
||||
<method name="readBytes" descriptor="([BII)I">
|
||||
<constant name="yes" type="int" value="1" />
|
||||
<constant name="no" type="int" value="0" />
|
||||
<return value="yes" />
|
||||
<return value="no" />
|
||||
<new def="x" class="Ljava/io/IOException" />
|
||||
<throw value="x" />
|
||||
</method>
|
||||
<method name="readBytes"
|
||||
descriptor="([BIILjava/io/FileDescriptor;)I">
|
||||
<constant name="yes" type="int" value="1" />
|
||||
<constant name="no" type="int" value="0" />
|
||||
<return value="yes" />
|
||||
<return value="no" />
|
||||
<new def="x" class="Ljava/io/IOException" />
|
||||
<throw value="x" />
|
||||
</method>
|
||||
<method name="skip" descriptor="(J)J">
|
||||
<constant name="yes" type="int" value="1" />
|
||||
<constant name="no" type="int" value="0" />
|
||||
<return value="yes" />
|
||||
<return value="no" />
|
||||
<new def="x" class="Ljava/io/IOException" />
|
||||
<throw value="x" />
|
||||
</method>
|
||||
</class>
|
||||
<class name="FileOutputStream">
|
||||
<method name="close" descriptor="()V"></method>
|
||||
<method name="open"
|
||||
descriptor="(Ljava/lang/String;)V">
|
||||
</method>
|
||||
<method name="openAppend"
|
||||
descriptor="(Ljava/lang/String;)V">
|
||||
</method>
|
||||
<method name="write" descriptor="(I)V"></method>
|
||||
<method name="writeBytes" descriptor="([BII)V"></method>
|
||||
</class>
|
||||
<class name="ObjectOutputStream">
|
||||
<method name="doublesToBytes" descriptor="([DI[BII)V"
|
||||
static="true" />
|
||||
<method name="floatsToBytes" descriptor="([FI[BII)V"
|
||||
static="true" />
|
||||
</class>
|
||||
<class name="ObjectStreamClass">
|
||||
<method name="hasStaticInitializer"
|
||||
descriptor="(Ljava/lang/Class;)Z" static="true">
|
||||
</method>
|
||||
</class>
|
||||
<class name="RandomAccessFile">
|
||||
<method name="close" descriptor="()V"></method>
|
||||
<method name="getFilePointer" descriptor="()J"></method>
|
||||
<method name="length" descriptor="()J"></method>
|
||||
<method name="open"
|
||||
descriptor="(Ljava/lang/String;Z)V">
|
||||
</method>
|
||||
<method name="open"
|
||||
descriptor="(Ljava/lang/String;I)V">
|
||||
</method>
|
||||
<method name="read" descriptor="()I"></method>
|
||||
<method name="readBytes"
|
||||
descriptor="([BIILjava/io/FileDescriptor;)I">
|
||||
</method>
|
||||
<method name="seek" descriptor="(J)V"></method>
|
||||
<method name="write" descriptor="(I)V"></method>
|
||||
<method name="writeBytes"
|
||||
descriptor="([BIILjava/io/FileDescriptor;)V">
|
||||
</method>
|
||||
<method name="writeBytes" descriptor="([BII)V"></method>
|
||||
</class>
|
||||
</package>
|
||||
|
||||
<package name="java/lang">
|
||||
<class name="Class">
|
||||
<method name="forName"
|
||||
descriptor="(Ljava/lang/String;)Ljava/lang/Class;"
|
||||
static="true">
|
||||
<new def="x" class="Ljava/lang/Class" />
|
||||
<return value="x" />
|
||||
<new def="y"
|
||||
class="Ljava/lang/ClassNotFoundException" />
|
||||
<throw value="y" />
|
||||
<new def="z" class="Ljava/lang/ClassFormatError" />
|
||||
<throw value="z" />
|
||||
</method>
|
||||
<method name="forName0"
|
||||
descriptor="(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"
|
||||
static="true">
|
||||
<new def="x" class="Ljava/lang/Class" />
|
||||
<return value="x" />
|
||||
<new def="y"
|
||||
class="Ljava/lang/ClassNotFoundException" />
|
||||
<throw value="y" />
|
||||
<new def="z" class="Ljava/lang/ClassFormatError" />
|
||||
<throw value="z" />
|
||||
</method>
|
||||
<method name="forName1"
|
||||
descriptor="(Ljava/lang/String;)Ljava/lang/Class;" static="true">
|
||||
<new def="x" class="Ljava/lang/Class" />
|
||||
<return value="x" />
|
||||
<new def="y"
|
||||
class="Ljava/lang/ClassNotFoundException" />
|
||||
<throw value="y" />
|
||||
<new def="z" class="Ljava/lang/ClassFormatError" />
|
||||
<throw value="z" />
|
||||
</method>
|
||||
<method name="getClassLoader0"
|
||||
descriptor="()Ljava/lang/ClassLoader;">
|
||||
<new def="x" class="Ljava/lang/ClassLoader" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getComponentType"
|
||||
descriptor="()Ljava/lang/Class;">
|
||||
<new def="x" class="Ljava/lang/Class" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getConstructor0"
|
||||
descriptor="([Ljava/lang/Class;I)Ljava/lang/reflect/Constructor;">
|
||||
<new def="x" class="Ljava/lang/reflect/Constructor" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getField0"
|
||||
descriptor="(Ljava/lang/String;I)Ljava/lang/reflect/Field;">
|
||||
<new def="x" class="Ljava/lang/reflect/Field" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getInterfaces"
|
||||
descriptor="()[Ljava/lang/Class;">
|
||||
<constant name="size" type="int" value="1" />
|
||||
<new def="x" class="[Ljava/lang/Class" size="size" />
|
||||
<new def="y" class="Ljava/lang/Class" />
|
||||
<aastore ref="x" value="y" index="0" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getMethod0"
|
||||
descriptor="(Ljava/lang/String;[Ljava/lang/Class;I)Ljava/lang/reflect/Method;">
|
||||
<new def="x" class="Ljava/lang/reflect/Method" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getMethods0"
|
||||
descriptor="(I)[Ljava/lang/reflect/Method;">
|
||||
<constant name="size" type="int" value="1" />
|
||||
<new def="x" class="[Ljava/lang/reflect/Method"
|
||||
size="size" />
|
||||
<new def="y" class="Ljava/lang/reflect/Method" />
|
||||
<aastore ref="x" value="y" index="0" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getModifiers" descriptor="()I"></method>
|
||||
<method name="getName"
|
||||
descriptor="()Ljava/lang/String;">
|
||||
<new def="x" class="Ljava/lang/String" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getPrimitiveClass"
|
||||
descriptor="(Ljava/lang/String;)Ljava/lang/Class;" static="true">
|
||||
<new def="x" class="Ljava/lang/Class" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getSigners"
|
||||
descriptor="()[Ljava/lang/Object;">
|
||||
<constant name="size" type="int" value="1" />
|
||||
<new def="x" class="[Ljava/lang/Object" size="size" />
|
||||
<new def="y" class="Ljava/lang/Class" />
|
||||
<aastore ref="x" value="y" index="0" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getSuperclass"
|
||||
descriptor="()Ljava/lang/Class;">
|
||||
<new def="x" class="Ljava/lang/Class" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getFields"
|
||||
descriptor="()[Ljava/lang/reflect/Field;">
|
||||
<constant name="size" type="int" value="1" />
|
||||
<new def="x" class="[Ljava/lang/reflect/Field" size="size"/>
|
||||
<new def="y" class="Ljava/lang/reflect/Field" />
|
||||
<aastore ref="x" value="y" index="0" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getConstructors"
|
||||
descriptor="()[Ljava/lang/reflect/Constructor;">
|
||||
<constant name="size" type="int" value="1" />
|
||||
<new def="x"
|
||||
class="[Ljava/lang/reflect/Constructor" size="size"/>
|
||||
<new def="y" class="Ljava/lang/reflect/Constructor" />
|
||||
<aastore ref="x" value="y" index="0" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="isAssignableFrom"
|
||||
descriptor="(Ljava/lang/Class;)Z">
|
||||
</method>
|
||||
<method name="isArray" descriptor="()Z"></method>
|
||||
<method name="isInstance"
|
||||
descriptor="(Ljava/lang/Object;)Z">
|
||||
</method>
|
||||
<method name="isInterface" descriptor="()Z"></method>
|
||||
<method name="isPrimitive" descriptor="()Z"></method>
|
||||
<method name="newInstance"
|
||||
descriptor="()Ljava/lang/Object;" factory="true">
|
||||
<new def="x" class="Lcom/ibm/wala/Malleable" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
</class>
|
||||
<class name="ClassLoader" allocatable="true">
|
||||
<method name="findBootstrapClass"
|
||||
descriptor="(Ljava/lang/String;)Ljava/lang/Class;">
|
||||
<new def="x" class="Ljava/lang/Class" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="findLoadedClass"
|
||||
descriptor="(Ljava/lang/String;)Ljava/lang/Class;">
|
||||
<new def="x" class="Ljava/lang/Class" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="getCallerClassLoader"
|
||||
descriptor="()Ljava/lang/ClassLoader;" static="true">
|
||||
<new def="x" class="Ljava/lang/ClassLoader" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
</class>
|
||||
<class name="Double">
|
||||
<method name="doubleToLongBits" descriptor="(D)J"
|
||||
static="true">
|
||||
</method>
|
||||
<method name="longBitsToDouble" descriptor="(J)D"
|
||||
static="true">
|
||||
</method>
|
||||
</class>
|
||||
<class name="Float">
|
||||
<method name="floatToIntBits" descriptor="(F)I"
|
||||
static="true">
|
||||
</method>
|
||||
<method name="intBitsToFloat" descriptor="(I)F"
|
||||
static="true">
|
||||
</method>
|
||||
</class>
|
||||
<class name="Object">
|
||||
<method name="clone"
|
||||
descriptor="()Ljava/lang/Object;">
|
||||
<return value="null" />
|
||||
<!-- Note that propagation-style builders should intercept calls to clone, and this model is OK for RTA -->
|
||||
</method>
|
||||
<method name="getClass"
|
||||
descriptor="()Ljava/lang/Class;">
|
||||
<new def="x" class="Ljava/lang/Class" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="hashCode" descriptor="()I"></method>
|
||||
<method name="notify" descriptor="()V"></method>
|
||||
<method name="notifyAll" descriptor="()V"></method>
|
||||
<method name="wait" descriptor="(J)V"></method>
|
||||
</class>
|
||||
<class name="Runtime">
|
||||
<method name="freeMemory" descriptor="()J"></method>
|
||||
<method name="gc" descriptor="()V"></method>
|
||||
<method name="totalMemory" descriptor="()J"></method>
|
||||
</class>
|
||||
<class name="SecurityManager">
|
||||
<method name="getClassContext"
|
||||
descriptor="()[Ljava/lang/Class;">
|
||||
<constant name="size" type="int" value="1" />
|
||||
<new def="x" class="[Ljava/lang/Class" size="size"/>
|
||||
<new def="y" class="Ljava/lang/Class" />
|
||||
<aastore ref="x" value="y" index="0" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
</class>
|
||||
<class name="StrictMath">
|
||||
<method name="ceil" descriptor="(D)D" static="true"></method>
|
||||
<method name="exp" descriptor="(D)D" static="true"></method>
|
||||
<method name="floor" descriptor="(D)D" static="true"></method>
|
||||
<method name="pow" descriptor="(DD)D" static="true"></method>
|
||||
</class>
|
||||
<class name="String">
|
||||
<method name="intern"
|
||||
descriptor="()Ljava/lang/String;">
|
||||
<new def="x" class="Ljava/lang/String" />
|
||||
<return value="x" />
|
||||
<poison
|
||||
reason="questionable model of java/lang/String/intern()"
|
||||
level="mild" />
|
||||
</method>
|
||||
</class>
|
||||
<class name="System">
|
||||
<method name="arraycopy"
|
||||
descriptor="(Ljava/lang/Object;ILjava/lang/Object;II)V"
|
||||
static="true">
|
||||
<call type="static" name="arraycopy"
|
||||
class="Lcom/ibm/wala/model/java/lang/System"
|
||||
descriptor="(Ljava/lang/Object;Ljava/lang/Object;)V" arg0="arg0"
|
||||
arg1="arg2" />
|
||||
<return />
|
||||
</method>
|
||||
<method name="currentTimeMillis" descriptor="()J"
|
||||
static="true">
|
||||
</method>
|
||||
<method name="getCallerClass"
|
||||
descriptor="()Ljava/lang/Class;" static="true">
|
||||
<new def="x" class="Ljava/lang/Class" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="identityHashCode"
|
||||
descriptor="(Ljava/lang/Object;)I" static="true">
|
||||
</method>
|
||||
<method name="initProperties"
|
||||
descriptor="(Ljava/util/Properties;)Ljava/util/Properties;"
|
||||
static="true">
|
||||
<new def="dummy1" class="Ljava/lang/Object" />
|
||||
<new def="dummy2" class="Ljava/lang/Object" />
|
||||
<call type="virtual" name="put"
|
||||
class="Ljava/util/Properties"
|
||||
descriptor="(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"
|
||||
arg0="arg0" arg1="dummy1" arg2="dummy2" def="ignore" />
|
||||
<new def="x" class="Ljava/util/Properties" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="mapLibraryName"
|
||||
descriptor="(Ljava/lang/String;)Ljava/lang/String;"
|
||||
static="true">
|
||||
<return value="arg0" />
|
||||
</method>
|
||||
<method name="setErr0"
|
||||
descriptor="(Ljava/io/PrintStream;)V" static="true">
|
||||
</method>
|
||||
<method name="setIn0"
|
||||
descriptor="(Ljava/io/InputStream;)V" static="true">
|
||||
</method>
|
||||
<method name="setOut0"
|
||||
descriptor="(Ljava/io/PrintStream;)V" static="true">
|
||||
</method>
|
||||
</class>
|
||||
<class name="Thread">
|
||||
<method name="currentThread"
|
||||
descriptor="()Ljava/lang/Thread;" static="true">
|
||||
<new def="x" class="Ljava/lang/Thread" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="interrupt0" descriptor="()V"></method>
|
||||
<method name="<init>" descriptor="()V">
|
||||
<putfield class="Ljava/lang/Thread" field="runnable"
|
||||
fieldType="Ljava/lang/Runnable" ref="arg0" value="arg0" />
|
||||
<putfield class="Ljava/lang/Thread" field="target"
|
||||
fieldType="Ljava/lang/Runnable" ref="arg0" value="arg0" />
|
||||
</method>
|
||||
<method name="<init>"
|
||||
descriptor="(Ljava/lang/Runnable;)V">
|
||||
<putfield class="Ljava/lang/Thread" field="runnable"
|
||||
fieldType="Ljava/lang/Runnable" ref="arg0" value="arg1" />
|
||||
<putfield class="Ljava/lang/Thread" field="target"
|
||||
fieldType="Ljava/lang/Runnable" ref="arg0" value="arg0" />
|
||||
</method>
|
||||
<method name="isAlive" descriptor="()Z"></method>
|
||||
<method name="resume0" descriptor="()V" />
|
||||
<method name="sleep" descriptor="(J)V" static="true">
|
||||
<new def="x"
|
||||
class="Ljava/lang/InterruptedException" />
|
||||
<throw value="x" />
|
||||
</method>
|
||||
<method name="start" descriptor="()V">
|
||||
<putfield class="Ljava/lang/Thread" field="runnable"
|
||||
fieldType="Ljava/lang/Runnable" ref="arg0" value="arg0" />
|
||||
<getfield class="Ljava/lang/Thread" field="runnable"
|
||||
fieldType="Ljava/lang/Runnable" def="x" ref="arg0" />
|
||||
<call type="interface" name="run"
|
||||
class="Ljava/lang/Runnable" descriptor="()V" arg0="x" />
|
||||
<putfield class="Ljava/lang/Thread" field="target"
|
||||
fieldType="Ljava/lang/Runnable" ref="arg0" value="arg0" />
|
||||
<getfield class="Ljava/lang/Thread" field="target"
|
||||
fieldType="Ljava/lang/Runnable" def="y" ref="arg0" />
|
||||
<call type="interface" name="run"
|
||||
class="Ljava/lang/Runnable" descriptor="()V" arg0="y" />
|
||||
</method>
|
||||
<method name="stop0" descriptor="()V" />
|
||||
<method name="yield" descriptor="()V" static="true" />
|
||||
</class>
|
||||
<class name="Throwable">
|
||||
<method name="fillInStackTrace"
|
||||
descriptor="()Ljava/lang/Throwable;">
|
||||
<return value="arg0" />
|
||||
</method>
|
||||
<method name="getStackTraceElement"
|
||||
descriptor="(I)Ljava/lang/StackTraceElement;">
|
||||
<new def="x" class="Ljava/lang/StackTraceElement" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="printStackTrace0"
|
||||
descriptor="(Ljava/lang/Object;)V" />
|
||||
<method name="getStackTraceDepth" descriptor="()I" />
|
||||
|
||||
</class>
|
||||
</package>
|
||||
<package name="java/lang/reflect">
|
||||
<class name="Array">
|
||||
<method name="get"
|
||||
descriptor="(Ljava/lang/Object;I)Ljava/lang/Object;" static="true"
|
||||
factory="true">
|
||||
<new def="x" class="Lcom/ibm/wala/Malleable" />
|
||||
<return value="x" />
|
||||
<poison
|
||||
reason="bogus model of java/lang/reflect/Array/get"
|
||||
level="severe" />
|
||||
</method>
|
||||
<method name="getByte"
|
||||
descriptor="(Ljava/lang/Object;I)B" static="true">
|
||||
</method>
|
||||
<method name="getLength"
|
||||
descriptor="(Ljava/lang/Object;)I" static="true">
|
||||
</method>
|
||||
<method name="multiNewArray"
|
||||
descriptor="(Ljava/lang/Class;[I)Ljava/lang/Object;" static="true"
|
||||
factory="true">
|
||||
<new def="x" class="Lcom/ibm/wala/Malleable" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="newArray"
|
||||
descriptor="(Ljava/lang/Class;I)Ljava/lang/Object;" static="true"
|
||||
factory="true">
|
||||
<new def="x" class="Lcom/ibm/wala/Malleable" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="newInstance"
|
||||
descriptor="(Ljava/lang/Class;I)Ljava/lang/Object;" static="true"
|
||||
factory="true">
|
||||
<new def="x" class="Lcom/ibm/wala/Malleable" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="set"
|
||||
descriptor="(Ljava/lang/Object;ILjava/lang/Object;)V"
|
||||
static="true">
|
||||
</method>
|
||||
<method name="setByte"
|
||||
descriptor="(Ljava/lang/Object;IB)V" static="true">
|
||||
</method>
|
||||
</class>
|
||||
<class name="Field">
|
||||
<method name="get"
|
||||
descriptor="(Ljava/lang/Object;)Ljava/lang/Object;"
|
||||
factory="true">
|
||||
<new def="x" class="Lcom/ibm/wala/Malleable" />
|
||||
<return value="x" />
|
||||
<poison
|
||||
reason="bogus model of java/lang/reflect/Field/get"
|
||||
level="severe" />
|
||||
</method>
|
||||
<method name="getBoolean"
|
||||
descriptor="(Ljava/lang/Object;)Z">
|
||||
</method>
|
||||
<method name="getByte"
|
||||
descriptor="(Ljava/lang/Object;)B">
|
||||
</method>
|
||||
<method name="getChar"
|
||||
descriptor="(Ljava/lang/Object;)C">
|
||||
</method>
|
||||
<method name="getDouble"
|
||||
descriptor="(Ljava/lang/Object;)D">
|
||||
</method>
|
||||
<method name="getFloat"
|
||||
descriptor="(Ljava/lang/Object;)F">
|
||||
</method>
|
||||
<method name="getInt"
|
||||
descriptor="(Ljava/lang/Object;)I">
|
||||
</method>
|
||||
<method name="getLong"
|
||||
descriptor="(Ljava/lang/Object;)J">
|
||||
</method>
|
||||
<method name="getShort"
|
||||
descriptor="(Ljava/lang/Object;)S">
|
||||
</method>
|
||||
<method name="set"
|
||||
descriptor="(Ljava/lang/Object;Ljava/lang/Object;)V">
|
||||
</method>
|
||||
<method name="setBoolean"
|
||||
descriptor="(Ljava/lang/Object;Z)V">
|
||||
</method>
|
||||
<method name="setByte"
|
||||
descriptor="(Ljava/lang/Object;B)V">
|
||||
</method>
|
||||
<method name="setChar"
|
||||
descriptor="(Ljava/lang/Object;C)V">
|
||||
</method>
|
||||
<method name="setDouble"
|
||||
descriptor="(Ljava/lang/Object;D)V">
|
||||
</method>
|
||||
<method name="setFloat"
|
||||
descriptor="(Ljava/lang/Object;F)V">
|
||||
</method>
|
||||
<method name="setInt"
|
||||
descriptor="(Ljava/lang/Object;I)V">
|
||||
</method>
|
||||
<method name="setLong"
|
||||
descriptor="(Ljava/lang/Object;J)V">
|
||||
</method>
|
||||
<method name="setShort"
|
||||
descriptor="(Ljava/lang/Object;S)V">
|
||||
</method>
|
||||
</class>
|
||||
</package>
|
||||
|
||||
<package name="java/net">
|
||||
<class name="PlainDatagramSocketImpl">
|
||||
<method name="bind"
|
||||
descriptor="(ILjava/net/InetAddress;)V">
|
||||
</method>
|
||||
</class>
|
||||
<class name="PlainSocketImpl">
|
||||
<method name="initProto" descriptor="()V" static="true" />
|
||||
<method name="socketAvailable" descriptor="()I" />
|
||||
<method name="socketBind"
|
||||
descriptor="(Ljava/net/InetAddress;I)V" />
|
||||
<method name="socketClose0" descriptor="(Z)V" />
|
||||
<method name="socketConnect"
|
||||
descriptor="(Ljava/net/InetAddress;II)V" />
|
||||
<method name="socketCreate" descriptor="(Z)V" />
|
||||
<method name="socketGetOption"
|
||||
descriptor="(ILjava/lang/Object;)I" />
|
||||
<method name="socketListen" descriptor="(I)V" />
|
||||
<method name="socketSetOption"
|
||||
descriptor="(IZLjava/lang/Object;)V" />
|
||||
</class>
|
||||
<class name="SocketInputStream">
|
||||
<method name="init" descriptor="()V" static="true" />
|
||||
<method name="socketRead0"
|
||||
descriptor="(Ljava/io/FileDescriptor;[BIII)I" />
|
||||
</class>
|
||||
<class name="SocketOutputStream">
|
||||
<method name="init" descriptor="()V" static="true" />
|
||||
<method name="socketWrite0"
|
||||
descriptor="(Ljava/io/FileDescriptor;[BII)V" />
|
||||
</class>
|
||||
</package>
|
||||
|
||||
<package name="java/security">
|
||||
<class name="AccessControlContext">
|
||||
<method name="getInheritedAccessControlContext"
|
||||
descriptor="()Ljava/security/AccessControlContext;">
|
||||
<new def="x" class="Ljava/lang/Object" />
|
||||
<return value="x" />
|
||||
<poison
|
||||
reason="questionable model of java/security/AccessControlContext/getInheritedAccessControlContext"
|
||||
level="moderate" />
|
||||
</method>
|
||||
</class>
|
||||
<class name="AccessController">
|
||||
<method name="doPrivileged"
|
||||
descriptor="(Ljava/security/PrivilegedAction;)Ljava/lang/Object;"
|
||||
static="true">
|
||||
<call type="interface" name="run"
|
||||
class="Ljava/security/PrivilegedAction"
|
||||
descriptor="()Ljava/lang/Object;" def="x" arg0="arg0" />
|
||||
<return value="x" />
|
||||
<new def="y"
|
||||
class="Ljava/security/PrivilegedActionException" />
|
||||
<throw value="y" />
|
||||
<poison
|
||||
reason="incorrect model of java/security/AccessController/doPrivileged"
|
||||
level="severe" />
|
||||
</method>
|
||||
<method name="doPrivileged"
|
||||
descriptor="(Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;"
|
||||
static="true">
|
||||
<call type="interface" name="run"
|
||||
class="Ljava/security/PrivilegedExceptionAction"
|
||||
descriptor="()Ljava/lang/Object;" def="x" arg0="arg0" />
|
||||
<return value="x" />
|
||||
<new def="y"
|
||||
class="Ljava/security/PrivilegedActionException" />
|
||||
<throw value="y" />
|
||||
<poison
|
||||
reason="incorrect model of java/security/AccessController/doPrivileged"
|
||||
level="severe" />
|
||||
</method>
|
||||
<method name="doPrivileged"
|
||||
descriptor="(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;"
|
||||
static="true">
|
||||
<call type="interface" name="run"
|
||||
class="Ljava/security/PrivilegedAction"
|
||||
descriptor="()Ljava/lang/Object;" def="x" arg0="arg0" />
|
||||
<return value="x" />
|
||||
<new def="y"
|
||||
class="Ljava/security/PrivilegedActionException" />
|
||||
<throw value="y" />
|
||||
<poison
|
||||
reason="incorrect model of java/security/AccessController/doPrivileged"
|
||||
level="severe" />
|
||||
</method>
|
||||
<method name="doPrivileged"
|
||||
descriptor="(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;"
|
||||
static="true">
|
||||
<call type="interface" name="run"
|
||||
class="Ljava/security/PrivilegedExceptionAction"
|
||||
descriptor="()Ljava/lang/Object;" def="x" arg0="arg0" />
|
||||
<return value="x" />
|
||||
<new def="y"
|
||||
class="Ljava/security/PrivilegedActionException" />
|
||||
<throw value="y" />
|
||||
<poison
|
||||
reason="incorrect model of java/security/AccessController/doPrivileged"
|
||||
level="severe" />
|
||||
</method>
|
||||
<method name="getStackAccessControlContext"
|
||||
descriptor="()Ljava/security/AccessControlContext;"
|
||||
static="true">
|
||||
<new def="x"
|
||||
class="Ljava/security/AccessControlContext" />
|
||||
<return value="x" />
|
||||
<poison
|
||||
reason="questionable model of java/security/AccessController/getStackAccessControlContext"
|
||||
level="moderate" />
|
||||
</method>
|
||||
</class>
|
||||
</package>
|
||||
|
||||
<package name="java/util">
|
||||
<class name="TimeZone">
|
||||
<method name="getSystemTimeZoneID"
|
||||
descriptor="(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"
|
||||
static="true">
|
||||
<new def="x" class="Ljava/lang/String" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
</class>
|
||||
</package>
|
||||
|
||||
<package name="java/util/logging">
|
||||
<class name="FileHandler">
|
||||
<method name="isSetUID" descriptor="()Z" static="true" />
|
||||
</class>
|
||||
</package>
|
||||
|
||||
<package name="java/util/prefs">
|
||||
<class name="FileSystemPreferences">
|
||||
<method name="chmod" descriptor="(Ljava/lang/String;I)I"
|
||||
static="true" />
|
||||
<method name="lockFile0"
|
||||
descriptor="(Ljava/lang/String;IZ)[I" static="true">
|
||||
<constant name="size" type="int" value="1" />
|
||||
<new def="x" class="[I" size="size"/>
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="unlockFile0" descriptor="(I)I"
|
||||
static="true" />
|
||||
</class>
|
||||
</package>
|
||||
|
||||
<package name="sun/misc">
|
||||
<class name="AtomicLongCSImpl">
|
||||
<method name="attemptUpdate" descriptor="(JJ)Z" />
|
||||
</class>
|
||||
<class name="AtomicLong">
|
||||
<method name="VMSupportsCS8" descriptor="()Z"
|
||||
static="true" />
|
||||
</class>
|
||||
<class name="Signal">
|
||||
<method name="handle0" descriptor="(IJ)J" static="true" />
|
||||
<method name="findSignal"
|
||||
descriptor="(Ljava/lang/String;)I" static="true" />
|
||||
</class>
|
||||
<class name="Unsafe" allocatable="true">
|
||||
<method name="getUnsafe" descriptor="()Lsun/misc/Unsafe"
|
||||
static="true">
|
||||
<new def="x" class="Lsun/misc/Unsafe" />
|
||||
<return value="x" />
|
||||
</method>
|
||||
<method name="allocateMemory" descriptor="(J)J" />
|
||||
<method name="copyMemory" descriptor="(JJJ)V" />
|
||||
<method name="freeMemory" descriptor="(J)V" />
|
||||
<method name="objectFieldOffset"
|
||||
descriptor="(Ljava/lang/reflect/Field;)J" />
|
||||
<method name="getBoolean" descriptor="(J)Z" />
|
||||
<method name="getByte" descriptor="(J)B" />
|
||||
<method name="getChar" descriptor="(J)C" />
|
||||
<method name="getDouble" descriptor="(J)D" />
|
||||
<method name="getFloat" descriptor="(J)F" />
|
||||
<method name="getInt" descriptor="(J)I" />
|
||||
<method name="getLong" descriptor="(J)J" />
|
||||
<method name="getShort" descriptor="(J)S" />
|
||||
<method name="getBoolean"
|
||||
descriptor="(Ljava/lang/Object;J)Z" />
|
||||
<method name="getByte"
|
||||
descriptor="(Ljava/lang/Object;J)B" />
|
||||
<method name="getChar"
|
||||
descriptor="(Ljava/lang/Object;J)C" />
|
||||
<method name="getDouble"
|
||||
descriptor="(Ljava/lang/Object;J)D" />
|
||||
<method name="getFloat"
|
||||
descriptor="(Ljava/lang/Object;J)F" />
|
||||
<method name="getInt"
|
||||
descriptor="(Ljava/lang/Object;J)I" />
|
||||
<method name="getLong"
|
||||
descriptor="(Ljava/lang/Object;J)J" />
|
||||
<method name="getShort"
|
||||
descriptor="(Ljava/lang/Object;J)S" />
|
||||
<method name="putBoolean" descriptor="(JZ)V" />
|
||||
<method name="putByte" descriptor="(JB)V" />
|
||||
<method name="putChar" descriptor="(JC)V" />
|
||||
<method name="putDouble" descriptor="(JD)V" />
|
||||
<method name="putFloat" descriptor="(JF)V" />
|
||||
<method name="putInt" descriptor="(JI)V" />
|
||||
<method name="putLong" descriptor="(JJ)V" />
|
||||
<method name="putShort" descriptor="(JS)V" />
|
||||
<method name="registerNatives" descriptor="()V"
|
||||
static="true" />
|
||||
</class>
|
||||
</package>
|
||||
|
||||
<package name="sun/nio/ch">
|
||||
<class name="IOUtil">
|
||||
<method name="initIDs" descriptor="()V" static="true" />
|
||||
</class>
|
||||
<class name="FileDispatcher">
|
||||
<method name="init" descriptor="()V" static="true" />
|
||||
</class>
|
||||
<class name="FileChannelImpl">
|
||||
<method name="lock0"
|
||||
descriptor="(Ljava/io/FileDescriptor;ZJJZ)I" />
|
||||
<method name="initIDs" descriptor="()J" static="true" />
|
||||
</class>
|
||||
</package>
|
||||
|
||||
</classloader>
|
||||
</summary-spec>
|
|
@ -0,0 +1,52 @@
|
|||
###############################################################################
|
||||
# WALA property file
|
||||
# This file defines the default settings for the core WALA Engine
|
||||
###############################################################################
|
||||
|
||||
################# Mandatory settings without default value ####################
|
||||
|
||||
#####
|
||||
# Identify the directory where Java Runtime libraries are located.
|
||||
# For instance, on a windows OS it's typically C:/Progra~1/Java/j2reYourVersion/lib
|
||||
#
|
||||
# N.B. This directory must contain a valid core.jar (or rt.jar for older VMs)
|
||||
# On IBM 1.4.x SDKs, this means you need to specify Java14x/jre/lib and not
|
||||
# Java14x/lib!
|
||||
#
|
||||
# Info: Location must be absolute.
|
||||
#####
|
||||
java_runtime_dir = Your location
|
||||
|
||||
################### Mandatory settings with default value ######################
|
||||
|
||||
##### Default output dir
|
||||
# Identify directory where all generated files without absolute path will be located.
|
||||
# Default value: results [Non absolute path are relative to WALA home location]
|
||||
# Info: Can be absolute or relative.
|
||||
#####
|
||||
#output_dir = Your location
|
||||
|
||||
############################ Optional settings ################################
|
||||
|
||||
#####
|
||||
# Identify the directory where J2EE standard libraries are located.
|
||||
# Required only if you ask to analyze J2EE code.
|
||||
# No default value.
|
||||
# Info: Location must be absolute.
|
||||
#####
|
||||
#j2ee_runtime_dir = Your location
|
||||
|
||||
#####
|
||||
# Identify the directory where Eclipse plugins are installed
|
||||
# Required only if you ask to analyze Eclipse plugins.
|
||||
# No default value.
|
||||
# Info: Location must be absolute.
|
||||
#####
|
||||
#eclipse_plugins_dir = Your location
|
||||
|
||||
##### Report file
|
||||
# Identify file name where to output WALA trace file.
|
||||
# Default value: wala_report.txt [Non absolute path are relative to 'output.dir' variable value]
|
||||
# Info: Can be absolute or relative.
|
||||
#####
|
||||
#WALA_report = Your file name
|
|
@ -0,0 +1,27 @@
|
|||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.runtime_3.2.0.v20060603.jar[~org/eclipse/core/internal/preferences/legacy/*;~org/eclipse/core/internal/runtime/*;+org/eclipse/core/runtime/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.osgi_3.2.0.v20060601.jar[+org/eclipse/osgi/event/*;+org/eclipse/osgi/framework/console/*;+org/eclipse/osgi/framework/eventmgr/*;+org/eclipse/osgi/framework/log/*;+org/eclipse/osgi/service/datalocation/*;+org/eclipse/osgi/service/debug/*;+org/eclipse/osgi/service/environment/*;+org/eclipse/osgi/service/localization/*;+org/eclipse/osgi/service/pluginconversion/*;+org/eclipse/osgi/service/resolver/*;+org/eclipse/osgi/service/runnable/*;+org/eclipse/osgi/service/urlconversion/*;+org/eclipse/osgi/storagemanager/*;+org/eclipse/osgi/util/*;+org/osgi/framework/*;+org/osgi/service/condpermadmin/*;+org/osgi/service/packageadmin/*;+org/osgi/service/permissionadmin/*;+org/osgi/service/startlevel/*;+org/osgi/service/url/*;+org/osgi/util/tracker/*;~org/eclipse/core/runtime/adaptor/*;~org/eclipse/core/runtime/internal/adaptor/*;~org/eclipse/core/runtime/internal/stats/*;~org/eclipse/osgi/baseadaptor/*;~org/eclipse/osgi/baseadaptor/bundlefile/*;~org/eclipse/osgi/baseadaptor/hooks/*;~org/eclipse/osgi/baseadaptor/loader/*;~org/eclipse/osgi/framework/adaptor/*;~org/eclipse/osgi/framework/debug/*;~org/eclipse/osgi/framework/internal/core/*;~org/eclipse/osgi/framework/internal/protocol/*;~org/eclipse/osgi/framework/internal/protocol/bundleentry/*;~org/eclipse/osgi/framework/internal/protocol/bundleresource/*;~org/eclipse/osgi/framework/internal/protocol/reference/*;~org/eclipse/osgi/framework/internal/reliablefile/*;~org/eclipse/osgi/framework/launcher/*;~org/eclipse/osgi/framework/util/*;~org/eclipse/osgi/internal/baseadaptor/*;~org/eclipse/osgi/internal/module/*;~org/eclipse/osgi/internal/profile/*;~org/eclipse/osgi/internal/resolver/*;~org/eclipse/osgi/internal/verifier/*;~org/eclipse/osgi/internal/provisional/verifier/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.equinox.common_3.2.0.v20060603.jar[~org/eclipse/core/internal/runtime/*;~org/eclipse/core/internal/boot/*;+org/eclipse/core/runtime/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.jobs_3.2.0.v20060603.jar[~org/eclipse/core/internal/jobs/*;+org/eclipse/core/runtime/jobs/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0.v20060603/runtime_registry_compatibility.jar[~org/eclipse/core/internal/registry/*;~org/eclipse/core/internal/registry/osgi/*;~org/eclipse/core/internal/registry/spi/*;+org/eclipse/core/runtime/*;+org/eclipse/core/runtime/dynamichelpers/*;+org/eclipse/core/runtime/spi/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0.v20060603[~org/eclipse/core/internal/registry/*;~org/eclipse/core/internal/registry/osgi/*;~org/eclipse/core/internal/registry/spi/*;+org/eclipse/core/runtime/*;+org/eclipse/core/runtime/dynamichelpers/*;+org/eclipse/core/runtime/spi/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.equinox.registry_3.2.0.v20060601.jar[~org/eclipse/core/internal/registry/*;~org/eclipse/core/internal/registry/osgi/*;~org/eclipse/core/internal/registry/spi/*;+org/eclipse/core/runtime/*;+org/eclipse/core/runtime/dynamichelpers/*;+org/eclipse/core/runtime/spi/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.apache.xerces_2.8.0.v200606131651/resolver.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.apache.xerces_2.8.0.v200606131651/xercesImpl.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.apache.xerces_2.8.0.v200606131651/xml-apis.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.equinox.preferences_3.2.0.v20060601.jar[~org/eclipse/core/internal/preferences/*;~org/eclipse/core/internal/preferences/exchange/*;+org/eclipse/core/runtime/preferences/*;+org/osgi/service/prefs/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0.v20060603/@dot[~org/eclipse/core/internal/registry/*;~org/eclipse/core/internal/registry/osgi/*;~org/eclipse/core/internal/registry/spi/*;+org/eclipse/core/runtime/*;+org/eclipse/core/runtime/dynamichelpers/*;+org/eclipse/core/runtime/spi/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.contenttype_3.2.0.v20060603.jar[~org/eclipse/core/internal/content/*;+org/eclipse/core/runtime/content/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.runtime.compatibility.auth_3.2.0.v20060601.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.emf.ecore_2.2.0.v200606271057.jar[+org/eclipse/emf/ecore/*;+org/eclipse/emf/ecore/impl/*;+org/eclipse/emf/ecore/plugin/*;+org/eclipse/emf/ecore/resource/*;+org/eclipse/emf/ecore/resource/impl/*;+org/eclipse/emf/ecore/util/*;+org/eclipse/emf/ecore/xml/namespace/*;+org/eclipse/emf/ecore/xml/namespace/impl/*;+org/eclipse/emf/ecore/xml/namespace/util/*;+org/eclipse/emf/ecore/xml/type/*;+org/eclipse/emf/ecore/xml/type/impl/*;+org/eclipse/emf/ecore/xml/type/internal/*;+org/eclipse/emf/ecore/xml/type/util/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.emf.common_2.2.0.v200606271057.jar[+org/eclipse/emf/common/*;+org/eclipse/emf/common/archive/*;+org/eclipse/emf/common/command/*;+org/eclipse/emf/common/notify/*;+org/eclipse/emf/common/notify/impl/*;+org/eclipse/emf/common/util/*;?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.resources_3.2.0.v20060603.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.resources.compatibility_3.2.0.v20060603.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.resources.win32_3.2.0.v20060603.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.runtime.compatibility_3.1.100.v20060603.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.update.configurator_3.2.0.v20060605.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.ant.core_3.1.100.v20060531.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.variables_3.1.100.v20060605.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.expressions_3.2.0.v20060605-1400.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.filesystem_1.0.0.v20060603.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.core.filesystem.win32.x86_1.0.0.v20060603.jar[?**/*]
|
||||
#ADAPTER#ACCESS#eclipse/plugins/org.eclipse.emf.ecore.xmi_2.2.0.v200606271057.jar[+org/eclipse/emf/ecore/xmi/*;+org/eclipse/emf/ecore/xmi/impl/*;+org/eclipse/emf/ecore/xmi/util/*;?**/*]
|
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
PLUGINNAME=core WALA analysis engine
|
||||
VENDORNAME=IBMproviderName = www.example.org
|
||||
pluginName = PatternSet Model
|
||||
# ====================================================================
|
||||
providerName = www.example.org
|
||||
|
|
@ -0,0 +1,561 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.pointers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.analysis.reflection.Malleable;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IField;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CompoundIterator;
|
||||
import com.ibm.wala.util.IntFunction;
|
||||
import com.ibm.wala.util.IntMapIterator;
|
||||
import com.ibm.wala.util.collections.EmptyIterator;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.graph.AbstractNumberedGraph;
|
||||
import com.ibm.wala.util.graph.EdgeManager;
|
||||
import com.ibm.wala.util.graph.NodeManager;
|
||||
import com.ibm.wala.util.graph.NumberedGraph;
|
||||
import com.ibm.wala.util.graph.NumberedNodeManager;
|
||||
import com.ibm.wala.util.graph.impl.NumberedNodeIterator;
|
||||
import com.ibm.wala.util.intset.BasicNonNegativeIntRelation;
|
||||
import com.ibm.wala.util.intset.IBinaryNonNegativeIntRelation;
|
||||
import com.ibm.wala.util.intset.IntSet;
|
||||
import com.ibm.wala.util.intset.MutableMapping;
|
||||
import com.ibm.wala.util.intset.MutableSparseIntSet;
|
||||
import com.ibm.wala.util.intset.OrdinalSet;
|
||||
import com.ibm.wala.util.intset.OrdinalSetMapping;
|
||||
import com.ibm.wala.util.intset.SparseIntSet;
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*/
|
||||
public class BasicHeapGraph extends HeapGraph {
|
||||
|
||||
private final static boolean VERBOSE = true;
|
||||
|
||||
private final static int VERBOSE_INTERVAL = 10000;
|
||||
|
||||
/**
|
||||
* Pointer analysis solution
|
||||
*/
|
||||
private final PointerAnalysis pointerAnalysis;
|
||||
|
||||
/**
|
||||
* The backing graph
|
||||
*/
|
||||
private final NumberedGraph<Object> G;
|
||||
|
||||
/**
|
||||
* governing call graph
|
||||
*/
|
||||
private final CallGraph callGraph;
|
||||
|
||||
/**
|
||||
* @param P
|
||||
* governing pointer analysis
|
||||
*/
|
||||
public BasicHeapGraph(final PointerAnalysis P, final CallGraph callGraph) {
|
||||
super(P.getHeapModel());
|
||||
this.pointerAnalysis = P;
|
||||
this.callGraph = callGraph;
|
||||
|
||||
final OrdinalSetMapping<PointerKey> pointerKeys = getPointerKeys(P);
|
||||
final NumberedNodeManager<Object> nodeMgr = new NumberedNodeManager<Object>() {
|
||||
public Iterator<Object> iterateNodes() {
|
||||
return new CompoundIterator<Object>(pointerKeys.iterator(), P.getInstanceKeyMapping().iterator());
|
||||
}
|
||||
|
||||
public int getNumberOfNodes() {
|
||||
return pointerKeys.getMappingSize() + P.getInstanceKeyMapping().getMappingSize();
|
||||
}
|
||||
|
||||
public void addNode(Object n) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public void removeNode(Object n) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public int getNumber(Object N) {
|
||||
if (N instanceof PointerKey) {
|
||||
return pointerKeys.getMappedIndex((PointerKey) N);
|
||||
} else {
|
||||
if (Assertions.verifyAssertions) {
|
||||
if (!(N instanceof InstanceKey)) {
|
||||
Assertions.UNREACHABLE(N.getClass().toString());
|
||||
}
|
||||
}
|
||||
int inumber = P.getInstanceKeyMapping().getMappedIndex((InstanceKey) N);
|
||||
return (inumber == -1) ? -1 : inumber + pointerKeys.getMappingSize();
|
||||
}
|
||||
}
|
||||
|
||||
public Object getNode(int number) {
|
||||
if (number >= pointerKeys.getMappingSize()) {
|
||||
return P.getInstanceKeyMapping().getMappedObject(number - pointerKeys.getMappingSize());
|
||||
} else {
|
||||
return pointerKeys.getMappedObject(number);
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxNumber() {
|
||||
return getNumberOfNodes() - 1;
|
||||
}
|
||||
|
||||
public boolean containsNode(Object n) {
|
||||
return getNumber(n) != -1;
|
||||
}
|
||||
|
||||
public Iterator<Object> iterateNodes(IntSet s) {
|
||||
return new NumberedNodeIterator<Object>(s, this);
|
||||
}
|
||||
};
|
||||
|
||||
final IBinaryNonNegativeIntRelation pred = computePredecessors(nodeMgr);
|
||||
final IntFunction<Object> toNode = new IntFunction<Object>() {
|
||||
public Object apply(int i) {
|
||||
return nodeMgr.getNode(i);
|
||||
}
|
||||
};
|
||||
|
||||
this.G = new AbstractNumberedGraph<Object>() {
|
||||
private final EdgeManager<Object> edgeMgr = new EdgeManager<Object>() {
|
||||
public Iterator<Object> getPredNodes(Object N) {
|
||||
int n = nodeMgr.getNumber(N);
|
||||
IntSet p = pred.getRelated(n);
|
||||
if (p == null) {
|
||||
return EmptyIterator.instance();
|
||||
} else {
|
||||
return new IntMapIterator<Object>(p.intIterator(), toNode);
|
||||
}
|
||||
}
|
||||
|
||||
public int getPredNodeCount(Object N) {
|
||||
int n = nodeMgr.getNumber(N);
|
||||
return pred.getRelatedCount(n);
|
||||
}
|
||||
|
||||
public Iterator<? extends Object> getSuccNodes(Object N) {
|
||||
int[] succ = computeSuccNodeNumbers(N, nodeMgr);
|
||||
if (succ == null) {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
SparseIntSet s = new MutableSparseIntSet(succ);
|
||||
return new IntMapIterator<Object>(s.intIterator(), toNode);
|
||||
}
|
||||
|
||||
public int getSuccNodeCount(Object N) {
|
||||
int[] succ = computeSuccNodeNumbers(N, nodeMgr);
|
||||
return succ == null ? 0 : succ.length;
|
||||
}
|
||||
|
||||
public void addEdge(Object src, Object dst) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public void removeEdge(Object src, Object dst) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public void removeAllIncidentEdges(Object node) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public void removeIncomingEdges(Object node) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public void removeOutgoingEdges(Object node) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public boolean hasEdge(Object src, Object dst) {
|
||||
Assertions.UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
protected NodeManager<Object> getNodeManager() {
|
||||
return nodeMgr;
|
||||
}
|
||||
|
||||
protected EdgeManager<Object> getEdgeManager() {
|
||||
return edgeMgr;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private OrdinalSetMapping<PointerKey> getPointerKeys(PointerAnalysis pointerAnalysis) {
|
||||
MutableMapping<PointerKey> result = new MutableMapping<PointerKey>();
|
||||
|
||||
for (Iterator it = pointerAnalysis.getPointerKeys().iterator(); it.hasNext();) {
|
||||
PointerKey p = (PointerKey) it.next();
|
||||
result.add(p);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private int[] computeSuccNodeNumbers(Object N, NumberedNodeManager<Object> nodeManager) {
|
||||
if (N instanceof PointerKey) {
|
||||
PointerKey P = (PointerKey) N;
|
||||
OrdinalSet S = pointerAnalysis.getPointsToSet(P);
|
||||
int[] result = new int[S.size()];
|
||||
int i = 0;
|
||||
for (Iterator it = S.iterator(); it.hasNext();) {
|
||||
result[i] = nodeManager.getNumber(it.next());
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
} else if (N instanceof InstanceKey) {
|
||||
InstanceKey I = (InstanceKey) N;
|
||||
TypeReference T = I.getConcreteType().getReference();
|
||||
|
||||
if (Assertions.verifyAssertions) {
|
||||
if (T == null) {
|
||||
Assertions._assert(T != null, "null concrete type from " + I.getClass());
|
||||
}
|
||||
}
|
||||
if (T.isArrayType()) {
|
||||
PointerKey p = getHeapModel().getPointerKeyForArrayContents(I);
|
||||
if (p == null || !nodeManager.containsNode(p)) {
|
||||
return null;
|
||||
} else {
|
||||
return new int[] { nodeManager.getNumber(p) };
|
||||
}
|
||||
} else if (!Malleable.isMalleable(T)) {
|
||||
IClass klass = getHeapModel().getClassHierarchy().lookupClass(T);
|
||||
if (Assertions.verifyAssertions) {
|
||||
if (klass == null) {
|
||||
Assertions._assert(klass != null, "null klass for type " + T);
|
||||
}
|
||||
}
|
||||
MutableSparseIntSet result = new MutableSparseIntSet();
|
||||
try {
|
||||
for (Iterator<IField> it = klass.getAllInstanceFields().iterator(); it.hasNext();) {
|
||||
IField f = it.next();
|
||||
if (!f.getFieldReference().getFieldType().isPrimitiveType()) {
|
||||
PointerKey p = getHeapModel().getPointerKeyForInstanceField(I, f);
|
||||
if (p != null && nodeManager.containsNode(p)) {
|
||||
result.add(nodeManager.getNumber(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassHierarchyException e) {
|
||||
// uh oh. skip it for now.
|
||||
}
|
||||
return result.toIntArray();
|
||||
} else {
|
||||
Assertions._assert(Malleable.isMalleable(T));
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
Assertions.UNREACHABLE("Unexpected type: " + N.getClass());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return R, y \in R(x,y) if the node y is a predecessor of node x
|
||||
*/
|
||||
private IBinaryNonNegativeIntRelation computePredecessors(NumberedNodeManager<Object> nodeManager) {
|
||||
BasicNonNegativeIntRelation R = new BasicNonNegativeIntRelation(new byte[] { BasicNonNegativeIntRelation.SIMPLE },
|
||||
BasicNonNegativeIntRelation.SIMPLE);
|
||||
|
||||
// we split the following loops to improve temporal locality,
|
||||
// particularly for locals
|
||||
computePredecessorsForNonLocals(nodeManager, R);
|
||||
computePredecessorsForLocals(nodeManager, R);
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
private void computePredecessorsForNonLocals(NumberedNodeManager<Object> nodeManager, BasicNonNegativeIntRelation R) {
|
||||
// Note: we run this loop backwards on purpose, to avoid lots of resizing of
|
||||
// bitvectors
|
||||
// in the backing relation. i.e., we will add the biggest bits first.
|
||||
// pretty damn tricky.
|
||||
for (int i = nodeManager.getMaxNumber(); i >= 0; i--) {
|
||||
if (VERBOSE) {
|
||||
if (i % VERBOSE_INTERVAL == 0) {
|
||||
System.err.println("Building HeapGraph: " + i);
|
||||
}
|
||||
}
|
||||
Object n = nodeManager.getNode(i);
|
||||
if (!(n instanceof LocalPointerKey)) {
|
||||
int[] succ = computeSuccNodeNumbers(n, nodeManager);
|
||||
if (succ != null) {
|
||||
for (int z = 0; z < succ.length; z++) {
|
||||
int j = succ[z];
|
||||
R.add(j, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* traverse locals in order, first by node, then by value number: attempt to
|
||||
* improve locality
|
||||
*/
|
||||
private void computePredecessorsForLocals(NumberedNodeManager<Object> nodeManager, BasicNonNegativeIntRelation R) {
|
||||
|
||||
ArrayList<LocalPointerKey> list = new ArrayList<LocalPointerKey>();
|
||||
for (Iterator it = nodeManager.iterateNodes(); it.hasNext();) {
|
||||
Object n = it.next();
|
||||
if (n instanceof LocalPointerKey) {
|
||||
list.add((LocalPointerKey) n);
|
||||
}
|
||||
}
|
||||
Object[] arr = list.toArray();
|
||||
Arrays.sort(arr, new LocalPointerComparator());
|
||||
|
||||
for (int i = 0; i < arr.length; i++) {
|
||||
if (VERBOSE) {
|
||||
if (i % VERBOSE_INTERVAL == 0) {
|
||||
System.err.println("Building HeapGraph: " + i + " of " + arr.length);
|
||||
}
|
||||
}
|
||||
LocalPointerKey n = (LocalPointerKey) arr[i];
|
||||
int num = nodeManager.getNumber(n);
|
||||
int[] succ = computeSuccNodeNumbers(n, nodeManager);
|
||||
if (succ != null) {
|
||||
for (int z = 0; z < succ.length; z++) {
|
||||
int j = succ[z];
|
||||
R.add(j, num);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sorts local pointers by node, then value number
|
||||
*/
|
||||
private final class LocalPointerComparator implements Comparator<Object> {
|
||||
public int compare(Object arg1, Object arg2) {
|
||||
LocalPointerKey o1 = (LocalPointerKey)arg1;
|
||||
LocalPointerKey o2 = (LocalPointerKey)arg2;
|
||||
if (o1.getNode().equals(o2.getNode())) {
|
||||
return o1.getValueNumber() - o2.getValueNumber();
|
||||
} else {
|
||||
return callGraph.getNumber(o1.getNode()) - callGraph.getNumber(o2.getNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NumberedNodeManager#getNumber(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public int getNumber(Object N) {
|
||||
return G.getNumber(N);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NumberedNodeManager#getNode(int)
|
||||
*/
|
||||
public Object getNode(int number) {
|
||||
return G.getNode(number);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NumberedNodeManager#getMaxNumber()
|
||||
*/
|
||||
public int getMaxNumber() {
|
||||
return G.getMaxNumber();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#iterateNodes()
|
||||
*/
|
||||
public Iterator<? extends Object> iterateNodes() {
|
||||
return G.iterateNodes();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#getNumberOfNodes()
|
||||
*/
|
||||
public int getNumberOfNodes() {
|
||||
return G.getNumberOfNodes();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodes(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public Iterator<? extends Object> getPredNodes(Object N) {
|
||||
return G.getPredNodes(N);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodeCount(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public int getPredNodeCount(Object N) {
|
||||
return G.getPredNodeCount(N);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodes(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public Iterator<? extends Object> getSuccNodes(Object N) {
|
||||
return G.getSuccNodes(N);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodeCount(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public int getSuccNodeCount(Object N) {
|
||||
return G.getSuccNodeCount(N);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#addNode(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public void addNode(Object n) {
|
||||
Assertions.UNREACHABLE();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#remove(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public void removeNode(Object n) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public void addEdge(Object from, Object to) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public void removeEdge(Object from, Object to) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public boolean hasEdge(Object from, Object to) {
|
||||
Assertions.UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeAllIncidentEdges(Object node) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#containsNode(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public boolean containsNode(Object N) {
|
||||
return G.containsNode(N);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer result = new StringBuffer();
|
||||
result.append("Nodes:\n");
|
||||
for (int i = 0; i < getMaxNumber(); i++) {
|
||||
Object node = getNode(i);
|
||||
if (node != null) {
|
||||
result.append(i).append(" ").append(node).append("\n");
|
||||
}
|
||||
}
|
||||
result.append("Edges:\n");
|
||||
for (int i = 0; i < getMaxNumber(); i++) {
|
||||
Object node = getNode(i);
|
||||
if (node != null) {
|
||||
result.append(i).append(" -> ");
|
||||
for (Iterator it = getSuccNodes(node); it.hasNext();) {
|
||||
Object s = it.next();
|
||||
result.append(getNumber(s)).append(" ");
|
||||
}
|
||||
result.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public void removeIncomingEdges(Object node) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*/
|
||||
public void removeOutgoingEdges(Object node) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public IntSet getSuccNodeNumbers(Object node) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
public IntSet getPredNodeNumbers(Object node) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.pointers;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.propagation.HeapModel;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.util.collections.Filter;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.graph.NumberedGraph;
|
||||
import com.ibm.wala.util.graph.impl.NumberedNodeIterator;
|
||||
import com.ibm.wala.util.graph.traverse.DFS;
|
||||
import com.ibm.wala.util.intset.IntSet;
|
||||
|
||||
/**
|
||||
* A Graph view of a pointer analysis solution.
|
||||
*
|
||||
* Nodes in the Graph are PointerKeys and InstanceKeys.
|
||||
*
|
||||
* There is an edge from a PointerKey P to an InstanceKey I iff the PointerAnalysis
|
||||
* indicates that P may point to I.
|
||||
*
|
||||
* There is an edge from an InstanceKey I to a PointerKey P iff
|
||||
* - P represents a field of an object instance modelled by I, or
|
||||
* - P represents the array contents of array instance I.
|
||||
*
|
||||
* @author sfink
|
||||
*
|
||||
*/
|
||||
public abstract class HeapGraph implements NumberedGraph<Object> {
|
||||
|
||||
private final HeapModel hm;
|
||||
|
||||
protected HeapGraph(HeapModel hm) {
|
||||
this.hm = hm;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.util.graph.NumberedNodeManager#iterateNodes(com.ibm.wala.util.intset.IntSet)
|
||||
*/
|
||||
public Iterator<Object> iterateNodes(IntSet s) {
|
||||
return new NumberedNodeIterator<Object>(s,this);
|
||||
}
|
||||
|
||||
public Collection<Object> getReachableInstances(Set<Object> roots) {
|
||||
Filter f = new Filter() {
|
||||
public boolean accepts(Object o) {
|
||||
return (o instanceof InstanceKey);
|
||||
}
|
||||
};
|
||||
return DFS.getReachableNodes(this, roots, f);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.util.graph.Graph#removeNode(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public void removeNodeAndEdges(Object N) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the heap model used in this pointer analysis.
|
||||
*/
|
||||
public HeapModel getHeapModel() {
|
||||
return hm;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
This package defines utilities to help navigate pointer analysis results.
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,61 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.reflection;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction.Visitor;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* A mapping from CallSiteReference to SSA InvokeInstruction.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class CallSiteMap {
|
||||
|
||||
/**
|
||||
* f: CallSiteReference -> InvokeInstruction
|
||||
*/
|
||||
private final Map<CallSiteReference, SSAInvokeInstruction> map = HashMapFactory.make();
|
||||
|
||||
/**
|
||||
* @param ir
|
||||
*/
|
||||
public CallSiteMap(final IR ir) {
|
||||
Visitor v = new Visitor() {
|
||||
public void visitInvoke(SSAInvokeInstruction instruction) {
|
||||
CallSiteReference site = instruction.getCallSite();
|
||||
map.put(site, instruction);
|
||||
}
|
||||
};
|
||||
SSAInstruction[] instructions = ir.getInstructions();
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
if (instructions[i] != null) {
|
||||
instructions[i].visit(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param site
|
||||
* @return the InvokeInstruction corresponding to the call site.
|
||||
*/
|
||||
public SSAInvokeInstruction getInstructionForSite(CallSiteReference site) {
|
||||
SSAInvokeInstruction result = map.get(site);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.analysis.reflection;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.callgraph.ContextItem;
|
||||
import com.ibm.wala.ipa.callgraph.ContextKey;
|
||||
|
||||
/**
|
||||
*
|
||||
* A context which is a <CGNode, CallSiteReference> pair
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class CallerSiteContext implements Context {
|
||||
private final CGNode caller;
|
||||
private final CallSiteReference site;
|
||||
|
||||
/**
|
||||
* @param caller
|
||||
* @param site
|
||||
*/
|
||||
public CallerSiteContext(CGNode caller, CallSiteReference site) {
|
||||
this.caller = caller;
|
||||
this.site = site;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ipa.callgraph.Context#get(com.ibm.wala.ipa.callgraph.ContextKey)
|
||||
*/
|
||||
public ContextItem get(ContextKey name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "[CallerSiteContext: " + caller + "," + site.getProgramCounter() + "]";
|
||||
}
|
||||
|
||||
public CGNode getCaller() {
|
||||
return caller;
|
||||
}
|
||||
|
||||
public CallSiteReference getSite() {
|
||||
return site;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object arg0) {
|
||||
if (getClass().equals(arg0.getClass())) {
|
||||
CallerSiteContext other = (CallerSiteContext) arg0;
|
||||
return caller.equals(other.caller) && (site.equals(other.site));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return site.hashCode() + 839 * caller.hashCode();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,362 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.reflection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cfg.ControlFlowGraph;
|
||||
import com.ibm.wala.cfg.InducedCFG;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.CodeScanner;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IField;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.classLoader.NewSiteReference;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.callgraph.ContextUtil;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.ipa.summaries.SyntheticIR;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
import com.ibm.wala.ssa.DefUse;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAArrayLengthInstruction;
|
||||
import com.ibm.wala.ssa.SSAGetInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSANewInstruction;
|
||||
import com.ibm.wala.ssa.SSAOptions;
|
||||
import com.ibm.wala.ssa.SSAPutInstruction;
|
||||
import com.ibm.wala.ssa.SSAReturnInstruction;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.Atom;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.NonNullSingletonIterator;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* A context interpreter for java.lang.Object.clone
|
||||
*
|
||||
* TODO: The current implementation does not model CloneNotSupportedExceptions
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class CloneInterpreter implements SSAContextInterpreter {
|
||||
|
||||
/**
|
||||
* Comment for <code>cloneAtom</code>
|
||||
*/
|
||||
public final static Atom cloneAtom = Atom.findOrCreateUnicodeAtom("clone");
|
||||
|
||||
private final static Descriptor cloneDesc = Descriptor.findOrCreateUTF8("()Ljava/lang/Object;");
|
||||
|
||||
/**
|
||||
* Comment for <code>CLONE</code>
|
||||
*/
|
||||
public final static MethodReference CLONE = MethodReference.findOrCreate(TypeReference.JavaLangObject, cloneAtom, cloneDesc);
|
||||
|
||||
private final static TypeReference SYNTHETIC_SYSTEM = TypeReference.findOrCreate(ClassLoaderReference.Primordial, TypeName
|
||||
.string2TypeName("Lcom/ibm/wala/model/java/lang/System"));
|
||||
|
||||
private final static Atom arraycopyAtom = Atom.findOrCreateUnicodeAtom("arraycopy");
|
||||
|
||||
private final static Descriptor arraycopyDesc = Descriptor.findOrCreateUTF8("(Ljava/lang/Object;Ljava/lang/Object;)V");
|
||||
|
||||
private final static MethodReference SYNTHETIC_ARRAYCOPY = MethodReference.findOrCreate(SYNTHETIC_SYSTEM, arraycopyAtom,
|
||||
arraycopyDesc);
|
||||
|
||||
/**
|
||||
* If the type is an array, the program counter of the synthesized call to
|
||||
* arraycopy. Doesn't really matter what it is.
|
||||
*/
|
||||
private final static int ARRAYCOPY_PC = 3;
|
||||
|
||||
private final static CallSiteReference ARRAYCOPY_SITE = CallSiteReference.make(ARRAYCOPY_PC, SYNTHETIC_ARRAYCOPY,
|
||||
IInvokeInstruction.Dispatch.STATIC);
|
||||
|
||||
private final static int NEW_PC = 0;
|
||||
|
||||
/**
|
||||
* Mapping from TypeReference -> IR TODO: Soft references?
|
||||
*/
|
||||
private Map<TypeReference, IR> IRCache = HashMapFactory.make();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.cfa.CFAContextInterpreter#getIR(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.detox.ipa.callgraph.Context,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public IR getIR(CGNode node, WarningSet warnings) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(understands(node));
|
||||
}
|
||||
IClass cls = ContextUtil.getConcreteClassFromContext(node.getContext());
|
||||
IR result = IRCache.get(cls.getReference());
|
||||
if (result == null) {
|
||||
result = makeIR(node.getMethod(), node.getContext(), cls, warnings);
|
||||
IRCache.put(cls.getReference(), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.cfa.CFAContextInterpreter#getNumberOfStatements(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.detox.ipa.callgraph.Context,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public int getNumberOfStatements(CGNode node, WarningSet warnings) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(understands(node));
|
||||
}
|
||||
return getIR(node, warnings).getInstructions().length;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.rta.RTAContextInterpreter#understands(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.detox.ipa.callgraph.Context)
|
||||
*/
|
||||
public boolean understands(CGNode node) {
|
||||
return (node.getMethod().getReference().equals(CLONE) && ContextUtil.getConcreteClassFromContext(node.getContext()) != null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.rta.RTAContextInterpreter#getAllocatedTypes(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.detox.ipa.callgraph.Context,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public Iterator<NewSiteReference> iterateNewSites(CGNode node, WarningSet warnings) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(understands(node));
|
||||
}
|
||||
IClass cls = ContextUtil.getConcreteClassFromContext(node.getContext());
|
||||
return new NonNullSingletonIterator<NewSiteReference>(NewSiteReference.make(NEW_PC, cls.getReference()));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.rta.RTAContextInterpreter#getCallSites(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.detox.ipa.callgraph.Context,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public Iterator<CallSiteReference> iterateCallSites(CGNode node, WarningSet warnings) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(understands(node));
|
||||
}
|
||||
return new NonNullSingletonIterator<CallSiteReference>(ARRAYCOPY_SITE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an array of statements that encode the behavior of the clone method
|
||||
* for a given type.
|
||||
*/
|
||||
private SSAInstruction[] makeStatements(IClass klass) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(klass != null);
|
||||
}
|
||||
|
||||
ArrayList<SSAInstruction> statements = new ArrayList<SSAInstruction>();
|
||||
// value number 1 is "this".
|
||||
int nextLocal = 2;
|
||||
|
||||
int retValue = nextLocal++;
|
||||
// value number of the result of the clone()
|
||||
NewSiteReference ref = NewSiteReference.make(NEW_PC, klass.getReference());
|
||||
SSANewInstruction N = null;
|
||||
if (klass.isArrayClass()) {
|
||||
int length = nextLocal++;
|
||||
statements.add(new SSAArrayLengthInstruction(length, 1));
|
||||
int[] sizes = new int[klass.getReference().getDimensionality()];
|
||||
Arrays.fill(sizes,length);
|
||||
N = new SSANewInstruction(retValue, ref, sizes);
|
||||
} else {
|
||||
N = new SSANewInstruction(retValue, ref);
|
||||
}
|
||||
statements.add(N);
|
||||
|
||||
int exceptionValue = nextLocal++;
|
||||
|
||||
if (klass.getReference().isArrayType()) {
|
||||
// generate a synthetic arraycopy from this (v.n. 1) to the clone
|
||||
int[] params = new int[2];
|
||||
params[0] = 1;
|
||||
params[1] = retValue;
|
||||
SSAInvokeInstruction S = new SSAInvokeInstruction(params, exceptionValue, ARRAYCOPY_SITE);
|
||||
statements.add(S);
|
||||
} else {
|
||||
// copy the fields over, one by one.
|
||||
// TODO:
|
||||
IClass k = klass;
|
||||
while (k != null) {
|
||||
for (Iterator<IField> it = klass.getDeclaredInstanceFields().iterator(); it.hasNext();) {
|
||||
IField f = it.next();
|
||||
int tempValue = nextLocal++;
|
||||
SSAGetInstruction G = new SSAGetInstruction(tempValue, 1, f.getFieldReference());
|
||||
statements.add(G);
|
||||
SSAPutInstruction P = new SSAPutInstruction(retValue, tempValue, f.getFieldReference());
|
||||
statements.add(P);
|
||||
}
|
||||
try {
|
||||
k = k.getSuperclass();
|
||||
} catch (ClassHierarchyException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SSAReturnInstruction R = new SSAReturnInstruction(retValue, false);
|
||||
statements.add(R);
|
||||
|
||||
SSAInstruction[] result = new SSAInstruction[statements.size()];
|
||||
Iterator<SSAInstruction> it = statements.iterator();
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = it.next();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an IR that encodes the behavior of the clone method for a given
|
||||
* type.
|
||||
*/
|
||||
private IR makeIR(IMethod method, Context context, IClass klass, WarningSet warnings) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(klass != null);
|
||||
}
|
||||
SSAInstruction instrs[] = makeStatements(klass);
|
||||
return new SyntheticIR(method, context, new InducedCFG(instrs, method, context), instrs, SSAOptions.defaultOptions(), null,
|
||||
warnings);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.cfa.CFAContextInterpreter#recordFactoryType(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.classLoader.IClass)
|
||||
*/
|
||||
public boolean recordFactoryType(CGNode node, IClass klass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.rta.RTAContextInterpreter#setWarnings(com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public void setWarnings(WarningSet newWarnings) {
|
||||
// this object is not bound to a WarningSet
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.xta.XTAContextInterpreter#iterateFieldsRead(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public Iterator iterateFieldsRead(CGNode node, WarningSet warnings) {
|
||||
SSAInstruction[] statements = getIR(node, warnings).getInstructions();
|
||||
return CodeScanner.getFieldsRead(statements).iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.xta.XTAContextInterpreter#iterateFieldsWritten(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public Iterator iterateFieldsWritten(CGNode node, WarningSet warnings) {
|
||||
SSAInstruction[] statements = getIR(node, warnings).getInstructions();
|
||||
return CodeScanner.getFieldsWritten(statements).iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.xta.XTAContextInterpreter#getCaughtExceptions(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public Set getCaughtExceptions(CGNode node, WarningSet warnings) {
|
||||
SSAInstruction[] statements = getIR(node, warnings).getInstructions();
|
||||
return CodeScanner.getCaughtExceptions(statements);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.xta.XTAContextInterpreter#hasObjectArrayLoad(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public boolean hasObjectArrayLoad(CGNode node, WarningSet warnings) {
|
||||
SSAInstruction[] statements = getIR(node, warnings).getInstructions();
|
||||
return CodeScanner.hasObjectArrayLoad(statements);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.xta.XTAContextInterpreter#hasObjectArrayStore(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public boolean hasObjectArrayStore(CGNode node, WarningSet warnings) {
|
||||
SSAInstruction[] statements = getIR(node, warnings).getInstructions();
|
||||
return CodeScanner.hasObjectArrayStore(statements);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.xta.XTAContextInterpreter#iterateCastTypes(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public Iterator iterateCastTypes(CGNode node, WarningSet warnings) {
|
||||
SSAInstruction[] statements = getIR(node, warnings).getInstructions();
|
||||
return CodeScanner.iterateCastTypes(statements);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.cfg.CFGProvider#getCFG(com.ibm.wala.ipa.callgraph.CGNode)
|
||||
*/
|
||||
public ControlFlowGraph getCFG(CGNode N, WarningSet warnings) {
|
||||
return getIR(N, warnings).getControlFlowGraph();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter#getDU(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public DefUse getDU(CGNode node, WarningSet warnings) {
|
||||
return new DefUse(getIR(node, warnings));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,809 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.reflection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.analysis.typeInference.ConeType;
|
||||
import com.ibm.wala.analysis.typeInference.PointType;
|
||||
import com.ibm.wala.analysis.typeInference.SetType;
|
||||
import com.ibm.wala.analysis.typeInference.TypeAbstraction;
|
||||
import com.ibm.wala.cfg.ControlFlowGraph;
|
||||
import com.ibm.wala.cfg.InducedCFG;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.CodeScanner;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.classLoader.NewSiteReference;
|
||||
import com.ibm.wala.classLoader.SyntheticMethod;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.callgraph.ReflectionSpecification;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.rta.RTAContextInterpreter;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.summaries.ReflectionSummary;
|
||||
import com.ibm.wala.ipa.summaries.SummarizedMethod;
|
||||
import com.ibm.wala.ipa.summaries.SyntheticIR;
|
||||
import com.ibm.wala.ipa.summaries.XMLReflectionReader;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.ssa.ConstantValue;
|
||||
import com.ibm.wala.ssa.DefUse;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSANewInstruction;
|
||||
import com.ibm.wala.ssa.SSAOptions;
|
||||
import com.ibm.wala.ssa.SSAReturnInstruction;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.util.warnings.Warning;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* Logic to interpret "factory" methods in context.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class FactoryBypassInterpreter implements RTAContextInterpreter, SSAContextInterpreter {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private final static int CONE_BOUND = 10;
|
||||
|
||||
private int indexLocal = 100;
|
||||
|
||||
private final Map<TypeReference, Integer> typeIndexMap = HashMapFactory.make();
|
||||
|
||||
/**
|
||||
* A Map from CallerSiteContext -> Set <TypeReference>represents the types a
|
||||
* factory method might create in a particular context
|
||||
*/
|
||||
private final Map<Context, Set<TypeReference>> map = HashMapFactory.make();
|
||||
|
||||
/**
|
||||
* A cache of synthetic method implementations, indexed by Context
|
||||
*/
|
||||
private final Map<Context, SpecializedFactoryMethod> syntheticMethodCache = HashMapFactory.make();
|
||||
|
||||
/**
|
||||
* Governing analysis options
|
||||
*/
|
||||
private final AnalysisOptions options;
|
||||
|
||||
/**
|
||||
* Governing class hierarchy
|
||||
*/
|
||||
private final ClassHierarchy cha;
|
||||
|
||||
/**
|
||||
* Keep track of analysis warnings
|
||||
*/
|
||||
private WarningSet warnings;
|
||||
|
||||
/**
|
||||
* User-defined reflection specification
|
||||
*/
|
||||
private final ReflectionSpecification userSpec;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param options
|
||||
* governing analysis options
|
||||
* @param cha
|
||||
* governing class hierarchy
|
||||
* @param userSpec
|
||||
* @param warnings
|
||||
* object to track analysis warnings
|
||||
*/
|
||||
public FactoryBypassInterpreter(AnalysisOptions options, ClassHierarchy cha, ReflectionSpecification userSpec, WarningSet warnings) {
|
||||
this.options = options;
|
||||
this.cha = cha;
|
||||
this.warnings = warnings;
|
||||
this.userSpec = userSpec;
|
||||
}
|
||||
|
||||
private int getLocalForType(TypeReference T) {
|
||||
Integer I = typeIndexMap.get(T);
|
||||
if (I == null) {
|
||||
typeIndexMap.put(T, I = new Integer(indexLocal += 2));
|
||||
}
|
||||
return I.intValue();
|
||||
}
|
||||
|
||||
private int getExceptionsForType(TypeReference T) {
|
||||
return getLocalForType(T) + 1;
|
||||
}
|
||||
|
||||
private int getCallSiteForType(TypeReference T) {
|
||||
return getLocalForType(T);
|
||||
}
|
||||
|
||||
private int getNewSiteForType(TypeReference T) {
|
||||
return getLocalForType(T) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.cfa.CFAContextInterpreter#getIR(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.wala.ipa.callgraph.Context,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public IR getIR(CGNode node, WarningSet warnings) {
|
||||
SpecializedFactoryMethod m = findOrCreateSpecializedFactoryMethod(node);
|
||||
return options.getSSACache().findOrCreateIR(m, node.getContext(), cha, options.getSSAOptions(), warnings);
|
||||
}
|
||||
|
||||
private Set getTypesForContext(Context context) {
|
||||
// first try user spec
|
||||
XMLReflectionReader spec = (XMLReflectionReader) userSpec;
|
||||
if (spec != null && context instanceof CallerSiteContext) {
|
||||
CallerSiteContext site = (CallerSiteContext) context;
|
||||
MethodReference m = site.getCaller().getMethod().getReference();
|
||||
ReflectionSummary summary = spec.getSummary(m);
|
||||
if (summary != null) {
|
||||
Set types = summary.getTypesForProgramLocation(site.getSite().getProgramCounter());
|
||||
if (types != null) {
|
||||
return types;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set types = map.get(context);
|
||||
return types;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.cfa.CFAContextInterpreter#getNumberOfStatements(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.wala.ipa.callgraph.Context,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public int getNumberOfStatements(CGNode node, WarningSet warnings) {
|
||||
SpecializedFactoryMethod m = findOrCreateSpecializedFactoryMethod(node);
|
||||
return m.allInstructions.size();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.rta.RTAContextInterpreter#understands(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.wala.ipa.callgraph.Context)
|
||||
*/
|
||||
public boolean understands(CGNode node) {
|
||||
return getTypesForContext(node.getContext()) != null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.rta.RTAContextInterpreter#getNewSites(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.wala.ipa.callgraph.Context,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public Iterator<NewSiteReference> iterateNewSites(CGNode node, WarningSet warnings) {
|
||||
SpecializedFactoryMethod m = findOrCreateSpecializedFactoryMethod(node);
|
||||
HashSet<NewSiteReference> result = HashSetFactory.make(5);
|
||||
for (Iterator<SSAInstruction> it = m.getAllocationStatements().iterator(); it.hasNext();) {
|
||||
SSANewInstruction s = (SSANewInstruction) it.next();
|
||||
result.add(s.getNewSite());
|
||||
}
|
||||
return result.iterator();
|
||||
}
|
||||
|
||||
public Iterator<SSAInstruction> getInvokeStatements(CGNode node) {
|
||||
SpecializedFactoryMethod m = findOrCreateSpecializedFactoryMethod(node);
|
||||
return m.getInvokeStatements().iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.rta.RTAContextInterpreter#getCallSites(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.detox.ipa.callgraph.Context,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public Iterator<CallSiteReference> iterateCallSites(CGNode node, WarningSet warnings) {
|
||||
final Iterator<SSAInstruction> I = getInvokeStatements(node);
|
||||
return new Iterator<CallSiteReference>() {
|
||||
public boolean hasNext() {
|
||||
return I.hasNext();
|
||||
}
|
||||
|
||||
public CallSiteReference next() {
|
||||
SSAInvokeInstruction s = (SSAInvokeInstruction) I.next();
|
||||
return s.getCallSite();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
*/
|
||||
protected class SpecializedFactoryMethod extends SyntheticMethod {
|
||||
|
||||
/**
|
||||
* List of synthetic allocation statements we model for this specialized
|
||||
* instance
|
||||
*/
|
||||
private ArrayList<SSAInstruction> allocations = new ArrayList<SSAInstruction>();
|
||||
|
||||
/**
|
||||
* List of synthetic invoke instructions we model for this specialized
|
||||
* instance.
|
||||
*/
|
||||
private ArrayList<SSAInstruction> calls = new ArrayList<SSAInstruction>();
|
||||
|
||||
/**
|
||||
* List of all instructions
|
||||
*/
|
||||
private ArrayList<SSAInstruction> allInstructions = new ArrayList<SSAInstruction>();
|
||||
|
||||
/**
|
||||
* The method being modelled
|
||||
*/
|
||||
private final IMethod method;
|
||||
|
||||
/**
|
||||
* Context being modelled
|
||||
*/
|
||||
private final Context context;
|
||||
|
||||
/**
|
||||
* next free local value number;
|
||||
*/
|
||||
private int nextLocal;
|
||||
|
||||
/**
|
||||
* value number for integer constant 1
|
||||
*/
|
||||
private int valueNumberForConstantOne = -1;
|
||||
|
||||
private void initValueNumberForConstantOne() {
|
||||
if (valueNumberForConstantOne == -1) {
|
||||
valueNumberForConstantOne = nextLocal++;
|
||||
}
|
||||
}
|
||||
|
||||
private final HashSet<TypeReference> types = HashSetFactory.make(5);
|
||||
|
||||
private SpecializedFactoryMethod(final SummarizedMethod m, Context context, final Set S) {
|
||||
super(m, m.getDeclaringClass(), m.isStatic(), true);
|
||||
|
||||
this.context = context;
|
||||
if (DEBUG) {
|
||||
Trace.println("Create SpecializedFactoryMethod " + m + S);
|
||||
}
|
||||
|
||||
this.method = m;
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(S != null);
|
||||
Assertions._assert(m.getDeclaringClass() != null, "null declaring class for " + m);
|
||||
}
|
||||
|
||||
// add original statements from the method summary
|
||||
nextLocal = addOriginalStatements(m);
|
||||
|
||||
for (Iterator it = S.iterator(); it.hasNext();) {
|
||||
TypeReference type = (TypeReference) it.next();
|
||||
TypeAbstraction T = typeRef2TypeAbstraction(type);
|
||||
addStatementsForTypeAbstraction(T);
|
||||
}
|
||||
}
|
||||
|
||||
private void addStatementsForTypeAbstraction(TypeAbstraction T) {
|
||||
|
||||
if (DEBUG) {
|
||||
Trace.println("adding " + T + " to " + method);
|
||||
}
|
||||
T = interceptType(T);
|
||||
if (T == null) {
|
||||
return;
|
||||
}
|
||||
if ((T instanceof PointType) || (T instanceof ConeType)) {
|
||||
TypeReference ref = T.getType().getReference();
|
||||
NewSiteReference site = NewSiteReference.make(0, ref);
|
||||
IClass klass = options.getClassTargetSelector().getAllocatedTarget(null, site);
|
||||
|
||||
if (DEBUG) {
|
||||
Trace.println("Selected allocated target: " + klass + " for " + T);
|
||||
}
|
||||
if (T instanceof PointType) {
|
||||
addStatementsForConcreteType(ref);
|
||||
} else if (T instanceof ConeType) {
|
||||
if (DEBUG) {
|
||||
Trace.println("Cone clause for " + T);
|
||||
}
|
||||
if (((ConeType) T).isInterface()) {
|
||||
Set implementors = cha.getImplementors(ref);
|
||||
if (DEBUG) {
|
||||
Trace.println("Implementors for " + T + " " + implementors);
|
||||
}
|
||||
if (implementors.isEmpty()) {
|
||||
if (DEBUG) {
|
||||
Trace.println("Found no implementors of type " + T);
|
||||
}
|
||||
warnings.add(NoSubtypesWarning.create(T));
|
||||
}
|
||||
if (implementors.size() > CONE_BOUND) {
|
||||
warnings.add(ManySubtypesWarning.create(T, implementors.size()));
|
||||
}
|
||||
|
||||
addStatementsForSetOfTypes(implementors.iterator());
|
||||
} else {
|
||||
Collection subclasses = cha.computeSubClasses(ref);
|
||||
if (DEBUG) {
|
||||
Trace.println("Subclasses for " + T + " " + subclasses);
|
||||
}
|
||||
if (subclasses.isEmpty()) {
|
||||
if (DEBUG) {
|
||||
Trace.println("Found no subclasses of type " + T);
|
||||
}
|
||||
warnings.add(NoSubtypesWarning.create(T));
|
||||
}
|
||||
if (subclasses.size() > CONE_BOUND) {
|
||||
warnings.add(ManySubtypesWarning.create(T, subclasses.size()));
|
||||
}
|
||||
addStatementsForSetOfTypes(subclasses.iterator());
|
||||
}
|
||||
} else {
|
||||
Assertions.UNREACHABLE("Unexpected type " + T.getClass());
|
||||
}
|
||||
} else if (T instanceof SetType) {
|
||||
addStatementsForSetOfTypes(((SetType) T).iteratePoints());
|
||||
} else {
|
||||
Assertions.UNREACHABLE("Unexpected type " + T.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private TypeAbstraction interceptType(TypeAbstraction T) {
|
||||
TypeReference type = T.getType().getReference();
|
||||
if (type.equals(TypeReference.JavaIoSerializable)) {
|
||||
warnings.add(IgnoreSerializableWarning.create());
|
||||
return null;
|
||||
} else {
|
||||
return T;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a method summary which allocates and returns an instance of
|
||||
* concrete type T.
|
||||
*
|
||||
* @param T
|
||||
*/
|
||||
private void addStatementsForConcreteType(final TypeReference T) {
|
||||
if (types.contains(T))
|
||||
return;
|
||||
types.add(T);
|
||||
if (DEBUG) {
|
||||
Trace.println("addStatementsForConcreteType: " + T);
|
||||
}
|
||||
NewSiteReference ref = NewSiteReference.make(getNewSiteForType(T), T);
|
||||
int alloc = getLocalForType(T);
|
||||
SSANewInstruction a = new SSANewInstruction(alloc, ref);
|
||||
if (DEBUG) {
|
||||
Trace.println("Added allocation: " + a);
|
||||
}
|
||||
|
||||
allocations.add(a);
|
||||
allInstructions.add(a);
|
||||
SSAReturnInstruction r = new SSAReturnInstruction(alloc, false);
|
||||
allInstructions.add(r);
|
||||
if (T.isArrayType()) {
|
||||
MethodReference init = MethodReference.findOrCreate(T, MethodReference.initAtom, MethodReference.defaultInitDesc);
|
||||
CallSiteReference site = CallSiteReference.make(getCallSiteForType(T), init, IInvokeInstruction.Dispatch.SPECIAL);
|
||||
int[] params = new int[1];
|
||||
params[0] = alloc;
|
||||
int exc = getExceptionsForType(T);
|
||||
SSAInvokeInstruction s = new SSAInvokeInstruction(params, exc, site);
|
||||
calls.add(s);
|
||||
allInstructions.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
private int addOriginalStatements(SummarizedMethod m) {
|
||||
SSAInstruction[] original = m.getStatements(options.getSSAOptions(), warnings);
|
||||
// local value number 1 is "this", so the next free value number is 2
|
||||
int nextLocal = 2;
|
||||
for (int i = 0; i < original.length; i++) {
|
||||
SSAInstruction s = original[i];
|
||||
allInstructions.add(s);
|
||||
if (s instanceof SSAInvokeInstruction) {
|
||||
calls.add(s);
|
||||
}
|
||||
if (s instanceof SSANewInstruction) {
|
||||
allocations.add(s);
|
||||
}
|
||||
for (int j = 0; j < s.getNumberOfDefs(); j++) {
|
||||
int def = s.getDef(j);
|
||||
if (def >= nextLocal) {
|
||||
nextLocal = def + 1;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < s.getNumberOfUses(); j++) {
|
||||
int use = s.getUse(j);
|
||||
if (use >= nextLocal) {
|
||||
nextLocal = use + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextLocal;
|
||||
}
|
||||
|
||||
private void addStatementsForSetOfTypes(Iterator it) {
|
||||
|
||||
if (!it.hasNext()) { // Uh. No types. Hope the caller reported a warning.
|
||||
SSAReturnInstruction r = new SSAReturnInstruction(nextLocal, false);
|
||||
allInstructions.add(r);
|
||||
}
|
||||
|
||||
for (; it.hasNext();) {
|
||||
IClass klass = (IClass) it.next();
|
||||
TypeReference T = klass.getReference();
|
||||
if (klass.isAbstract() || types.contains(T)) {
|
||||
continue;
|
||||
}
|
||||
types.add(T);
|
||||
int i = getLocalForType(T);
|
||||
NewSiteReference ref = NewSiteReference.make(getNewSiteForType(T), T);
|
||||
SSANewInstruction a = null;
|
||||
if (T.isArrayType()) {
|
||||
int[] sizes = new int[T.getDimensionality()];
|
||||
initValueNumberForConstantOne();
|
||||
Arrays.fill(sizes, valueNumberForConstantOne);
|
||||
a = new SSANewInstruction(i, ref, sizes);
|
||||
|
||||
} else {
|
||||
a = new SSANewInstruction(i, ref);
|
||||
}
|
||||
allocations.add(a);
|
||||
allInstructions.add(a);
|
||||
SSAReturnInstruction r = new SSAReturnInstruction(i, false);
|
||||
allInstructions.add(r);
|
||||
MethodReference init = MethodReference.findOrCreate(T, MethodReference.initAtom, MethodReference.defaultInitDesc);
|
||||
CallSiteReference site = CallSiteReference.make(getCallSiteForType(T), init, IInvokeInstruction.Dispatch.SPECIAL);
|
||||
int[] params = new int[1];
|
||||
params[0] = i;
|
||||
SSAInvokeInstruction s = new SSAInvokeInstruction(params, getExceptionsForType(T), site);
|
||||
calls.add(s);
|
||||
allInstructions.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
public List<SSAInstruction> getAllocationStatements() {
|
||||
return allocations;
|
||||
}
|
||||
|
||||
public List<SSAInstruction> getInvokeStatements() {
|
||||
return calls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Two specialized methods can be different, even if they represent the same
|
||||
* source method. So, revert to object identity for testing equality. TODO:
|
||||
* this is non-optimal; could try to re-use specialized methods that have
|
||||
* the same context.
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
return this == obj;
|
||||
}
|
||||
|
||||
public int hashCode() { // TODO: change this to avoid non-determinism!
|
||||
return System.identityHashCode(this);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return super.toString();
|
||||
}
|
||||
|
||||
public SSAInstruction[] getStatements(WarningSet warnings) {
|
||||
SSAInstruction[] result = new SSAInstruction[allInstructions.size()];
|
||||
int i = 0;
|
||||
for (Iterator<SSAInstruction> it = allInstructions.iterator(); it.hasNext();) {
|
||||
result[i++] = it.next();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public IClass getDeclaringClass() {
|
||||
if (Assertions.verifyAssertions) {
|
||||
if (method.getDeclaringClass() == null) {
|
||||
Assertions._assert(method.getDeclaringClass() != null, "null declaring class for original method " + method);
|
||||
}
|
||||
}
|
||||
return method.getDeclaringClass();
|
||||
}
|
||||
|
||||
public int getNumberOfParameters() {
|
||||
return method.getNumberOfParameters();
|
||||
}
|
||||
|
||||
public TypeReference getParameterType(int i) {
|
||||
return method.getParameterType(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getIR(com.ibm.wala.util.WarningSet)
|
||||
*/
|
||||
public IR makeIR(SSAOptions options, WarningSet warnings) {
|
||||
SSAInstruction[] instrs = getStatements(warnings);
|
||||
Map<Integer, ConstantValue> constants = null;
|
||||
if (valueNumberForConstantOne > -1) {
|
||||
constants = HashMapFactory.make(1);
|
||||
constants.put(new Integer(valueNumberForConstantOne), new ConstantValue(new Integer(1)));
|
||||
}
|
||||
|
||||
return new SyntheticIR(this, context, new InducedCFG(instrs, this, context), instrs, options, constants, warnings);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean recordType(Context context, TypeReference type) {
|
||||
Set<TypeReference> types = map.get(context);
|
||||
if (types == null) {
|
||||
types = HashSetFactory.make(2);
|
||||
map.put(context, types);
|
||||
}
|
||||
if (types.contains(type)) {
|
||||
return false;
|
||||
} else {
|
||||
types.add(type);
|
||||
// update any extant synthetic method
|
||||
SpecializedFactoryMethod m = syntheticMethodCache.get(context);
|
||||
if (m != null) {
|
||||
TypeAbstraction T = typeRef2TypeAbstraction(type);
|
||||
m.addStatementsForTypeAbstraction(T);
|
||||
options.getSSACache().invalidate(m, context);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* @return a TypeAbstraction object representing this type. We just use
|
||||
* ConeTypes by default, since we don't propagate information allowing
|
||||
* us to distinguish between points and cones yet.
|
||||
*/
|
||||
private TypeAbstraction typeRef2TypeAbstraction(TypeReference type) {
|
||||
IClass klass = cha.lookupClass(type);
|
||||
if (klass != null) {
|
||||
return new ConeType(klass, cha);
|
||||
// if (klass.isAbstract() || klass.isInterface()) {
|
||||
// return new ConeType(klass, cha);
|
||||
// } else {
|
||||
// return new PointType(klass, cha);
|
||||
// }
|
||||
}
|
||||
Assertions.UNREACHABLE(type.toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.rta.RTAContextInterpreter#recordFactoryType(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.classLoader.IClass)
|
||||
*/
|
||||
public boolean recordFactoryType(CGNode node, IClass klass) {
|
||||
return recordType(node.getContext(), klass.getReference());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.rta.RTAContextInterpreter#setWarnings(com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public void setWarnings(WarningSet newWarnings) {
|
||||
this.warnings = newWarnings;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.rta.RTAContextInterpreter#iterateFieldsRead(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public Iterator iterateFieldsRead(CGNode node, WarningSet warnings) {
|
||||
SpecializedFactoryMethod m = findOrCreateSpecializedFactoryMethod(node);
|
||||
try {
|
||||
return CodeScanner.iterateFieldsRead(m, warnings);
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.rta.RTAContextInterpreter#iterateFieldsWritten(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public Iterator iterateFieldsWritten(CGNode node, WarningSet warnings) {
|
||||
SpecializedFactoryMethod m = findOrCreateSpecializedFactoryMethod(node);
|
||||
try {
|
||||
return CodeScanner.iterateFieldsWritten(m, warnings);
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private SpecializedFactoryMethod findOrCreateSpecializedFactoryMethod(CGNode node) {
|
||||
SpecializedFactoryMethod m = syntheticMethodCache.get(node.getContext());
|
||||
if (m == null) {
|
||||
Set types = getTypesForContext(node.getContext());
|
||||
m = new SpecializedFactoryMethod((SummarizedMethod) node.getMethod(), node.getContext(), types);
|
||||
syntheticMethodCache.put(node.getContext(), m);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
public Set getCaughtExceptions(CGNode node, WarningSet warnings) {
|
||||
SpecializedFactoryMethod m = findOrCreateSpecializedFactoryMethod(node);
|
||||
try {
|
||||
return CodeScanner.getCaughtExceptions(m, warnings);
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasObjectArrayLoad(CGNode node, WarningSet warnings) {
|
||||
SpecializedFactoryMethod m = findOrCreateSpecializedFactoryMethod(node);
|
||||
try {
|
||||
return CodeScanner.hasObjectArrayLoad(m, warnings);
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasObjectArrayStore(CGNode node, WarningSet warnings) {
|
||||
SpecializedFactoryMethod m = findOrCreateSpecializedFactoryMethod(node);
|
||||
try {
|
||||
return CodeScanner.hasObjectArrayStore(m, warnings);
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator iterateCastTypes(CGNode node, WarningSet warnings) {
|
||||
SpecializedFactoryMethod m = findOrCreateSpecializedFactoryMethod(node);
|
||||
try {
|
||||
return CodeScanner.iterateCastTypes(m, warnings);
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.cfg.CFGProvider#getCFG(com.ibm.wala.ipa.callgraph.CGNode)
|
||||
*/
|
||||
public ControlFlowGraph getCFG(CGNode N, WarningSet warnings) {
|
||||
return getIR(N, warnings).getControlFlowGraph();
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* A waring when we expect excessive pollution from a factory method
|
||||
*/
|
||||
private static class ManySubtypesWarning extends Warning {
|
||||
|
||||
final int nImplementors;
|
||||
|
||||
final TypeAbstraction T;
|
||||
|
||||
ManySubtypesWarning(TypeAbstraction T, int nImplementors) {
|
||||
super(Warning.MODERATE);
|
||||
this.T = T;
|
||||
this.nImplementors = nImplementors;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return getClass().toString() + " : " + T + " " + nImplementors;
|
||||
}
|
||||
|
||||
public static ManySubtypesWarning create(TypeAbstraction T, int n) {
|
||||
return new ManySubtypesWarning(T, n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* A warning when we fail to find subtypes for a factory method
|
||||
*/
|
||||
private static class NoSubtypesWarning extends Warning {
|
||||
|
||||
final TypeAbstraction T;
|
||||
|
||||
NoSubtypesWarning(TypeAbstraction T) {
|
||||
super(Warning.SEVERE);
|
||||
this.T = T;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return getClass().toString() + " : " + T;
|
||||
}
|
||||
|
||||
public static NoSubtypesWarning create(TypeAbstraction T) {
|
||||
return new NoSubtypesWarning(T);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* A waring when we find flow of a factory allocation to a cast to
|
||||
* serializable
|
||||
*/
|
||||
private static class IgnoreSerializableWarning extends Warning {
|
||||
|
||||
private static IgnoreSerializableWarning instance = new IgnoreSerializableWarning();
|
||||
|
||||
public String getMsg() {
|
||||
return getClass().toString();
|
||||
}
|
||||
|
||||
public static IgnoreSerializableWarning create() {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter#getDU(com.ibm.wala.ipa.callgraph.CGNode,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public DefUse getDU(CGNode node, WarningSet warnings) {
|
||||
SpecializedFactoryMethod m = findOrCreateSpecializedFactoryMethod(node);
|
||||
return options.getSSACache().findOrCreateDU(m, node.getContext(), cha, options.getSSAOptions(), warnings);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.reflection;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.classLoader.SyntheticMethod;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.callgraph.ContextSelector;
|
||||
import com.ibm.wala.ipa.callgraph.MethodTargetSelector;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
* For synthetic methods marked as "Factories", we analyze in a context defined by the caller.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class FactoryContextSelector implements ContextSelector {
|
||||
|
||||
|
||||
private final MethodTargetSelector methodTargetSelector;
|
||||
|
||||
private final ClassHierarchy cha;
|
||||
|
||||
/**
|
||||
* @param methodTargetSelector
|
||||
*/
|
||||
public FactoryContextSelector(ClassHierarchy cha, MethodTargetSelector methodTargetSelector) {
|
||||
this.cha = cha;
|
||||
this.methodTargetSelector = methodTargetSelector;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ipa.callgraph.ContextSelector#getCalleeTarget(com.ibm.wala.ipa.callgraph.CGNode, com.ibm.wala.classLoader.CallSiteReference, com.ibm.wala.classLoader.IMethod)
|
||||
*/
|
||||
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey receiver) {
|
||||
if (callee.isSynthetic()) {
|
||||
SyntheticMethod s = (SyntheticMethod) callee;
|
||||
if (s.isFactoryMethod()) {
|
||||
return new CallerSiteContext(caller, site);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ipa.callgraph.ContextSelector#mayUnderstand(com.ibm.wala.ipa.callgraph.CGNode, com.ibm.wala.classLoader.CallSiteReference, com.ibm.wala.classLoader.IMethod, com.ibm.wala.ipa.callgraph.propagation.InstanceKey)
|
||||
*/
|
||||
public boolean mayUnderstand(CGNode caller, CallSiteReference site, IMethod targetMethod, InstanceKey instance) {
|
||||
if (targetMethod.isSynthetic()) {
|
||||
SyntheticMethod s = (SyntheticMethod) targetMethod;
|
||||
if (s.isFactoryMethod()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ipa.callgraph.ContextSelector#getBoundOnNumberOfTargets(com.ibm.wala.ipa.callgraph.CGNode, com.ibm.wala.classLoader.CallSiteReference, com.ibm.wala.classLoader.IMethod)
|
||||
*/
|
||||
public int getBoundOnNumberOfTargets(CGNode caller, CallSiteReference site, IMethod callee) {
|
||||
if (callee.isSynthetic()) {
|
||||
SyntheticMethod s = (SyntheticMethod) callee;
|
||||
if (s.isFactoryMethod()) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ipa.callgraph.rta.RTAContextInterpreter#setWarnings(com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public void setWarnings(WarningSet newWarnings) {
|
||||
// this object is not bound to a WarningSet
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ipa.callgraph.ContextSelector#contextIsIrrelevant(com.ibm.wala.classLoader.CallSiteReference)
|
||||
*/
|
||||
public boolean contextIsIrrelevant(CGNode node, CallSiteReference site) {
|
||||
boolean result = methodTargetSelector.mightReturnSyntheticMethod(node,site);
|
||||
if (result) {
|
||||
IMethod callee = methodTargetSelector.getCalleeTarget(node, site, null);
|
||||
if (callee != null && callee.isSynthetic()) {
|
||||
SyntheticMethod s = (SyntheticMethod) callee;
|
||||
if (s.isFactoryMethod()) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ipa.callgraph.ContextSelector#contextIsIrrelevant(com.ibm.wala.types.MethodReference)
|
||||
*/
|
||||
public boolean allSitesDispatchIdentically(CGNode node, CallSiteReference site) {
|
||||
boolean result = methodTargetSelector.mightReturnSyntheticMethod(node,site);
|
||||
if (result) {
|
||||
IClass recv = cha.lookupClass(site.getDeclaredTarget().getDeclaringClass());
|
||||
if (recv == null) {
|
||||
return false;
|
||||
}
|
||||
IMethod callee = methodTargetSelector.getCalleeTarget(node, site, recv);
|
||||
if (callee != null && callee.isSynthetic()) {
|
||||
SyntheticMethod s = (SyntheticMethod) callee;
|
||||
if (s.isFactoryMethod()) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.reflection;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
|
||||
/**
|
||||
*
|
||||
* An instance key which has an associated node
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public interface InstanceKeyWithNode extends InstanceKey {
|
||||
|
||||
/**
|
||||
* @return the node which created this instance.
|
||||
*/
|
||||
CGNode getNode();
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.reflection;
|
||||
|
||||
import com.ibm.wala.analysis.typeInference.TypeAbstraction;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.callgraph.ContextItem;
|
||||
import com.ibm.wala.ipa.callgraph.ContextKey;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* Implement a Context which corresponds to a given type abstraction.
|
||||
* Thus, this maps the name "TYPE" to a JavaTypeAbstraction.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class JavaTypeContext implements Context {
|
||||
|
||||
private final TypeAbstraction type;
|
||||
|
||||
public JavaTypeContext(TypeAbstraction type) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(type != null);
|
||||
}
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
public ContextItem get(ContextKey name) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(name == ContextKey.RECEIVER);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "JavaTypeContext<" + type + ">";
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 6367 * type.hashCode();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (getClass().equals(obj.getClass())) {
|
||||
JavaTypeContext other = (JavaTypeContext)obj;
|
||||
return type.equals(other.type);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.reflection;
|
||||
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* some utility support for dealing with "malleable" reflection allocations
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class Malleable {
|
||||
private final static TypeName MalleableName = TypeName.string2TypeName("Lcom/ibm/wala/Malleable");
|
||||
public final static TypeReference Malleable = TypeReference.findOrCreate(ClassLoaderReference.Primordial, MalleableName);
|
||||
public final static TypeReference ExtMalleable = TypeReference.findOrCreate(ClassLoaderReference.Extension, MalleableName);
|
||||
|
||||
public final static TypeReference MalleableCollection = TypeReference.findOrCreate(ClassLoaderReference.Primordial,
|
||||
"Lcom/ibm/wala/model/java/util/MalleableCollection");
|
||||
|
||||
|
||||
public static boolean isMalleable(TypeReference T) {
|
||||
return T.equals(Malleable) || T.equals(ExtMalleable);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
This package provides functions to deal with reflection.
|
||||
</BODY>
|
||||
</HTML>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
This package provides a layer to perform abstract interpretation over
|
||||
the JVM stack machine.
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,122 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.typeInference;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* Absraction of a Java type. These are immutable.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class ConeType extends TypeAbstraction {
|
||||
|
||||
private final IClass type;
|
||||
private final ClassHierarchy cha;
|
||||
|
||||
/**
|
||||
* default constructor
|
||||
*/
|
||||
public ConeType(IClass type, ClassHierarchy cha) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(type != null);
|
||||
Assertions._assert(type.getReference().isReferenceType());
|
||||
}
|
||||
this.type = type;
|
||||
this.cha = cha;
|
||||
}
|
||||
|
||||
public TypeAbstraction meet(TypeAbstraction rhs) {
|
||||
if (rhs == TOP) {
|
||||
return this;
|
||||
} else if (rhs instanceof ConeType) {
|
||||
ConeType other = (ConeType) rhs;
|
||||
if (type.equals(other.type)) {
|
||||
return this;
|
||||
} else if (type.isArrayClass() || other.type.isArrayClass()) {
|
||||
// give up on arrays. We don't care anyway.
|
||||
return new ConeType(cha.getRootClass(), cha);
|
||||
} else {
|
||||
return new ConeType(cha.getLeastCommonSuperclass(this.type, other.type), cha);
|
||||
}
|
||||
} else if (rhs instanceof PointType) {
|
||||
return rhs.meet(this);
|
||||
} else if (rhs instanceof PrimitiveType) {
|
||||
return TOP;
|
||||
} else {
|
||||
Assertions.UNREACHABLE("unexpected type " + rhs.getClass());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "cone:" + type.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getType.
|
||||
* @return TypeReference
|
||||
*/
|
||||
public IClass getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof ConeType))
|
||||
return false;
|
||||
ConeType other = (ConeType) obj;
|
||||
if (other == TOP)
|
||||
return false;
|
||||
if (Assertions.verifyAssertions) {
|
||||
if (!cha.equals(other.cha)) {
|
||||
Assertions._assert(cha.equals(other.cha), "different chas " + this +" " + other);
|
||||
}
|
||||
}
|
||||
return type.equals(other.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return 39 * type.hashCode();
|
||||
}
|
||||
|
||||
public boolean isArrayType() {
|
||||
return getType().isArrayClass();
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
return getType().isInterface();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an Iteration of IClass that implement this interface
|
||||
*/
|
||||
public Iterator iterateImplementors() {
|
||||
return cha.getImplementors(getType().getReference()).iterator();
|
||||
}
|
||||
|
||||
public ClassHierarchy getClassHierarchy() {
|
||||
return cha;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.typeInference;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* Abstraction of a Java type. These are immutable.
|
||||
* @author sfink
|
||||
*/
|
||||
public class PointType extends TypeAbstraction {
|
||||
|
||||
private final IClass type;
|
||||
private final ClassHierarchy cha;
|
||||
|
||||
/**
|
||||
* Private constructor ... only for internal use.
|
||||
*/
|
||||
public PointType(IClass type, ClassHierarchy cha) {
|
||||
this.type = type;
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(type != null);
|
||||
Assertions._assert(type.getReference().isReferenceType());
|
||||
}
|
||||
this.cha = cha;
|
||||
}
|
||||
|
||||
public TypeAbstraction meet(TypeAbstraction rhs) {
|
||||
if (rhs == TOP) {
|
||||
return this;
|
||||
} else {
|
||||
if (rhs instanceof PointType) {
|
||||
PointType other = (PointType) rhs;
|
||||
if (type.equals(other.type)) {
|
||||
return this;
|
||||
} else if (type.isArrayClass() || other.type.isArrayClass()) {
|
||||
// give up on arrays. We don't care anyway.
|
||||
return new ConeType(cha.getRootClass(), cha);
|
||||
} else {
|
||||
return new ConeType(cha.getLeastCommonSuperclass(this.type, other.type), cha);
|
||||
}
|
||||
} else if (rhs instanceof ConeType) {
|
||||
ConeType other = (ConeType) rhs;
|
||||
TypeReference T = other.getType().getReference();
|
||||
if (type.isArrayClass() || T.isArrayType()) {
|
||||
// give up on arrays. We don't care anyway.
|
||||
return new ConeType(cha.getRootClass(), cha);
|
||||
}
|
||||
IClass typeKlass = type;
|
||||
if (cha.isSubclassOf(typeKlass, other.getType())) {
|
||||
return other;
|
||||
} else if (other.isInterface()) {
|
||||
if (cha.implementsInterface(typeKlass, T)) {
|
||||
return other;
|
||||
}
|
||||
}
|
||||
// if we get here, we need to do cha-based superclass and return a cone.
|
||||
// TODO: avoid the allocation
|
||||
return other.meet(new ConeType(other.getType(), cha));
|
||||
} else {
|
||||
Assertions.UNREACHABLE("Unexpected type: " + rhs.getClass());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "point: " + type.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getType.
|
||||
*
|
||||
* @return TypeReference
|
||||
*/
|
||||
public IClass getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof PointType)) {
|
||||
return false;
|
||||
}
|
||||
PointType other = (PointType) obj;
|
||||
if (Assertions.verifyAssertions) {
|
||||
if (!cha.equals(other.cha)) {
|
||||
Assertions._assert(cha.equals(other.cha), "different chas " + this + " " + other);
|
||||
}
|
||||
}
|
||||
return type.equals(other.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return 37 * type.hashCode();
|
||||
}
|
||||
|
||||
public boolean isArrayType() {
|
||||
return getType().isArrayClass();
|
||||
}
|
||||
|
||||
public IClass getIClass() {
|
||||
return type;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.typeInference;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
|
||||
public class PrimitiveType extends TypeAbstraction {
|
||||
|
||||
private static Map<TypeReference, PrimitiveType> refernceToType = new HashMap<TypeReference, PrimitiveType>();
|
||||
|
||||
public static final PrimitiveType BOOLEAN = makePrimitive(TypeReference.Boolean);
|
||||
|
||||
public static final PrimitiveType CHAR = makePrimitive(TypeReference.Char);
|
||||
|
||||
public static final PrimitiveType BYTE = makePrimitive(TypeReference.Byte);
|
||||
|
||||
public static final PrimitiveType SHORT = makePrimitive(TypeReference.Short);
|
||||
|
||||
public static final PrimitiveType INT = makePrimitive(TypeReference.Int);
|
||||
|
||||
public static final PrimitiveType LONG = makePrimitive(TypeReference.Long);
|
||||
|
||||
public static final PrimitiveType FLOAT = makePrimitive(TypeReference.Float);
|
||||
|
||||
public static final PrimitiveType DOUBLE = makePrimitive(TypeReference.Double);
|
||||
|
||||
private static HashMap<String, String> primitiveNameMap;
|
||||
static {
|
||||
primitiveNameMap = HashMapFactory.make(9);
|
||||
primitiveNameMap.put("I", "int");
|
||||
primitiveNameMap.put("J", "long");
|
||||
primitiveNameMap.put("S", "short");
|
||||
primitiveNameMap.put("B", "byte");
|
||||
primitiveNameMap.put("C", "char");
|
||||
primitiveNameMap.put("D", "double");
|
||||
primitiveNameMap.put("F", "float");
|
||||
primitiveNameMap.put("Z", "boolean");
|
||||
primitiveNameMap.put("V", "void");
|
||||
}
|
||||
|
||||
private final TypeReference reference;
|
||||
|
||||
private PrimitiveType(TypeReference reference) {
|
||||
this.reference = reference;
|
||||
}
|
||||
|
||||
public TypeAbstraction meet(TypeAbstraction rhs) {
|
||||
if (rhs == TOP) {
|
||||
return this;
|
||||
} else if (rhs == this) {
|
||||
return this;
|
||||
} else if (this == BOOLEAN) {
|
||||
return rhs;
|
||||
} else if (rhs == BOOLEAN) {
|
||||
return this;
|
||||
}
|
||||
return TOP;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return reference.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
return this == other;
|
||||
}
|
||||
|
||||
public IClass getType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PrimitiveType getPrimitive(TypeReference reference) {
|
||||
return refernceToType.get(reference);
|
||||
}
|
||||
|
||||
private static PrimitiveType makePrimitive(TypeReference reference) {
|
||||
PrimitiveType newType = new PrimitiveType(reference);
|
||||
refernceToType.put(reference, newType);
|
||||
return newType;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String result = primitiveNameMap.get(reference.getName().toString());
|
||||
return (result != null) ? result : "PrimitiveType";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.typeInference;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.CodeScanner;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* Holds results of type inference for call site receivers.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class ReceiverTypeInference {
|
||||
|
||||
private TypeInference ti;
|
||||
|
||||
/**
|
||||
* Mapping from call site reference to InvokeInstruction. TODO: this kind of
|
||||
* sucks. Redesign?
|
||||
*/
|
||||
private HashMap<CallSiteReference, SSAInvokeInstruction> invokeMap;
|
||||
|
||||
/**
|
||||
* An object to track analysis warnings
|
||||
*/
|
||||
private WarningSet warnings;
|
||||
|
||||
public ReceiverTypeInference(TypeInference ti, WarningSet warnings) {
|
||||
this.ti = ti;
|
||||
this.warnings = warnings;
|
||||
|
||||
try {
|
||||
setupInvokeMap();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method setupInvokeMap. TODO: redesign stuff so that all this is not
|
||||
* necessary. TODO: has that time come .. is this unnecesary yet?
|
||||
*
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
private void setupInvokeMap() throws InvalidClassFileException {
|
||||
|
||||
invokeMap = HashMapFactory.make(5);
|
||||
IR ir = ti.getIR();
|
||||
IMethod method = ir.getMethod();
|
||||
// set up mapping from Integer (program counter) -> CallSiteReference
|
||||
HashMap<Integer, CallSiteReference> intMap = HashMapFactory.make(5);
|
||||
for (Iterator it = CodeScanner.iterateCallSites(method, warnings); it.hasNext();) {
|
||||
CallSiteReference site = (CallSiteReference) it.next();
|
||||
int pc = site.getProgramCounter();
|
||||
intMap.put(new Integer(pc), site);
|
||||
}
|
||||
// now set up mapping from CallSiteReference -> InvokeInstruction
|
||||
SSAInstruction[] instructions = ir.getInstructions();
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
SSAInstruction s = instructions[i];
|
||||
if (s instanceof SSAInvokeInstruction) {
|
||||
SSAInvokeInstruction call = (SSAInvokeInstruction) s;
|
||||
int pc = call.getProgramCounter();
|
||||
CallSiteReference site = intMap.get(new Integer(pc));
|
||||
invokeMap.put(site, call);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TypeAbstraction getReceiverType(CallSiteReference site) {
|
||||
SSAInvokeInstruction instruction = getInvokeInstruction(site);
|
||||
if (instruction == null) {
|
||||
return null;
|
||||
}
|
||||
int def = instruction.getReceiver();
|
||||
if (def == -1) {
|
||||
return null;
|
||||
} else {
|
||||
return ti.getType(def);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getInvokeInstruction.
|
||||
*
|
||||
* @param site
|
||||
* @return InvokeInstruction
|
||||
*/
|
||||
private SSAInvokeInstruction getInvokeInstruction(CallSiteReference site) {
|
||||
return invokeMap.get(site);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.typeInference;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAOptions;
|
||||
import com.ibm.wala.util.CacheReference;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* A soft cache of results of type inference
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class ReceiverTypeInferenceCache {
|
||||
|
||||
private final WarningSet warnings;
|
||||
|
||||
private final ClassHierarchy cha;
|
||||
|
||||
private final AnalysisOptions options;
|
||||
|
||||
public ReceiverTypeInferenceCache(ClassHierarchy cha, AnalysisOptions options, WarningSet warnings) {
|
||||
this.warnings = warnings;
|
||||
this.options = options;
|
||||
this.cha = cha;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A cache of TypeInference results; a mapping from CGNode ->
|
||||
* ReceiverTypeInference
|
||||
*/
|
||||
private final Map<CGNode, Object> typeInferenceMap = HashMapFactory.make();
|
||||
|
||||
/**
|
||||
* @param n
|
||||
* node
|
||||
* @return null if unable to perform type inference
|
||||
*/
|
||||
public ReceiverTypeInference findOrCreate(CGNode n) {
|
||||
Object ref = typeInferenceMap.get(n);
|
||||
ReceiverTypeInference result = (ReceiverTypeInference) CacheReference.get(ref);
|
||||
try {
|
||||
if (result == null) {
|
||||
SSAOptions options = SSAOptions.defaultOptions();
|
||||
options.setUsePiNodes(true);
|
||||
IR ir = this.options.getSSACache().findOrCreateIR(n.getMethod(), n.getContext(), cha, options, warnings);
|
||||
TypeInference T = new TypeInference(ir, cha);
|
||||
T.solve();
|
||||
|
||||
result = new ReceiverTypeInference(T, warnings);
|
||||
ref = CacheReference.make(result);
|
||||
typeInferenceMap.put(n, ref);
|
||||
}
|
||||
return result;
|
||||
} catch (ClassCastException e) {
|
||||
// this might happen if it's not a ShrikeCTMethodWrapper
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.typeInference;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Abstraction of a set of PointTypes. These are immutable.
|
||||
* TODO: fix for efficiency if needed.
|
||||
*
|
||||
* @author sfink
|
||||
*
|
||||
*/
|
||||
public class SetType extends TypeAbstraction {
|
||||
|
||||
private final HashSet<TypeReference> types;
|
||||
private final int hashCode;
|
||||
|
||||
public SetType(PointType[] points) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(points != null);
|
||||
Assertions._assert(points.length > 0);
|
||||
}
|
||||
types = HashSetFactory.make(points.length);
|
||||
int h = 0;
|
||||
for (int i = 0; i< points.length; i++) {
|
||||
TypeReference T = points[i].getType().getReference();
|
||||
h ^= T.hashCode();
|
||||
types.add(T);
|
||||
}
|
||||
hashCode = h;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.analysis.typeInference.TypeAbstraction#meet(com.ibm.wala.analysis.typeInference.TypeAbstraction)
|
||||
*/
|
||||
public TypeAbstraction meet(TypeAbstraction rhs) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.analysis.typeInference.TypeAbstraction#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
// TODO: make SetTypes of size 1 equal PointTypes.
|
||||
// need a factory facade for this.
|
||||
|
||||
// TODO: canonicalize?? How to improve this?
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof SetType) {
|
||||
if (hashCode() != obj.hashCode()) {
|
||||
return false;
|
||||
} else {
|
||||
SetType other = (SetType)obj;
|
||||
return (types.equals(other.types));
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.analysis.typeInference.TypeAbstraction#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator of the TypeReferences which compose this Set.
|
||||
*/
|
||||
public Iterator iteratePoints() {
|
||||
return types.iterator();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.analysis.typeInference;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.ipa.callgraph.ContextItem;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* Absraction of a Java type. These are immutable.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public abstract class TypeAbstraction implements ContextItem {
|
||||
|
||||
/**
|
||||
* Canonical element representing TOP for a dataflow lattice
|
||||
*/
|
||||
public final static TypeAbstraction TOP = new TypeAbstraction() {
|
||||
public TypeAbstraction meet(TypeAbstraction rhs) {
|
||||
return rhs;
|
||||
}
|
||||
public String toString() {
|
||||
return "JavaTypeAbstraction.TOP";
|
||||
}
|
||||
public int hashCode() {
|
||||
return 17;
|
||||
}
|
||||
public boolean equals(Object other) {
|
||||
return this == other;
|
||||
}
|
||||
public IClass getType() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
public abstract TypeAbstraction meet(TypeAbstraction rhs);
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(Object)
|
||||
*/
|
||||
public abstract boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public abstract int hashCode();
|
||||
|
||||
/**
|
||||
* This is here for convenience; it makes sense for Point and Cone Dispatch.
|
||||
* TODO: probably should get rid of it.
|
||||
*/
|
||||
public IClass getType() {
|
||||
Assertions.UNREACHABLE("getType not implemented for " + getClass());
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,766 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.typeInference;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.dataflow.ssa.SSAInference;
|
||||
import com.ibm.wala.fixedpoint.impl.AbstractOperator;
|
||||
import com.ibm.wala.fixedpoint.impl.AbstractVariable;
|
||||
import com.ibm.wala.fixedpoint.impl.NullaryOperator;
|
||||
import com.ibm.wala.fixpoint.FixedPointConstants;
|
||||
import com.ibm.wala.fixpoint.IVariable;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAArrayLengthInstruction;
|
||||
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
|
||||
import com.ibm.wala.ssa.SSABinaryOpInstruction;
|
||||
import com.ibm.wala.ssa.SSACheckCastInstruction;
|
||||
import com.ibm.wala.ssa.SSAConversionInstruction;
|
||||
import com.ibm.wala.ssa.SSAGetCaughtExceptionInstruction;
|
||||
import com.ibm.wala.ssa.SSAGetInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSANewInstruction;
|
||||
import com.ibm.wala.ssa.SSAPhiInstruction;
|
||||
import com.ibm.wala.ssa.SSAPiInstruction;
|
||||
import com.ibm.wala.ssa.SSAUnaryOpInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.SSACFG.ExceptionHandlerBasicBlock;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* This class performs intraprocedural type propagation on an SSA IR.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class TypeInference extends SSAInference implements FixedPointConstants {
|
||||
|
||||
/**
|
||||
* The governing SSA form
|
||||
*/
|
||||
protected IR ir;
|
||||
|
||||
/**
|
||||
* The governing class hierarchy
|
||||
*/
|
||||
protected ClassHierarchy cha;
|
||||
|
||||
/**
|
||||
* A singleton instance of the phi operator.
|
||||
*/
|
||||
private final static AbstractOperator phiOp = new PhiOperator();
|
||||
|
||||
private final static AbstractOperator primitivePropagateOp = new PrimitivePropagateOperator();
|
||||
|
||||
/**
|
||||
* A cone type for java.lang.Object
|
||||
*/
|
||||
protected final TypeAbstraction BOTTOM;
|
||||
|
||||
/**
|
||||
* A singleton instance of the pi operator.
|
||||
*/
|
||||
private final static PiOperator piOp = new PiOperator();
|
||||
|
||||
/**
|
||||
* should type inference track primitive types?
|
||||
*/
|
||||
protected final boolean doPrimitives;
|
||||
|
||||
public TypeInference(IR ir, ClassHierarchy cha, boolean doPrimitives) {
|
||||
this.cha = cha;
|
||||
this.ir = ir;
|
||||
this.doPrimitives = doPrimitives;
|
||||
this.BOTTOM = new ConeType(cha.getRootClass(), cha);
|
||||
initialize();
|
||||
}
|
||||
|
||||
public TypeInference(IR ir, ClassHierarchy cha) {
|
||||
this(ir, cha, false);
|
||||
}
|
||||
|
||||
protected void initialize() {
|
||||
init(ir, this.new TypeVarFactory(), this.new TypeOperatorFactory());
|
||||
}
|
||||
|
||||
protected void initializeVariables() {
|
||||
int[] parameterValueNumbers = ir.getParameterValueNumbers();
|
||||
for (int i = 0; i < parameterValueNumbers.length; i++) {
|
||||
TypeVariable v = (TypeVariable) getVariable(parameterValueNumbers[i]);
|
||||
TypeReference t = ir.getParameterType(i);
|
||||
|
||||
if (t.isReferenceType()) {
|
||||
IClass klass = cha.lookupClass(t);
|
||||
if (klass != null) {
|
||||
v.setType(new ConeType(klass, cha));
|
||||
} else {
|
||||
v.setType(ConeType.TOP);
|
||||
// v.setType(BOTTOM);
|
||||
}
|
||||
} else if (doPrimitives) {
|
||||
v.setType(PrimitiveType.getPrimitive(t));
|
||||
}
|
||||
}
|
||||
|
||||
SymbolTable st = ir.getSymbolTable();
|
||||
if (st != null) {
|
||||
for(int i = 0; i < st.getMaxValueNumber(); i++ ) {
|
||||
if (st.isConstant(i)) {
|
||||
TypeVariable v = (TypeVariable) getVariable(i);
|
||||
v.setType(getConstantType(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Iterator it = ir.iterateNormalInstructions(); it.hasNext();) {
|
||||
SSAInstruction s = (SSAInstruction) it.next();
|
||||
if (s instanceof SSAAbstractInvokeInstruction) {
|
||||
SSAAbstractInvokeInstruction call = (SSAAbstractInvokeInstruction) s;
|
||||
TypeVariable v = (TypeVariable) getVariable(call.getException());
|
||||
Collection defaultExceptions = call.getExceptionTypes();
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(defaultExceptions.size() == 1);
|
||||
}
|
||||
// t should be NullPointerException
|
||||
TypeReference t = (TypeReference) defaultExceptions.iterator().next();
|
||||
IClass klass = cha.lookupClass(t);
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(klass != null);
|
||||
}
|
||||
v.setType(new PointType(klass, cha));
|
||||
|
||||
IMethod m = cha.resolveMethod(call.getDeclaredTarget());
|
||||
if (m != null) {
|
||||
TypeReference[] x = m.getDeclaredExceptions();
|
||||
if (x != null) {
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
TypeReference tx = x[i];
|
||||
IClass tc = cha.lookupClass(tx);
|
||||
if (tc != null) {
|
||||
v.setType(v.getType().meet(new ConeType(tc, cha)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void initializeWorkList() {
|
||||
addAllStatementsToWorkList();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sfink
|
||||
*
|
||||
* An operator which initializes a type to a declared type.
|
||||
*/
|
||||
protected final class DeclaredTypeOperator extends NullaryOperator {
|
||||
private final TypeAbstraction type;
|
||||
|
||||
public DeclaredTypeOperator(TypeAbstraction type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that we need evalute this operator at most once
|
||||
*/
|
||||
public byte evaluate(IVariable lhs) {
|
||||
TypeVariable t = (TypeVariable) lhs;
|
||||
if (t.type.equals(type)) {
|
||||
return NOT_CHANGED_AND_FIXED;
|
||||
} else {
|
||||
t.setType(type);
|
||||
return CHANGED_AND_FIXED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "delared type := " + type;
|
||||
}
|
||||
|
||||
public boolean isNullary() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.dataflow.Operator#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return 9931 * type.hashCode();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.dataflow.Operator#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof DeclaredTypeOperator) {
|
||||
DeclaredTypeOperator d = (DeclaredTypeOperator) o;
|
||||
return type.equals(d.type);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
*/
|
||||
private static final class PhiOperator extends AbstractOperator {
|
||||
|
||||
private PhiOperator() {
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: work on efficiency shortcuts for this.
|
||||
*/
|
||||
public byte evaluate(IVariable lhs, IVariable[] rhs) {
|
||||
TypeVariable L = (TypeVariable) lhs;
|
||||
TypeAbstraction lhsType = L.getType();
|
||||
TypeAbstraction meet = TypeAbstraction.TOP;
|
||||
for (int i = 0; i < rhs.length; i++) {
|
||||
if (rhs[i] != null) {
|
||||
TypeVariable r = (TypeVariable) rhs[i];
|
||||
meet = meet.meet(r.getType());
|
||||
}
|
||||
}
|
||||
if (lhsType.equals(meet)) {
|
||||
return NOT_CHANGED;
|
||||
} else {
|
||||
L.setType(meet);
|
||||
return CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "phi meet";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.dataflow.Operator#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return 9929;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.dataflow.Operator#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof PhiOperator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
*/
|
||||
private static final class PiOperator extends AbstractOperator {
|
||||
|
||||
private PiOperator() {
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: work on efficiency shortcuts for this.
|
||||
*/
|
||||
public byte evaluate(IVariable lhsOperand, IVariable[] rhsOperands) {
|
||||
TypeVariable lhs = (TypeVariable) lhsOperand;
|
||||
TypeAbstraction lhsType = lhs.getType();
|
||||
|
||||
TypeVariable rhs = (TypeVariable) rhsOperands[0];
|
||||
TypeAbstraction rhsType = rhs.getType();
|
||||
|
||||
if (lhsType.equals(rhsType)) {
|
||||
return NOT_CHANGED;
|
||||
} else {
|
||||
lhs.setType(rhsType);
|
||||
return CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "pi";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.dataflow.Operator#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return 9929 * 13;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.dataflow.Operator#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof PiOperator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
*/
|
||||
private static final class PrimitivePropagateOperator extends AbstractOperator {
|
||||
|
||||
private PrimitivePropagateOperator() {
|
||||
}
|
||||
|
||||
public byte evaluate(IVariable lhs, IVariable[] rhs) {
|
||||
TypeVariable L = (TypeVariable) lhs;
|
||||
TypeAbstraction lhsType = L.getType();
|
||||
TypeAbstraction meet = TypeAbstraction.TOP;
|
||||
for (int i = 0; i < rhs.length; i++) {
|
||||
if (rhs[i] != null) {
|
||||
TypeVariable r = (TypeVariable) rhs[i];
|
||||
meet = meet.meet(r.getType());
|
||||
}
|
||||
}
|
||||
if (lhsType.equals(meet)) {
|
||||
return NOT_CHANGED;
|
||||
} else {
|
||||
L.setType(meet);
|
||||
return CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "propagate";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.dataflow.Operator#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return 99292;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.dataflow.Operator#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof PrimitivePropagateOperator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This operator will extract the element type from an arrayref in an array
|
||||
* access instruction
|
||||
*
|
||||
* TODO: why isn't this a nullary operator?
|
||||
*/
|
||||
private final class GetElementType extends AbstractOperator {
|
||||
private final SSAArrayLoadInstruction load;
|
||||
|
||||
GetElementType(SSAArrayLoadInstruction load) {
|
||||
this.load = load;
|
||||
}
|
||||
|
||||
public byte evaluate(IVariable lhs, IVariable[] rhs) {
|
||||
TypeVariable t = (TypeVariable) lhs;
|
||||
TypeAbstraction arrayType = getType(load.getArrayRef());
|
||||
if (arrayType.equals(TypeAbstraction.TOP)) {
|
||||
return NOT_CHANGED;
|
||||
}
|
||||
TypeReference elementType = null;
|
||||
|
||||
if (arrayType instanceof PointType) {
|
||||
elementType = ((PointType) arrayType).getType().getReference().getArrayElementType();
|
||||
} else if (arrayType instanceof ConeType) {
|
||||
elementType = ((ConeType) arrayType).getType().getReference().getArrayElementType();
|
||||
} else {
|
||||
Assertions.UNREACHABLE("Unexpected type " + arrayType.getClass());
|
||||
}
|
||||
if (elementType.isPrimitiveType()) {
|
||||
if (doPrimitives && t.getType() == TypeAbstraction.TOP) {
|
||||
t.setType(PrimitiveType.getPrimitive(elementType));
|
||||
return CHANGED;
|
||||
}
|
||||
return NOT_CHANGED;
|
||||
}
|
||||
|
||||
if (t.getType() != TypeAbstraction.TOP) {
|
||||
TypeReference tType = null;
|
||||
if (t.getType() instanceof PointType) {
|
||||
tType = ((PointType) t.getType()).getType().getReference();
|
||||
} else if (t.getType() instanceof ConeType) {
|
||||
tType = ((ConeType) t.getType()).getType().getReference();
|
||||
} else {
|
||||
Assertions.UNREACHABLE("Unexpected type " + t.getType().getClass());
|
||||
}
|
||||
if (tType.equals(elementType)) {
|
||||
return NOT_CHANGED;
|
||||
} else {
|
||||
IClass klass = cha.lookupClass(elementType);
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(klass != null);
|
||||
}
|
||||
t.setType(new ConeType(klass, cha));
|
||||
return CHANGED;
|
||||
}
|
||||
} else {
|
||||
IClass klass = cha.lookupClass(elementType);
|
||||
// if (Assertions.verifyAssertions) {
|
||||
// Assertions._assert(klass != null);
|
||||
// }
|
||||
if (klass != null) {
|
||||
t.setType(new ConeType(klass, cha));
|
||||
} else {
|
||||
t.setType(ConeType.TOP);
|
||||
}
|
||||
|
||||
return CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "getElementType " + load;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.dataflow.Operator#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return 9923 * load.hashCode();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.dataflow.Operator#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof GetElementType) {
|
||||
GetElementType other = (GetElementType) o;
|
||||
return load.equals(other.load);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected class TypeOperatorFactory extends SSAInstruction.Visitor implements OperatorFactory {
|
||||
|
||||
protected AbstractOperator result = null;
|
||||
|
||||
public AbstractOperator get(SSAInstruction instruction) {
|
||||
instruction.visit(this);
|
||||
AbstractOperator temp = result;
|
||||
result = null;
|
||||
return temp;
|
||||
}
|
||||
|
||||
public void visitArrayLoad(SSAArrayLoadInstruction instruction) {
|
||||
result = new GetElementType(instruction);
|
||||
}
|
||||
|
||||
public void visitArrayLength(SSAArrayLengthInstruction instruction) {
|
||||
if (!doPrimitives) {
|
||||
result = null;
|
||||
} else {
|
||||
result = new DeclaredTypeOperator(PrimitiveType.INT);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitGet(SSAGetInstruction instruction) {
|
||||
TypeReference type = instruction.getDeclaredFieldType();
|
||||
|
||||
if (doPrimitives && type.isPrimitiveType()) {
|
||||
result = new DeclaredTypeOperator(PrimitiveType.getPrimitive(type));
|
||||
} else {
|
||||
IClass klass = cha.lookupClass(type);
|
||||
if (klass == null) {
|
||||
// get from a field of a type that cannot be loaded.
|
||||
// be pessimistic
|
||||
result = new DeclaredTypeOperator(BOTTOM);
|
||||
} else {
|
||||
result = new DeclaredTypeOperator(new ConeType(klass, cha));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitInvoke(SSAInvokeInstruction instruction) {
|
||||
TypeReference type = instruction.getDeclaredResultType();
|
||||
if (type.isReferenceType()) {
|
||||
IClass klass = cha.lookupClass(type);
|
||||
if (klass == null) {
|
||||
// a type that cannot be loaded.
|
||||
// be pessimistic
|
||||
result = new DeclaredTypeOperator(BOTTOM);
|
||||
} else {
|
||||
result = new DeclaredTypeOperator(new ConeType(klass, cha));
|
||||
}
|
||||
} else if (doPrimitives && type.isPrimitiveType()) {
|
||||
result = new DeclaredTypeOperator(PrimitiveType.getPrimitive(type));
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void visitNew(SSANewInstruction instruction) {
|
||||
TypeReference type = instruction.getConcreteType();
|
||||
IClass klass = cha.lookupClass(type);
|
||||
if (klass == null) {
|
||||
// a type that cannot be loaded.
|
||||
// be pessimistic
|
||||
result = new DeclaredTypeOperator(BOTTOM);
|
||||
} else {
|
||||
result = new DeclaredTypeOperator(new PointType(klass, cha));
|
||||
}
|
||||
}
|
||||
|
||||
public void visitCheckCast(SSACheckCastInstruction instruction) {
|
||||
TypeReference type = instruction.getDeclaredResultType();
|
||||
IClass klass = cha.lookupClass(type);
|
||||
if (klass == null) {
|
||||
// a type that cannot be loaded.
|
||||
// be pessimistic
|
||||
result = new DeclaredTypeOperator(BOTTOM);
|
||||
} else {
|
||||
result = new DeclaredTypeOperator(new ConeType(klass, cha));
|
||||
}
|
||||
}
|
||||
|
||||
public void visitConversion(SSAConversionInstruction instruction) {
|
||||
if (doPrimitives) {
|
||||
result = new DeclaredTypeOperator(PrimitiveType.getPrimitive(instruction.getToType()));
|
||||
}
|
||||
}
|
||||
|
||||
public void visitBinaryOp(SSABinaryOpInstruction instruction) {
|
||||
if (doPrimitives) {
|
||||
result = primitivePropagateOp;
|
||||
}
|
||||
}
|
||||
|
||||
public void visitUnaryOp(SSAUnaryOpInstruction instruction) {
|
||||
if (doPrimitives) {
|
||||
result = primitivePropagateOp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void visitGetCaughtException(SSAGetCaughtExceptionInstruction instruction) {
|
||||
TypeAbstraction type = meetDeclaredExceptionTypes(instruction, cha);
|
||||
result = new DeclaredTypeOperator(type);
|
||||
}
|
||||
|
||||
public void visitPhi(SSAPhiInstruction instruction) {
|
||||
result = phiOp;
|
||||
}
|
||||
|
||||
public void visitPi(SSAPiInstruction instruction) {
|
||||
result = piOp;
|
||||
}
|
||||
|
||||
private TypeAbstraction meetDeclaredExceptionTypes(SSAGetCaughtExceptionInstruction s, ClassHierarchy cha) {
|
||||
ExceptionHandlerBasicBlock bb = (ExceptionHandlerBasicBlock) ir.getControlFlowGraph().getNode(s.getBasicBlockNumber());
|
||||
Iterator it = bb.getCaughtExceptionTypes();
|
||||
TypeReference t = (TypeReference) it.next();
|
||||
IClass klass = cha.lookupClass(t);
|
||||
TypeAbstraction result = null;
|
||||
if (klass == null) {
|
||||
// a type that cannot be loaded.
|
||||
// be pessimistic
|
||||
result = BOTTOM;
|
||||
} else {
|
||||
result = new ConeType(klass, cha);
|
||||
}
|
||||
while (it.hasNext()) {
|
||||
t = (TypeReference) it.next();
|
||||
IClass tClass = cha.lookupClass(t);
|
||||
if (tClass == null) {
|
||||
result = BOTTOM;
|
||||
} else {
|
||||
result = result.meet(new ConeType(tClass, cha));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A type variable in the dataflow system.
|
||||
*/
|
||||
protected static class TypeVariable extends AbstractVariable {
|
||||
|
||||
private TypeAbstraction type;
|
||||
|
||||
private final int hash;
|
||||
|
||||
public TypeVariable(TypeAbstraction type, int hashCode) {
|
||||
this.type = type;
|
||||
this.hash = hashCode;
|
||||
}
|
||||
|
||||
public void copyState(IVariable v) {
|
||||
TypeVariable other = (TypeVariable) v;
|
||||
this.type = other.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type.
|
||||
*
|
||||
* @return TypeAbstraction
|
||||
*/
|
||||
public TypeAbstraction getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type.
|
||||
*
|
||||
* @param type
|
||||
* The type to set
|
||||
*/
|
||||
public void setType(TypeAbstraction type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return type.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.dataflow.AbstractVariable#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class TypeVarFactory implements VariableFactory {
|
||||
|
||||
public IVariable makeVariable(int valueNumber) {
|
||||
SymbolTable st = ir.getSymbolTable();
|
||||
if (doPrimitives) {
|
||||
if (st.isConstant(valueNumber)) {
|
||||
if (st.isBooleanConstant(valueNumber)) {
|
||||
return new TypeVariable(PrimitiveType.BOOLEAN, 797 * valueNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (st.isStringConstant(valueNumber)) {
|
||||
// IClass klass = cha.lookupClass(TypeReference.JavaLangString);
|
||||
// TypeAbstraction stringTypeAbs = new PointType(klass,cha);
|
||||
// return new TypeVariable(stringTypeAbs, 797 * valueNumber);
|
||||
// }
|
||||
return new TypeVariable(TypeAbstraction.TOP, 797 * valueNumber);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ir.
|
||||
*
|
||||
* @return IR
|
||||
*/
|
||||
public IR getIR() {
|
||||
return ir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getType.
|
||||
*
|
||||
* @param valueNumber
|
||||
* @return JavaTypeAbstraction
|
||||
*/
|
||||
public TypeAbstraction getType(int valueNumber) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
if (getVariable(valueNumber) == null) {
|
||||
Assertions._assert(getVariable(valueNumber) != null, "null variable for value number " + valueNumber);
|
||||
}
|
||||
}
|
||||
return ((TypeVariable) getVariable(valueNumber)).getType();
|
||||
}
|
||||
|
||||
public TypeAbstraction getConstantType(int valueNumber) {
|
||||
if (ir.getSymbolTable().isStringConstant(valueNumber)) {
|
||||
return new PointType(cha.lookupClass(TypeReference.JavaLangString), cha);
|
||||
} else {
|
||||
return getConstantPrimitiveType(valueNumber);
|
||||
}
|
||||
}
|
||||
|
||||
public TypeAbstraction getConstantPrimitiveType(int valueNumber) {
|
||||
SymbolTable st = ir.getSymbolTable();
|
||||
if (!st.isConstant(valueNumber)) {
|
||||
return TypeAbstraction.TOP;
|
||||
}
|
||||
if (st.isIntegerConstant(valueNumber)) {
|
||||
return PrimitiveType.INT;
|
||||
} else if (st.isFloatConstant(valueNumber)) {
|
||||
return PrimitiveType.FLOAT;
|
||||
} else if (st.isDoubleConstant(valueNumber)) {
|
||||
return PrimitiveType.DOUBLE;
|
||||
}
|
||||
return TypeAbstraction.TOP;
|
||||
}
|
||||
|
||||
public boolean isUndefined(int valueNumber) {
|
||||
// TODO: Julian, you seem to be using BOTTOM in the European style.
|
||||
// Steve's code assumes American style (god forbid), so what you're getting
|
||||
// here
|
||||
// is not undefined, but java.lang.Object [NR/EY]
|
||||
if (getVariable(valueNumber) == null)
|
||||
return true;
|
||||
TypeAbstraction ta = ((TypeVariable) getVariable(valueNumber)).getType();
|
||||
return ta == BOTTOM || ta.getType() == null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
This package provides intraprocedural type inference over the SSA form.
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,656 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.cfg;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.shrikeBT.Constants;
|
||||
import com.ibm.wala.util.CompoundIterator;
|
||||
import com.ibm.wala.util.IteratorPlusOne;
|
||||
import com.ibm.wala.util.IteratorPlusTwo;
|
||||
import com.ibm.wala.util.collections.EmptyIterator;
|
||||
import com.ibm.wala.util.collections.Filter;
|
||||
import com.ibm.wala.util.collections.FilterIterator;
|
||||
import com.ibm.wala.util.collections.Iterator2Collection;
|
||||
import com.ibm.wala.util.collections.NonNullSingletonIterator;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.graph.impl.DelegatingNumberedNodeManager;
|
||||
import com.ibm.wala.util.graph.impl.NumberedNodeIterator;
|
||||
import com.ibm.wala.util.graph.impl.SparseNumberedEdgeManager;
|
||||
import com.ibm.wala.util.intset.BasicNonNegativeIntRelation;
|
||||
import com.ibm.wala.util.intset.BitVector;
|
||||
import com.ibm.wala.util.intset.FixedSizeBitVector;
|
||||
import com.ibm.wala.util.intset.IntSet;
|
||||
import com.ibm.wala.util.intset.MutableSparseIntSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* A graph of basic blocks.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public abstract class AbstractCFG implements ControlFlowGraph, Constants {
|
||||
|
||||
/**
|
||||
* The method this AbstractCFG represents
|
||||
*/
|
||||
private final IMethod method;
|
||||
|
||||
/**
|
||||
* An object to track nodes in this cfg
|
||||
*/
|
||||
private DelegatingNumberedNodeManager<IBasicBlock> nodeManager = new DelegatingNumberedNodeManager<IBasicBlock>();
|
||||
|
||||
/**
|
||||
* An object to track most normal edges in this cfg
|
||||
*/
|
||||
private SparseNumberedEdgeManager<IBasicBlock> normalEdgeManager = new SparseNumberedEdgeManager<IBasicBlock>(nodeManager, 2,
|
||||
BasicNonNegativeIntRelation.SIMPLE);
|
||||
|
||||
/**
|
||||
* An object to track not-to-exit exceptional edges in this cfg
|
||||
*/
|
||||
private SparseNumberedEdgeManager<IBasicBlock> exceptionalEdgeManager = new SparseNumberedEdgeManager<IBasicBlock>(nodeManager,
|
||||
0, BasicNonNegativeIntRelation.SIMPLE);
|
||||
|
||||
/**
|
||||
* Which basic blocks have a normal edge to exit()?
|
||||
*/
|
||||
private FixedSizeBitVector normalToExit;
|
||||
|
||||
/**
|
||||
* Which basic blocks have an exceptional edge to exit()?
|
||||
*/
|
||||
private FixedSizeBitVector exceptionalToExit;
|
||||
|
||||
/**
|
||||
* Which basic blocks have a fall-through?
|
||||
*/
|
||||
private FixedSizeBitVector fallThru;
|
||||
|
||||
/**
|
||||
* Which basic blocks are catch blocks?
|
||||
*/
|
||||
private BitVector catchBlocks;
|
||||
|
||||
/**
|
||||
* Cache here for efficiency
|
||||
*/
|
||||
private IBasicBlock exit;
|
||||
|
||||
/**
|
||||
* @param method
|
||||
*/
|
||||
protected AbstractCFG(IMethod method) {
|
||||
this.method = method;
|
||||
this.catchBlocks = new BitVector(10);
|
||||
}
|
||||
|
||||
/**
|
||||
* subclasses must call this before calling addEdge, but after creating the
|
||||
* nodes
|
||||
*/
|
||||
protected void init() {
|
||||
normalToExit = new FixedSizeBitVector(getMaxNumber() + 1);
|
||||
exceptionalToExit = new FixedSizeBitVector(getMaxNumber() + 1);
|
||||
fallThru = new FixedSizeBitVector(getMaxNumber() + 1);
|
||||
exit = (IBasicBlock) getNode(getMaxNumber());
|
||||
}
|
||||
|
||||
public abstract boolean equals(Object o);
|
||||
|
||||
public abstract int hashCode();
|
||||
|
||||
/**
|
||||
* Return the entry basic block for the CFG.
|
||||
*
|
||||
* @return the entry basic block for the CFG.
|
||||
*/
|
||||
public IBasicBlock entry() {
|
||||
return (IBasicBlock) getNode(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the exit basic block for the CFG.
|
||||
*
|
||||
* @return the exit basic block for the CFG.
|
||||
*/
|
||||
public IBasicBlock exit() {
|
||||
return exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public int getPredNodeCount(IBasicBlock N) {
|
||||
if (N.equals(exit())) {
|
||||
// TODO: cache if necessary
|
||||
FixedSizeBitVector x = FixedSizeBitVector.or(normalToExit, exceptionalToExit);
|
||||
return x.populationCount();
|
||||
} else {
|
||||
boolean normalIn = getNumberOfNormalIn(N) > 0;
|
||||
boolean exceptionalIn = getNumberOfExceptionalIn(N) > 0;
|
||||
if (normalIn) {
|
||||
if (exceptionalIn) {
|
||||
return new Iterator2Collection<IBasicBlock>(getPredNodes(N)).size();
|
||||
} else {
|
||||
return getNumberOfNormalIn(N);
|
||||
}
|
||||
} else {
|
||||
return getNumberOfExceptionalIn(N);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getNumberOfNormalIn(IBasicBlock N) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(!N.equals(exit()));
|
||||
}
|
||||
int number = getNumber(N);
|
||||
int xtra = 0;
|
||||
if (number > 0) {
|
||||
if (fallThru.get(number - 1)) {
|
||||
xtra++;
|
||||
}
|
||||
}
|
||||
return normalEdgeManager.getPredNodeCount(N) + xtra;
|
||||
}
|
||||
|
||||
public int getNumberOfExceptionalIn(IBasicBlock N) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(!N.equals(exit()));
|
||||
}
|
||||
return exceptionalEdgeManager.getPredNodeCount(N);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param number
|
||||
* number of a basic block in this cfg
|
||||
*/
|
||||
boolean hasAnyNormalOut(int number) {
|
||||
return (fallThru.get(number) || normalEdgeManager.getSuccNodeCount(number) > 0 || normalToExit.get(number));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param number
|
||||
* number of a basic block in this cfg
|
||||
*/
|
||||
private int getNumberOfNormalOut(int number) {
|
||||
int xtra = 0;
|
||||
if (fallThru.get(number)) {
|
||||
xtra++;
|
||||
}
|
||||
if (normalToExit.get(number)) {
|
||||
xtra++;
|
||||
}
|
||||
return normalEdgeManager.getSuccNodeCount(number) + xtra;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param number
|
||||
* number of a basic block in this cfg
|
||||
*/
|
||||
public int getNumberOfExceptionalOut(int number) {
|
||||
int xtra = 0;
|
||||
if (exceptionalToExit.get(number)) {
|
||||
xtra++;
|
||||
}
|
||||
return exceptionalEdgeManager.getSuccNodeCount(number) + xtra;
|
||||
}
|
||||
|
||||
public int getNumberOfNormalOut(IBasicBlock N) {
|
||||
return getNumberOfNormalOut(getNumber(N));
|
||||
}
|
||||
|
||||
public int getNumberOfExceptionalOut(IBasicBlock N) {
|
||||
return getNumberOfExceptionalOut(getNumber(N));
|
||||
}
|
||||
|
||||
public Iterator<IBasicBlock> getPredNodes(IBasicBlock N) {
|
||||
if (N.equals(exit())) {
|
||||
return new FilterIterator<IBasicBlock>(iterateNodes(), new Filter() {
|
||||
public boolean accepts(Object o) {
|
||||
int i = getNumber((IBasicBlock) o);
|
||||
return normalToExit.get(i) || exceptionalToExit.get(i);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
int number = getNumber(N);
|
||||
boolean normalIn = getNumberOfNormalIn(N) > 0;
|
||||
boolean exceptionalIn = getNumberOfExceptionalIn(N) > 0;
|
||||
if (normalIn) {
|
||||
if (exceptionalIn) {
|
||||
HashSet<IBasicBlock> result = new HashSet<IBasicBlock>(getNumberOfNormalIn(N) + getNumberOfExceptionalIn(N));
|
||||
result.addAll(new Iterator2Collection<IBasicBlock>(normalEdgeManager.getPredNodes(N)));
|
||||
result.addAll(new Iterator2Collection<IBasicBlock>(exceptionalEdgeManager.getPredNodes(N)));
|
||||
if (fallThru.get(number - 1)) {
|
||||
result.add(getNode(number - 1));
|
||||
}
|
||||
return result.iterator();
|
||||
} else {
|
||||
if (number > 0 && fallThru.get(number - 1)) {
|
||||
return new IteratorPlusOne<IBasicBlock>(normalEdgeManager.getPredNodes(N), getNode(number - 1));
|
||||
} else {
|
||||
return normalEdgeManager.getPredNodes(N);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// !normalIn
|
||||
if (exceptionalIn) {
|
||||
return exceptionalEdgeManager.getPredNodes(N);
|
||||
} else {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getSuccNodeCount(IBasicBlock N) {
|
||||
if (N.equals(exit())) {
|
||||
return 0;
|
||||
}
|
||||
int nNormal = getNumberOfNormalOut(N);
|
||||
int nExc = getNumberOfExceptionalOut(N);
|
||||
if (nNormal > 0) {
|
||||
if (nExc > 0) {
|
||||
if (nExc == 1) {
|
||||
int number = getNumber(N);
|
||||
if (exceptionalToExit.get(number)) {
|
||||
if (normalToExit.get(number)) {
|
||||
return nNormal + nExc - 1;
|
||||
} else {
|
||||
return nNormal + nExc;
|
||||
}
|
||||
} else {
|
||||
return slowCountSuccNodes(N);
|
||||
}
|
||||
} else {
|
||||
return slowCountSuccNodes(N);
|
||||
}
|
||||
} else {
|
||||
return nNormal;
|
||||
}
|
||||
} else {
|
||||
// nNormal == 0
|
||||
return nExc;
|
||||
}
|
||||
}
|
||||
|
||||
private int slowCountSuccNodes(IBasicBlock N) {
|
||||
return new Iterator2Collection<IBasicBlock>(getSuccNodes(N)).size();
|
||||
}
|
||||
|
||||
public Iterator<IBasicBlock> getSuccNodes(IBasicBlock N) {
|
||||
int number = getNumber(N);
|
||||
if (normalToExit.get(number) && exceptionalToExit.get(number)) {
|
||||
return new CompoundIterator<IBasicBlock>(iterateNormalSuccessorsWithoutExit(number), iterateExceptionalSuccessors(number));
|
||||
} else {
|
||||
return new CompoundIterator<IBasicBlock>(iterateNormalSuccessors(number), iterateExceptionalSuccessors(number));
|
||||
}
|
||||
}
|
||||
|
||||
private Iterator<IBasicBlock> iterateExceptionalSuccessors(int number) {
|
||||
if (exceptionalEdgeManager.hasAnySuccessor(number)) {
|
||||
if (exceptionalToExit.get(number)) {
|
||||
return new IteratorPlusOne<IBasicBlock>(exceptionalEdgeManager.getSuccNodes(number), exit());
|
||||
} else {
|
||||
return exceptionalEdgeManager.getSuccNodes(number);
|
||||
}
|
||||
} else {
|
||||
if (exceptionalToExit.get(number)) {
|
||||
return new NonNullSingletonIterator<IBasicBlock>(exit());
|
||||
} else {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<IBasicBlock> iterateExceptionalPredecessors(IBasicBlock N) {
|
||||
if (N.equals(exit())) {
|
||||
return new FilterIterator<IBasicBlock>(iterateNodes(), new Filter() {
|
||||
public boolean accepts(Object o) {
|
||||
int i = getNumber((IBasicBlock) o);
|
||||
return exceptionalToExit.get(i);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return exceptionalEdgeManager.getPredNodes(N);
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<IBasicBlock> iterateNormalPredecessors(IBasicBlock N) {
|
||||
if (N.equals(exit())) {
|
||||
return new FilterIterator<IBasicBlock>(iterateNodes(), new Filter() {
|
||||
public boolean accepts(Object o) {
|
||||
int i = getNumber((IBasicBlock) o);
|
||||
return normalToExit.get(i);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
int number = getNumber(N);
|
||||
if (number > 0 && fallThru.get(number - 1)) {
|
||||
return new IteratorPlusOne<IBasicBlock>(normalEdgeManager.getPredNodes(N), getNode(number - 1));
|
||||
} else {
|
||||
return normalEdgeManager.getPredNodes(N);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Iterator<IBasicBlock> iterateNormalSuccessors(int number) {
|
||||
if (fallThru.get(number)) {
|
||||
if (normalToExit.get(number)) {
|
||||
return new IteratorPlusTwo<IBasicBlock>(normalEdgeManager.getSuccNodes(number), getNode(number + 1), exit());
|
||||
} else {
|
||||
return new IteratorPlusOne<IBasicBlock>(normalEdgeManager.getSuccNodes(number), getNode(number + 1));
|
||||
}
|
||||
} else {
|
||||
if (normalToExit.get(number)) {
|
||||
return new IteratorPlusOne<IBasicBlock>(normalEdgeManager.getSuccNodes(number), exit());
|
||||
} else {
|
||||
return normalEdgeManager.getSuccNodes(number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Iterator<IBasicBlock> iterateNormalSuccessorsWithoutExit(int number) {
|
||||
if (fallThru.get(number)) {
|
||||
return new IteratorPlusOne<IBasicBlock>(normalEdgeManager.getSuccNodes(number), getNode(number + 1));
|
||||
} else {
|
||||
return normalEdgeManager.getSuccNodes(number);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param n
|
||||
*/
|
||||
public void addNode(IBasicBlock n) {
|
||||
nodeManager.addNode(n);
|
||||
}
|
||||
|
||||
public int getMaxNumber() {
|
||||
return nodeManager.getMaxNumber();
|
||||
}
|
||||
|
||||
public IBasicBlock getNode(int number) {
|
||||
return nodeManager.getNode(number);
|
||||
}
|
||||
|
||||
public int getNumber(IBasicBlock N) {
|
||||
return nodeManager.getNumber(N);
|
||||
}
|
||||
|
||||
public int getNumberOfNodes() {
|
||||
return nodeManager.getNumberOfNodes();
|
||||
}
|
||||
|
||||
public Iterator<IBasicBlock> iterateNodes() {
|
||||
return nodeManager.iterateNodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param src
|
||||
* @param dst
|
||||
*/
|
||||
public void addEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
Assertions.UNREACHABLE("Don't call me .. use addNormalEdge or addExceptionalEdge");
|
||||
}
|
||||
|
||||
public void removeEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public boolean hasEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
int x = getNumber(src);
|
||||
if (dst.equals(exit())) {
|
||||
return normalToExit.get(x) || exceptionalToExit.get(x);
|
||||
} else if (getNumber(dst) == (x + 1) && fallThru.get(x)) {
|
||||
return true;
|
||||
}
|
||||
return normalEdgeManager.hasEdge(src, dst) || exceptionalEdgeManager.hasEdge(src, dst);
|
||||
}
|
||||
|
||||
public boolean hasExceptionalEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
int x = getNumber(src);
|
||||
if (dst.equals(exit())) {
|
||||
return exceptionalToExit.get(x);
|
||||
}
|
||||
return exceptionalEdgeManager.hasEdge(src, dst);
|
||||
}
|
||||
|
||||
public boolean hasNormalEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
int x = getNumber(src);
|
||||
if (dst.equals(exit())) {
|
||||
return normalToExit.get(x);
|
||||
} else if (getNumber(dst) == (x + 1) && fallThru.get(x)) {
|
||||
return true;
|
||||
}
|
||||
return normalEdgeManager.hasEdge(src, dst);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param src
|
||||
* @param dst
|
||||
*/
|
||||
public void addNormalEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
if (dst.equals(exit())) {
|
||||
normalToExit.set(getNumber(src));
|
||||
} else if (getNumber(dst) == (getNumber(src) + 1)) {
|
||||
fallThru.set(getNumber(src));
|
||||
} else {
|
||||
normalEdgeManager.addEdge(src, dst);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param src
|
||||
* @param dst
|
||||
*/
|
||||
public void addExceptionalEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
if (dst.equals(exit())) {
|
||||
exceptionalToExit.set(getNumber(src));
|
||||
} else {
|
||||
exceptionalEdgeManager.addEdge(src, dst);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.Graph#removeNode(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public void removeNodeAndEdges(IBasicBlock N) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#remove(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public void removeNode(IBasicBlock n) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#containsNode(com.ibm.wala.util.graph.Node)
|
||||
*/
|
||||
public boolean containsNode(IBasicBlock N) {
|
||||
return nodeManager.containsNode(N);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer s = new StringBuffer("");
|
||||
for (Iterator it = iterateNodes(); it.hasNext();) {
|
||||
IBasicBlock bb = (IBasicBlock) it.next();
|
||||
s.append("BB").append(getNumber(bb)).append("\n");
|
||||
|
||||
Iterator<IBasicBlock> succNodes = getSuccNodes(bb);
|
||||
while (succNodes.hasNext()) {
|
||||
s.append(" -> BB").append(getNumber(succNodes.next())).append("\n");
|
||||
}
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* record that basic block i is a catch block
|
||||
*
|
||||
* @param i
|
||||
*/
|
||||
protected void setCatchBlock(int i) {
|
||||
catchBlocks.set(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i
|
||||
* @return true iff block i is a catch block
|
||||
*/
|
||||
public boolean isCatchBlock(int i) {
|
||||
return catchBlocks.get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the catchBlocks.
|
||||
*
|
||||
* @return BitVector
|
||||
*/
|
||||
public BitVector getCatchBlocks() {
|
||||
return catchBlocks;
|
||||
}
|
||||
|
||||
public IMethod getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.EdgeManager#removeEdges(java.lang.Object)
|
||||
*/
|
||||
public void removeAllIncidentEdges(IBasicBlock node) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getExceptionalSuccessors(com.ibm.wala.cfg.IBasicBlock)
|
||||
*/
|
||||
public Collection<IBasicBlock> getExceptionalSuccessors(IBasicBlock b) {
|
||||
return new Iterator2Collection<IBasicBlock>(iterateExceptionalSuccessors(b.getNumber()));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getNormalSuccessors(com.ibm.wala.cfg.IBasicBlock)
|
||||
*/
|
||||
public Collection<IBasicBlock> getNormalSuccessors(IBasicBlock b) {
|
||||
return new Iterator2Collection<IBasicBlock>(iterateNormalSuccessors(b.getNumber()));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NumberedNodeManager#iterateNodes(com.ibm.wala.util.intset.IntSet)
|
||||
*/
|
||||
public Iterator<IBasicBlock> iterateNodes(IntSet s) {
|
||||
return new NumberedNodeIterator<IBasicBlock>(s, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public void removeIncomingEdges(IBasicBlock node) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public void removeOutgoingEdges(IBasicBlock node) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public FixedSizeBitVector getExceptionalToExit() {
|
||||
return exceptionalToExit;
|
||||
}
|
||||
|
||||
public FixedSizeBitVector getNormalToExit() {
|
||||
return normalToExit;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getExceptionalPredecessors(com.ibm.wala.cfg.IBasicBlock)
|
||||
*/
|
||||
public Collection<IBasicBlock> getExceptionalPredecessors(IBasicBlock b) {
|
||||
return new Iterator2Collection<IBasicBlock>(iterateExceptionalPredecessors(b));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getNormalPredecessors(com.ibm.wala.cfg.IBasicBlock)
|
||||
*/
|
||||
public Collection<IBasicBlock> getNormalPredecessors(IBasicBlock b) {
|
||||
return new Iterator2Collection<IBasicBlock>(iterateNormalPredecessors(b));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public IntSet getPredNodeNumbers(IBasicBlock node) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: optimize this. (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public IntSet getSuccNodeNumbers(IBasicBlock node) {
|
||||
int number = getNumber(node);
|
||||
IntSet s = normalEdgeManager.getSuccNodeNumbers(node);
|
||||
MutableSparseIntSet result = s == null ? new MutableSparseIntSet() : new MutableSparseIntSet(s);
|
||||
s = exceptionalEdgeManager.getSuccNodeNumbers(node);
|
||||
if (s != null) {
|
||||
result.addAll(s);
|
||||
}
|
||||
if (normalToExit.get(number) || exceptionalToExit.get(number)) {
|
||||
result.add(exit.getNumber());
|
||||
}
|
||||
if (fallThru.get(number)) {
|
||||
result.add(number + 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.cfg;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.IRFactory;
|
||||
import com.ibm.wala.util.CacheReference;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* A mapping from IMethod -> SoftReference -> ShrikeCFG
|
||||
*
|
||||
* This doesn't work very well ... GCs don't do such a great job with
|
||||
* SoftReferences ... revamp it.
|
||||
*
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class CFGCache {
|
||||
|
||||
/**
|
||||
* Help out the garbage collector: periodically "reset" this cache
|
||||
*/
|
||||
final private static int RESET_INTERVAL = 10000;
|
||||
|
||||
/**
|
||||
* A mapping from ShrikeCTMethodWrapper -> SoftReference -> IR
|
||||
*/
|
||||
private HashMap<Object, Object> dictionary = new HashMap<Object, Object>();
|
||||
|
||||
/**
|
||||
* Count accesses between resets.
|
||||
*/
|
||||
private int resetCount = 0;
|
||||
|
||||
/**
|
||||
* The factory that actually creates new IR objects
|
||||
*/
|
||||
private final IRFactory factory;
|
||||
|
||||
public CFGCache(IRFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param m
|
||||
* a "normal" (bytecode-based) method
|
||||
* @param warnings
|
||||
* an option to track analysis warnings
|
||||
* @return an IR for m, built according to the specified options. null if m is
|
||||
* abstract or native.
|
||||
*/
|
||||
public synchronized ControlFlowGraph findOrCreate(IMethod m, Context C, ClassHierarchy cha, WarningSet warnings) {
|
||||
|
||||
if (m.isAbstract() || m.isNative()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
processResetLogic(m);
|
||||
|
||||
Pair<IMethod,Context> p = new Pair<IMethod,Context>(m, C);
|
||||
Object ref = dictionary.get(p);
|
||||
if (ref == null || CacheReference.get(ref) == null) {
|
||||
ControlFlowGraph cfg = factory.makeCFG(m, C, cha, warnings);
|
||||
ref = CacheReference.make(cfg);
|
||||
dictionary.put(p, ref);
|
||||
return cfg;
|
||||
} else {
|
||||
ControlFlowGraph cfg = (ControlFlowGraph) CacheReference.get(ref);
|
||||
return (cfg == null) ? findOrCreate(m, C, cha, warnings) : cfg;
|
||||
}
|
||||
}
|
||||
|
||||
private void processResetLogic(IMethod m) {
|
||||
resetCount++;
|
||||
if (resetCount == RESET_INTERVAL) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The existence of this is unfortunate.
|
||||
*/
|
||||
public void wipe() {
|
||||
dictionary = new HashMap<Object, Object>();
|
||||
}
|
||||
|
||||
/**
|
||||
* clear out null refs
|
||||
*/
|
||||
private void reset() {
|
||||
resetCount = 0;
|
||||
Map<Object, Object> oldDictionary = dictionary;
|
||||
dictionary = new HashMap<Object, Object>();
|
||||
|
||||
for (Iterator it = oldDictionary.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry e = (Map.Entry) it.next();
|
||||
Object key = e.getKey();
|
||||
Object val = e.getValue();
|
||||
if (CacheReference.get(val) != null) {
|
||||
dictionary.put(key, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate cached information relating to a method
|
||||
*
|
||||
* @param method
|
||||
*/
|
||||
public void invalidate(IMethod method, Context C) {
|
||||
dictionary.remove(new Pair<IMethod,Context>(method, C));
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.cfg;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSACFG;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAReturnInstruction;
|
||||
import com.ibm.wala.ssa.SSAThrowInstruction;
|
||||
import com.ibm.wala.ssa.SSACFG.ExceptionHandlerBasicBlock;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.Exceptions;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.graph.Graph;
|
||||
import com.ibm.wala.util.graph.impl.SlowSparseNumberedGraph;
|
||||
import com.ibm.wala.util.warnings.WalaException;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
* Utility class to remove edges to exit() from a CFG
|
||||
*
|
||||
* @author Stephen Fink
|
||||
*/
|
||||
public class CFGSanitizer {
|
||||
|
||||
/*
|
||||
*/
|
||||
public static Graph<IBasicBlock> sanitize(IR ir, ClassHierarchy cha) throws WalaException {
|
||||
|
||||
Assertions._assert(ir != null, "IR is null");
|
||||
|
||||
ControlFlowGraph cfg = ir.getControlFlowGraph();
|
||||
Graph<IBasicBlock> G = new SlowSparseNumberedGraph<IBasicBlock>();
|
||||
// add all nodes to the graph
|
||||
for (Iterator<? extends IBasicBlock> it = cfg.iterateNodes(); it.hasNext();) {
|
||||
G.addNode(it.next());
|
||||
}
|
||||
|
||||
// add all edges to the graph, except those that go to exit
|
||||
for (Iterator it = cfg.iterateNodes(); it.hasNext();) {
|
||||
IBasicBlock b = (IBasicBlock) it.next();
|
||||
for (Iterator it2 = cfg.getSuccNodes(b); it2.hasNext();) {
|
||||
IBasicBlock b2 = (IBasicBlock) it2.next();
|
||||
|
||||
if (!b2.isExitBlock()) {
|
||||
G.addEdge(b, b2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now add edges to exit, ignoring undeclared exceptions
|
||||
IBasicBlock exit = cfg.exit();
|
||||
|
||||
for (Iterator it = cfg.getPredNodes(exit); it.hasNext();) {
|
||||
// for each predecessor of exit ...
|
||||
IBasicBlock b = (IBasicBlock) it.next();
|
||||
|
||||
SSAInstruction s = ir.getInstructions()[b.getLastInstructionIndex()];
|
||||
if (s == null) {
|
||||
// TODO: this shouldn't happen?
|
||||
continue;
|
||||
}
|
||||
if (s instanceof SSAReturnInstruction || s instanceof SSAThrowInstruction) {
|
||||
// return or athrow: add edge to exit
|
||||
G.addEdge(b, exit);
|
||||
} else {
|
||||
// compute types of exceptions the pei may throw
|
||||
TypeReference[] exceptions = computeExceptions(cha, s);
|
||||
// remove any exceptions that are caught by catch blocks
|
||||
for (Iterator it2 = cfg.getSuccNodes(b); it2.hasNext();) {
|
||||
IBasicBlock c = (IBasicBlock) it2.next();
|
||||
|
||||
if (c.isCatchBlock()) {
|
||||
SSACFG.ExceptionHandlerBasicBlock cb = (ExceptionHandlerBasicBlock) c;
|
||||
|
||||
for (Iterator it3 = cb.getCaughtExceptionTypes(); it3.hasNext();) {
|
||||
TypeReference ex = (TypeReference) it3.next();
|
||||
IClass exClass = cha.lookupClass(ex);
|
||||
if (exClass == null) {
|
||||
throw new WalaException("failed to find " + ex);
|
||||
}
|
||||
for (int i = 0; i < exceptions.length; i++) {
|
||||
if (exceptions[i] != null) {
|
||||
IClass exi = cha.lookupClass(exceptions[i]);
|
||||
if (exi == null) {
|
||||
throw new WalaException("failed to find " + exceptions[i]);
|
||||
}
|
||||
if (cha.isSubclassOf(exi, exClass)) {
|
||||
exceptions[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// check the remaining uncaught exceptions
|
||||
TypeReference[] declared = ir.getMethod().getDeclaredExceptions();
|
||||
if (declared != null && exceptions != null) {
|
||||
for (int i = 0; i < exceptions.length; i++) {
|
||||
boolean isDeclared = false;
|
||||
if (exceptions[i] != null) {
|
||||
IClass exi = cha.lookupClass(exceptions[i]);
|
||||
if (exi == null) {
|
||||
throw new WalaException("failed to find " + exceptions[i]);
|
||||
}
|
||||
for (int j = 0; j < declared.length; j++) {
|
||||
IClass dc = cha.lookupClass(declared[j]);
|
||||
if (dc == null) {
|
||||
throw new WalaException("failed to find " + declared[j]);
|
||||
}
|
||||
if (cha.isSubclassOf(exi, dc)) {
|
||||
isDeclared = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isDeclared) {
|
||||
// found a declared exceptional edge
|
||||
G.addEdge(b, exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return G;
|
||||
}
|
||||
|
||||
private static TypeReference[] computeExceptions(ClassHierarchy cha, SSAInstruction s) {
|
||||
Collection c = null;
|
||||
if (s instanceof SSAInvokeInstruction) {
|
||||
SSAInvokeInstruction call = (SSAInvokeInstruction) s;
|
||||
c = Exceptions.inferInvokeExceptions(call.getDeclaredTarget(), cha, new WarningSet());
|
||||
} else {
|
||||
c = s.getExceptionTypes();
|
||||
}
|
||||
if (c == null) {
|
||||
return null;
|
||||
} else {
|
||||
TypeReference[] exceptions = new TypeReference[c.size()];
|
||||
Iterator it = c.iterator();
|
||||
for (int i = 0; i < exceptions.length; i++) {
|
||||
exceptions[i] = (TypeReference) it.next();
|
||||
}
|
||||
return exceptions;
|
||||
}
|
||||
}
|
||||
|
||||
} // CFGSanitizerImpl
|
|
@ -0,0 +1,102 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.cfg;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.shrikeBT.IInstruction;
|
||||
import com.ibm.wala.util.graph.NumberedGraph;
|
||||
import com.ibm.wala.util.intset.BitVector;
|
||||
|
||||
/**
|
||||
* An interface that is common to the Shrike and SSA CFG implementations.
|
||||
*
|
||||
* @author cahoon
|
||||
* @author sfink
|
||||
*/
|
||||
public interface ControlFlowGraph extends NumberedGraph<IBasicBlock> {
|
||||
|
||||
/**
|
||||
* Return the entry basic block in the CFG
|
||||
*/
|
||||
public IBasicBlock entry();
|
||||
|
||||
/**
|
||||
* @return the synthetic exit block for the cfg
|
||||
*/
|
||||
public IBasicBlock exit();
|
||||
|
||||
/**
|
||||
* @return the indices of the catch blocks, as a bit vector
|
||||
*/
|
||||
public BitVector getCatchBlocks();
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* an instruction index
|
||||
* @return the basic block which contains this instruction.
|
||||
*/
|
||||
public IBasicBlock getBlockForInstruction(int index);
|
||||
|
||||
/**
|
||||
* @return the instructions of this CFG, as an array.
|
||||
*/
|
||||
IInstruction[] getInstructions();
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* an instruction index
|
||||
* @return the program counter (bytecode index) corresponding to that
|
||||
* instruction
|
||||
*/
|
||||
public int getProgramCounter(int index);
|
||||
|
||||
/**
|
||||
* @return the Method this CFG represents
|
||||
*/
|
||||
public IMethod getMethod();
|
||||
|
||||
/**
|
||||
* The order of blocks returned should be arbitrary but deterministic.
|
||||
*
|
||||
* @param b
|
||||
* @return the basic blocks which may be reached from b via exceptional
|
||||
* control flow
|
||||
*/
|
||||
public Collection<IBasicBlock> getExceptionalSuccessors(IBasicBlock b);
|
||||
|
||||
/**
|
||||
* The order of blocks returned should be arbitrary but deterministic.
|
||||
* @param b
|
||||
* @return the basic blocks which may be reached from b via normal control
|
||||
* flow
|
||||
*/
|
||||
public Collection<IBasicBlock> getNormalSuccessors(IBasicBlock b);
|
||||
|
||||
/**
|
||||
* The order of blocks returned should be arbitrary but deterministic.
|
||||
*
|
||||
* @param b
|
||||
* @return the basic blocks from which b may be reached via exceptional
|
||||
* control flow
|
||||
*/
|
||||
public Collection<IBasicBlock> getExceptionalPredecessors(IBasicBlock b);
|
||||
|
||||
/**
|
||||
* The order of blocks returned should be arbitrary but deterministic.
|
||||
*
|
||||
* @param b
|
||||
* @return the basic blocks from which b may be reached via normal
|
||||
* control flow
|
||||
*/
|
||||
public Collection<IBasicBlock> getNormalPredecessors(IBasicBlock b);
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.cfg;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.shrikeBT.IInstruction;
|
||||
import com.ibm.wala.util.graph.INodeWithNumber;
|
||||
|
||||
/**
|
||||
* An interface for a basic block in a control flow graph.
|
||||
* @author cahoon
|
||||
* @author Stephen Fink
|
||||
*/
|
||||
public interface IBasicBlock extends INodeWithNumber {
|
||||
|
||||
/**
|
||||
* Get the index of the first instruction in the basic block. The value
|
||||
* is an index into the instruction array that contains all the instructions
|
||||
* for the method.
|
||||
*
|
||||
* If the result is < 0, the block has no instructions
|
||||
*
|
||||
* @return the instruction index for the first instruction in the basic block.
|
||||
*/
|
||||
public int getFirstInstructionIndex();
|
||||
|
||||
/**
|
||||
* Get the index of the last instruction in the basic block. The value
|
||||
* is an index into the instruction array that contains all the instructions
|
||||
* for the method.
|
||||
*
|
||||
* If the result is < 0, the block has no instructions
|
||||
*
|
||||
* @return the instruction index for the last instruction in the basic block
|
||||
*/
|
||||
public int getLastInstructionIndex();
|
||||
|
||||
/**
|
||||
* @return an Iterator of all instructions in this basic block
|
||||
*/
|
||||
public Iterator<? extends IInstruction> iterateAllInstructions();
|
||||
|
||||
/**
|
||||
* Return true if the basic block represents a catch block.
|
||||
* @return true if the basic block represents a catch block.
|
||||
*/
|
||||
public boolean isCatchBlock();
|
||||
|
||||
/**
|
||||
* Return true if the basic block represents the unique exit block.
|
||||
* @return true if the basic block represents the unique exit block.
|
||||
*/
|
||||
public boolean isExitBlock();
|
||||
|
||||
/**
|
||||
* Return true if the basic block represents the unique entry block.
|
||||
* @return true if the basic block represents the unique entry block.
|
||||
*/
|
||||
public boolean isEntryBlock();
|
||||
|
||||
/**
|
||||
* @return governing method for this block
|
||||
*/
|
||||
public IMethod getMethod();
|
||||
|
||||
/**
|
||||
* Each basic block should have a unique number in its cfg
|
||||
* @return the basic block's number
|
||||
*/
|
||||
public int getNumber();
|
||||
|
||||
}
|
|
@ -0,0 +1,524 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.cfg;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.shrikeBT.IInstruction;
|
||||
import com.ibm.wala.ssa.SSAArrayLengthInstruction;
|
||||
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
|
||||
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
|
||||
import com.ibm.wala.ssa.SSACheckCastInstruction;
|
||||
import com.ibm.wala.ssa.SSAConditionalBranchInstruction;
|
||||
import com.ibm.wala.ssa.SSAGetInstruction;
|
||||
import com.ibm.wala.ssa.SSAGotoInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAMonitorInstruction;
|
||||
import com.ibm.wala.ssa.SSANewInstruction;
|
||||
import com.ibm.wala.ssa.SSAPutInstruction;
|
||||
import com.ibm.wala.ssa.SSAReturnInstruction;
|
||||
import com.ibm.wala.ssa.SSASwitchInstruction;
|
||||
import com.ibm.wala.ssa.SSAThrowInstruction;
|
||||
import com.ibm.wala.util.collections.ArrayIterator;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.util.graph.GraphIntegrity;
|
||||
import com.ibm.wala.util.graph.GraphIntegrity.UnsoundGraphException;
|
||||
import com.ibm.wala.util.graph.impl.NodeWithNumber;
|
||||
|
||||
/**
|
||||
* A ControlFlowGraph computed from a set of SSA instructions
|
||||
*
|
||||
* This is a funny CFG ... we assume that there are always fallthru edges, even
|
||||
* from throws and returns.
|
||||
*/
|
||||
public class InducedCFG extends AbstractCFG {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
/**
|
||||
* A partial map from Instruction -> BasicBlock
|
||||
*/
|
||||
private final BasicBlock[] i2block;
|
||||
|
||||
private final Context context;
|
||||
|
||||
private final IInstruction[] instructions;
|
||||
|
||||
/**
|
||||
* TODO: we do not yet support induced CFGS with exception handlers.
|
||||
*
|
||||
* @param instructions
|
||||
*/
|
||||
public InducedCFG(SSAInstruction[] instructions, IMethod method, Context context) {
|
||||
super(method);
|
||||
this.context = context;
|
||||
this.instructions = instructions;
|
||||
if (DEBUG) {
|
||||
Trace.println("compute InducedCFG: " + method);
|
||||
}
|
||||
i2block = new BasicBlock[instructions.length];
|
||||
if (instructions.length == 0) {
|
||||
makeEmptyBlocks();
|
||||
} else {
|
||||
makeBasicBlocks();
|
||||
}
|
||||
init();
|
||||
computeEdges();
|
||||
|
||||
if (DEBUG) {
|
||||
try {
|
||||
GraphIntegrity.check(this);
|
||||
} catch (UnsoundGraphException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return context.hashCode() ^ getMethod().hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof InducedCFG) &&
|
||||
getMethod().equals(((InducedCFG)o).getMethod()) &&
|
||||
context.equals(((InducedCFG)o).context);
|
||||
}
|
||||
|
||||
public IInstruction[] getInstructions() {
|
||||
return instructions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute outgoing edges in the control flow graph.
|
||||
*/
|
||||
private void computeEdges() {
|
||||
for (Iterator it = iterateNodes(); it.hasNext();) {
|
||||
BasicBlock b = (BasicBlock) it.next();
|
||||
if (b.equals(exit()))
|
||||
continue;
|
||||
b.computeOutgoingEdges();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create basic blocks for an empty method
|
||||
*/
|
||||
private void makeEmptyBlocks() {
|
||||
BasicBlock b = new BasicBlock(-1);
|
||||
addNode(b);
|
||||
}
|
||||
|
||||
protected BranchVisitor makeBranchVisitor(boolean[] r) {
|
||||
return new BranchVisitor(r);
|
||||
}
|
||||
|
||||
protected PEIVisitor makePEIVisitor(boolean[] r) {
|
||||
return new PEIVisitor(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk through the instructions and compute basic block boundaries.
|
||||
*/
|
||||
private void makeBasicBlocks() {
|
||||
SSAInstruction[] instructions = (SSAInstruction[]) getInstructions();
|
||||
final boolean[] r = new boolean[instructions.length];
|
||||
|
||||
// Compute r so r[i] == true iff instruction i begins a basic block.
|
||||
// While doing so count the number of blocks.
|
||||
r[0] = true;
|
||||
BranchVisitor branchVisitor = makeBranchVisitor(r);
|
||||
PEIVisitor peiVisitor = makePEIVisitor(r);
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
if (instructions[i] != null) {
|
||||
branchVisitor.setIndex(i);
|
||||
instructions[i].visit(branchVisitor);
|
||||
// TODO: deal with exception handlers
|
||||
peiVisitor.setIndex(i);
|
||||
instructions[i].visit(peiVisitor);
|
||||
}
|
||||
}
|
||||
|
||||
BasicBlock b = null;
|
||||
for (int i = 0; i < r.length; i++) {
|
||||
if (r[i]) {
|
||||
b = new BasicBlock(i);
|
||||
addNode(b);
|
||||
|
||||
if (DEBUG) {
|
||||
Trace.println("Add basic block " + b);
|
||||
}
|
||||
}
|
||||
i2block[i] = b;
|
||||
}
|
||||
// allocate the exit block
|
||||
BasicBlock exit = new BasicBlock(-1);
|
||||
if (DEBUG) {
|
||||
Trace.println("Add exit block " + exit);
|
||||
}
|
||||
addNode(exit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* This visitor identifies basic block boundaries induced by branch
|
||||
* instructions.
|
||||
*/
|
||||
public class BranchVisitor extends SSAInstruction.Visitor {
|
||||
private boolean[] r;
|
||||
|
||||
protected BranchVisitor(boolean[] r) {
|
||||
this.r = r;
|
||||
}
|
||||
int index = 0;
|
||||
|
||||
void setIndex(int i) {
|
||||
index = i;
|
||||
}
|
||||
|
||||
public void visitGoto(SSAGotoInstruction instruction) {
|
||||
Assertions.UNREACHABLE("haven't implemented logic for goto yet.");
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitConditionalBranch(SSAConditionalBranchInstruction instruction) {
|
||||
Assertions.UNREACHABLE("haven't implemented logic for cbranch yet.");
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitSwitch(SSASwitchInstruction instruction) {
|
||||
Assertions.UNREACHABLE("haven't implemented logic for switch yet.");
|
||||
breakBasicBlock();
|
||||
int[] targets = instruction.getTargets();
|
||||
for (int i = 0; i < targets.length; i++) {
|
||||
r[targets[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void visitReturn(SSAReturnInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitThrow(SSAThrowInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
protected void breakBasicBlock() {
|
||||
if (index + 1 < getInstructions().length && !r[index + 1]) {
|
||||
r[index + 1] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: extend the following to deal with catch blocks. Right now
|
||||
// it simply breaks basic blocks at PEIs.
|
||||
public class PEIVisitor extends SSAInstruction.Visitor {
|
||||
private boolean[] r;
|
||||
|
||||
protected PEIVisitor(boolean[] r) {
|
||||
this.r = r;
|
||||
}
|
||||
int index = 0;
|
||||
|
||||
void setIndex(int i) {
|
||||
index = i;
|
||||
}
|
||||
|
||||
protected void breakBasicBlock() {
|
||||
if (index + 1 < getInstructions().length && !r[index + 1]) {
|
||||
r[index + 1] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void visitArrayLength(SSAArrayLengthInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitArrayLoad(SSAArrayLoadInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitArrayStore(SSAArrayStoreInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitCheckCast(SSACheckCastInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitGet(SSAGetInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitInvoke(SSAInvokeInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitMonitor(SSAMonitorInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitNew(SSANewInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitPut(SSAPutInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
|
||||
public void visitThrow(com.ibm.wala.ssa.SSAThrowInstruction instruction) {
|
||||
breakBasicBlock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getBlockForInstruction(int)
|
||||
*/
|
||||
public IBasicBlock getBlockForInstruction(int index) {
|
||||
if (i2block[index] == null) {
|
||||
Assertions.productionAssertion(false, "unexpected null for " + index);
|
||||
}
|
||||
return i2block[index];
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getExceptionHandlers()
|
||||
*/
|
||||
public Set getExceptionHandlers() {
|
||||
// TODO: support exception handlers
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
// TODO: share some common parts of this implementation with the ShrikeCFG
|
||||
// implementation! right now it's clone-and-owned :(
|
||||
private class BasicBlock extends NodeWithNumber implements IBasicBlock {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object arg0) {
|
||||
if (getClass().equals(arg0.getClass())) {
|
||||
BasicBlock other = (BasicBlock) arg0;
|
||||
return start == other.start && getMethod().equals(other.getMethod());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private final int start;
|
||||
|
||||
BasicBlock(int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add any exceptional edges generated by the last instruction in a basic
|
||||
* block.
|
||||
*
|
||||
* @param last
|
||||
* the last instruction in a basic block.
|
||||
*/
|
||||
private void addExceptionalEdges(SSAInstruction last) {
|
||||
if (last.isPEI()) {
|
||||
// we don't currently model catch blocks here ... instead just link
|
||||
// to the exit block
|
||||
addExceptionalEdgeTo((BasicBlock) exit());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param b
|
||||
*/
|
||||
private void addNormalEdgeTo(BasicBlock b) {
|
||||
addNormalEdge(this, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param b
|
||||
*/
|
||||
private void addExceptionalEdgeTo(BasicBlock b) {
|
||||
addExceptionalEdge(this, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method computeOutgoingEdges.
|
||||
*/
|
||||
private void computeOutgoingEdges() {
|
||||
|
||||
if (DEBUG) {
|
||||
Trace.println("Block " + this + ": computeOutgoingEdges()");
|
||||
}
|
||||
// TODO: we don't currently model branches
|
||||
|
||||
SSAInstruction last = (SSAInstruction) getInstructions()[getLastInstructionIndex()];
|
||||
addExceptionalEdges(last);
|
||||
// this CFG is odd in that we assume fallthru might always
|
||||
// happen .. this is because I'm too lazy to code control
|
||||
// flow in all method summaries yet.
|
||||
if (true) {
|
||||
// if (last.isFallThrough()) {
|
||||
if (DEBUG) {
|
||||
Trace.println("Add fallthru to " + getNode(getGraphNodeId() + 1));
|
||||
}
|
||||
addNormalEdgeTo((BasicBlock) getNode(getGraphNodeId() + 1));
|
||||
}
|
||||
if (last instanceof SSAReturnInstruction) {
|
||||
// link each return instrution to the exit block.
|
||||
BasicBlock exit = (BasicBlock) exit();
|
||||
addNormalEdgeTo(exit);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#getFirstInstructionIndex()
|
||||
*/
|
||||
public int getFirstInstructionIndex() {
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getLastInstructionIndex.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getLastInstructionIndex() {
|
||||
int exitNumber = InducedCFG.this.getNumber(exit());
|
||||
if (getGraphNodeId() == exitNumber) {
|
||||
// this is the exit block
|
||||
return -2;
|
||||
}
|
||||
if (getGraphNodeId() == (exitNumber - 1)) {
|
||||
// this is the last non-exit block
|
||||
return getInstructions().length - 1;
|
||||
} else {
|
||||
BasicBlock next = (BasicBlock) getNode(getGraphNodeId() + 1);
|
||||
return next.getFirstInstructionIndex() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#isCatchBlock()
|
||||
*/
|
||||
public boolean isCatchBlock() {
|
||||
// TODO: support induced CFG with catch blocks.
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 1153 * getGraphNodeId() + getMethod().hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "BB[Induced]" + getNumber() + " - " + getMethod().getSignature();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#isExitBlock()
|
||||
*/
|
||||
public boolean isExitBlock() {
|
||||
return getLastInstructionIndex() == -2;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#isEntryBlock()
|
||||
*/
|
||||
public boolean isEntryBlock() {
|
||||
return getNumber() == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#getMethod()
|
||||
*/
|
||||
public IMethod getMethod() {
|
||||
return InducedCFG.this.getMethod();
|
||||
}
|
||||
|
||||
public boolean endsInPEI() {
|
||||
return getInstructions()[getLastInstructionIndex()].isPEI();
|
||||
}
|
||||
|
||||
public boolean endsInReturn() {
|
||||
return getInstructions()[getLastInstructionIndex()] instanceof SSAReturnInstruction;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#getNumber()
|
||||
*/
|
||||
public int getNumber() {
|
||||
return InducedCFG.this.getNumber(this);
|
||||
}
|
||||
|
||||
public Iterator<IInstruction> iterateAllInstructions() {
|
||||
return new ArrayIterator<IInstruction>(getInstructions(),getFirstInstructionIndex(),getLastInstructionIndex());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer s = new StringBuffer("");
|
||||
for (Iterator it = iterateNodes(); it.hasNext();) {
|
||||
BasicBlock bb = (BasicBlock) it.next();
|
||||
s.append("BB").append(getNumber(bb)).append("\n");
|
||||
for (int j = bb.getFirstInstructionIndex(); j <= bb.getLastInstructionIndex(); j++) {
|
||||
s.append(" ").append(j).append(" ").append(getInstructions()[j]).append("\n");
|
||||
}
|
||||
|
||||
Iterator<IBasicBlock> succNodes = getSuccNodes(bb);
|
||||
while (succNodes.hasNext()) {
|
||||
s.append(" -> BB").append(getNumber(succNodes.next())).append("\n");
|
||||
}
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Since this CFG is synthetic, for now we assume the instruction index is the
|
||||
* same as the program counter
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getProgramCounter(int)
|
||||
*/
|
||||
public int getProgramCounter(int index) {
|
||||
if (getInstructions()[index] instanceof SSAInvokeInstruction) {
|
||||
return ((SSAInvokeInstruction) getInstructions()[index]).getCallSite().getProgramCounter();
|
||||
} else {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,581 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.cfg;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.classLoader.ShrikeCTMethodWrapper;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.shrikeBT.ExceptionHandler;
|
||||
import com.ibm.wala.shrikeBT.IInstruction;
|
||||
import com.ibm.wala.shrikeBT.Instruction;
|
||||
import com.ibm.wala.shrikeBT.ReturnInstruction;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.Exceptions;
|
||||
import com.ibm.wala.util.ShrikeUtil;
|
||||
import com.ibm.wala.util.collections.ArrayIterator;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.util.graph.impl.NodeWithNumber;
|
||||
import com.ibm.wala.util.warnings.Warning;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* A graph of basic blocks.
|
||||
*
|
||||
* @author sfink
|
||||
* @author roca
|
||||
*/
|
||||
public class ShrikeCFG extends AbstractCFG {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private int[] instruction2Block;
|
||||
|
||||
private final WarningSet warnings;
|
||||
|
||||
private final ClassHierarchy cha;
|
||||
|
||||
private final ShrikeCTMethodWrapper method;
|
||||
|
||||
/**
|
||||
* Cache this here for efficiency
|
||||
*/
|
||||
private final int hashBase;
|
||||
|
||||
/**
|
||||
* Set of Shrike ExceptionHandler objects that cover this method.
|
||||
*/
|
||||
private Set<ExceptionHandler> exceptionHandlers = HashSetFactory.make(10);
|
||||
|
||||
/**
|
||||
* Constructor for ControlFlowGraph.
|
||||
*/
|
||||
public ShrikeCFG(ShrikeCTMethodWrapper method, WarningSet warnings, ClassHierarchy cha) {
|
||||
super(method);
|
||||
this.method = method;
|
||||
this.hashBase = method.hashCode() * 9967;
|
||||
this.warnings = warnings;
|
||||
this.cha = cha;
|
||||
makeBasicBlocks();
|
||||
init();
|
||||
computeI2BMapping();
|
||||
computeEdges();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 9511 * getMethod().hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof ShrikeCFG) && getMethod().equals(((ShrikeCFG) o).getMethod());
|
||||
}
|
||||
|
||||
public IInstruction[] getInstructions() {
|
||||
try {
|
||||
return method.getInstructions();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a mapping from instruction to basic block. Also, compute the blocks
|
||||
* that end with a 'normal' return.
|
||||
*/
|
||||
private void computeI2BMapping() {
|
||||
instruction2Block = new int[getInstructions().length];
|
||||
for (Iterator it = iterateNodes(); it.hasNext();) {
|
||||
final BasicBlock b = (BasicBlock) it.next();
|
||||
for (int j = b.getFirstInstructionIndex(); j <= b.getLastInstructionIndex(); j++) {
|
||||
instruction2Block[j] = getNumber(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute outgoing edges in the control flow graph.
|
||||
*/
|
||||
private void computeEdges() {
|
||||
for (Iterator it = iterateNodes(); it.hasNext();) {
|
||||
BasicBlock b = (BasicBlock) it.next();
|
||||
if (b.equals(exit())) {
|
||||
continue;
|
||||
} else if (b.equals(entry())) {
|
||||
addNormalEdge(b, getBlockForInstruction(0));
|
||||
} else {
|
||||
b.computeOutgoingEdges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getBasicBlockStarts, stolen from ShrikeBT verifier
|
||||
*/
|
||||
private void makeBasicBlocks() {
|
||||
ExceptionHandler[][] handlers;
|
||||
try {
|
||||
handlers = method.getHandlers();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
handlers = null;
|
||||
}
|
||||
boolean[] r = new boolean[getInstructions().length];
|
||||
boolean[] catchers = new boolean[getInstructions().length];
|
||||
// we initially start with both the entry and exit block.
|
||||
int blockCount = 2;
|
||||
|
||||
// Compute r so r[i] == true iff instruction i begins a basic block.
|
||||
// While doing so count the number of blocks.
|
||||
r[0] = true;
|
||||
Instruction[] instructions = (Instruction[]) getInstructions();
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
int[] targets = instructions[i].getBranchTargets();
|
||||
|
||||
// if there are any targets, then break the basic block here.
|
||||
// also break the basic block after a return
|
||||
if (targets.length > 0 || !instructions[i].isFallThrough()) {
|
||||
if (i + 1 < instructions.length && !r[i + 1]) {
|
||||
r[i + 1] = true;
|
||||
blockCount++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < targets.length; j++) {
|
||||
if (!r[targets[j]]) {
|
||||
r[targets[j]] = true;
|
||||
blockCount++;
|
||||
}
|
||||
}
|
||||
if (Exceptions.isPEI(instructions[i])) {
|
||||
ExceptionHandler[] hs = handlers[i];
|
||||
// break the basic block here.
|
||||
if (i + 1 < instructions.length && !r[i + 1]) {
|
||||
r[i + 1] = true;
|
||||
blockCount++;
|
||||
}
|
||||
if (hs != null && hs.length > 0) {
|
||||
for (int j = 0; j < hs.length; j++) {
|
||||
exceptionHandlers.add(hs[j]);
|
||||
if (!r[hs[j].getHandler()]) {
|
||||
// we have not discovered the catch block yet.
|
||||
// form a new basic block
|
||||
r[hs[j].getHandler()] = true;
|
||||
blockCount++;
|
||||
}
|
||||
catchers[hs[j].getHandler()] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BasicBlock entry = new BasicBlock(-1);
|
||||
addNode(entry);
|
||||
|
||||
int j = 1;
|
||||
for (int i = 0; i < r.length; i++) {
|
||||
if (r[i]) {
|
||||
BasicBlock b = new BasicBlock(i);
|
||||
addNode(b);
|
||||
if (catchers[i]) {
|
||||
setCatchBlock(j);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
BasicBlock exit = new BasicBlock(-1);
|
||||
addNode(exit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instruction's basic block in the CFG given the index of the
|
||||
* instruction in the CFG's instruction array.
|
||||
*/
|
||||
public IBasicBlock getBlockForInstruction(int index) {
|
||||
return (IBasicBlock) getNode(instruction2Block[index]);
|
||||
}
|
||||
|
||||
public final class BasicBlock extends NodeWithNumber implements IBasicBlock {
|
||||
|
||||
/**
|
||||
* The number of the ShrikeBT instruction that begins this block.
|
||||
*/
|
||||
private int startIndex;
|
||||
|
||||
public BasicBlock(int startIndex) {
|
||||
this.startIndex = startIndex;
|
||||
}
|
||||
|
||||
public boolean isCatchBlock() {
|
||||
return ShrikeCFG.this.isCatchBlock(getNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method computeOutgoingEdges.
|
||||
*/
|
||||
private void computeOutgoingEdges() {
|
||||
if (DEBUG) {
|
||||
Trace.println("Block " + this + ": computeOutgoingEdges()");
|
||||
}
|
||||
|
||||
Instruction last = (Instruction) getInstructions()[getLastInstructionIndex()];
|
||||
int[] targets = last.getBranchTargets();
|
||||
for (int i = 0; i < targets.length; i++) {
|
||||
BasicBlock b = (BasicBlock) getBlockForInstruction(targets[i]);
|
||||
addNormalEdgeTo(b);
|
||||
}
|
||||
addExceptionalEdges(last);
|
||||
if (last.isFallThrough()) {
|
||||
BasicBlock next = (BasicBlock) getNode(getNumber() + 1);
|
||||
addNormalEdgeTo(next);
|
||||
}
|
||||
if (last instanceof ReturnInstruction) {
|
||||
// link each return instrution to the exit block.
|
||||
BasicBlock exit = (BasicBlock) exit();
|
||||
addNormalEdgeTo(exit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add any exceptional edges generated by the last instruction in a basic
|
||||
* block.
|
||||
*
|
||||
* @param last
|
||||
* the last instruction in a basic block.
|
||||
*/
|
||||
private void addExceptionalEdges(Instruction last) {
|
||||
if (Exceptions.isPEI(last)) {
|
||||
Collection<TypeReference> exceptionTypes = null;
|
||||
boolean goToAllHandlers = false;
|
||||
|
||||
ExceptionHandler[] hs = getExceptionHandlers();
|
||||
if (last.getOpcode() == OP_athrow) {
|
||||
// this class does not have the type information needed
|
||||
// to determine what the athrow throws. So, add an
|
||||
// edge to all reachable handlers. Better information can
|
||||
// be obtained later with SSA type propagation.
|
||||
// TODO: consider pruning to only the exception types that
|
||||
// this method either catches or allocates, since these are
|
||||
// the only types that can flow to an athrow.
|
||||
goToAllHandlers = true;
|
||||
} else {
|
||||
if (hs != null && hs.length > 0) {
|
||||
exceptionTypes = Exceptions.getExceptionTypes(getMethod().getDeclaringClass().getReference().getClassLoader(), last,
|
||||
cha, warnings);
|
||||
}
|
||||
}
|
||||
|
||||
if (hs != null && hs.length > 0) {
|
||||
// found a handler for this PEI
|
||||
|
||||
// create a mutable copy
|
||||
if (!goToAllHandlers) {
|
||||
exceptionTypes = new HashSet<TypeReference>(exceptionTypes);
|
||||
}
|
||||
|
||||
for (int j = 0; j < hs.length; j++) {
|
||||
if (DEBUG) {
|
||||
Trace.println(" handler " + hs[j]);
|
||||
}
|
||||
BasicBlock b = (BasicBlock) getBlockForInstruction(hs[j].getHandler());
|
||||
if (DEBUG) {
|
||||
Trace.println(" target " + b);
|
||||
}
|
||||
if (goToAllHandlers) {
|
||||
// add an edge to the catch block.
|
||||
addExceptionalEdgeTo(b);
|
||||
} else {
|
||||
TypeReference caughtException = null;
|
||||
|
||||
if (hs[j].getCatchClass() != null) {
|
||||
ClassLoaderReference loader = ShrikeCFG.this.getMethod().getDeclaringClass().getReference().getClassLoader();
|
||||
caughtException = ShrikeUtil.makeTypeReference(loader, hs[j].getCatchClass());
|
||||
IClass caughtClass = cha.lookupClass(caughtException);
|
||||
if (caughtClass == null) {
|
||||
// conservatively add the edge, and raise a warning
|
||||
addExceptionalEdgeTo(b);
|
||||
warnings.add(FailedExceptionResolutionWarning.create(caughtException));
|
||||
// null out caughtException, to avoid attempting to process it
|
||||
caughtException = null;
|
||||
}
|
||||
}
|
||||
if (caughtException == null) {
|
||||
// this means that the handler catches all exceptions.
|
||||
// add the edge and null out all types
|
||||
addExceptionalEdgeTo(b);
|
||||
exceptionTypes.clear();
|
||||
} else {
|
||||
// the set "caught" should be the set of exceptions that MUST have been caught
|
||||
// by the handlers in scope
|
||||
HashSet<TypeReference> caught = HashSetFactory.make(exceptionTypes.size());
|
||||
// check if we should add an edge to the catch block.
|
||||
for (Iterator it = exceptionTypes.iterator(); it.hasNext();) {
|
||||
TypeReference t = (TypeReference) it.next();
|
||||
if (t != null) {
|
||||
IClass klass = cha.lookupClass(t);
|
||||
if (klass == null) {
|
||||
warnings.add(FailedExceptionResolutionWarning.create(caughtException));
|
||||
// conservatively add an edge
|
||||
addExceptionalEdgeTo(b);
|
||||
} else {
|
||||
IClass caughtClass = cha.lookupClass(caughtException);
|
||||
if (cha.isSubclassOf(klass, caughtClass) || cha.isSubclassOf(caughtClass, klass)) {
|
||||
// add the edge and null out the type from the array
|
||||
addExceptionalEdgeTo(b);
|
||||
if (cha.isSubclassOf( klass, caughtClass )) {
|
||||
caught.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exceptionTypes.removeAll(caught);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if needed, add an edge to the exit block.
|
||||
if (exceptionTypes == null || !exceptionTypes.isEmpty()) {
|
||||
BasicBlock exit = (BasicBlock) exit();
|
||||
addExceptionalEdgeTo(exit);
|
||||
}
|
||||
} else {
|
||||
// found no handler for this PEI ... link to the exit block.
|
||||
BasicBlock exit = (BasicBlock) exit();
|
||||
addExceptionalEdgeTo(exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ExceptionHandler[] getExceptionHandlers() {
|
||||
ExceptionHandler[][] handlers;
|
||||
try {
|
||||
handlers = method.getHandlers();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
handlers = null;
|
||||
}
|
||||
ExceptionHandler[] hs = handlers[getLastInstructionIndex()];
|
||||
return hs;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return true iff exception extends RuntimeException or Error
|
||||
// */
|
||||
// private boolean isUndeclaredType(IClass exception) {
|
||||
// IClass re = cha.lookupClass(TypeReference.JavaLangRuntimeException);
|
||||
// IClass error = cha.lookupClass(TypeReference.JavaLangError);
|
||||
// boolean result = cha.isSubclassOf(exception, re) ||
|
||||
// cha.isSubclassOf(exception, error);
|
||||
// return result;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param b
|
||||
*/
|
||||
private void addNormalEdgeTo(BasicBlock b) {
|
||||
addNormalEdge(this, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param b
|
||||
*/
|
||||
private void addExceptionalEdgeTo(BasicBlock b) {
|
||||
addExceptionalEdge(this, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getLastInstructionIndex.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getLastInstructionIndex() {
|
||||
|
||||
if (this == entry() || this == exit()) {
|
||||
// these are the special end blocks
|
||||
return -2;
|
||||
}
|
||||
if (getNumber() == (getMaxNumber() - 1)) {
|
||||
// this is the last non-exit block
|
||||
return getInstructions().length - 1;
|
||||
} else {
|
||||
BasicBlock next = (BasicBlock) getNode(getNumber() + 1);
|
||||
return next.getFirstInstructionIndex() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getFirstInstructionIndex.
|
||||
*/
|
||||
public int getFirstInstructionIndex() {
|
||||
return startIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "BB[Shrike]" + getNumber() + " - " + method.getDeclaringClass().getReference().getName() + "." + method.getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#isExitBlock()
|
||||
*/
|
||||
public boolean isExitBlock() {
|
||||
return this == ShrikeCFG.this.exit();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#isEntryBlock()
|
||||
*/
|
||||
public boolean isEntryBlock() {
|
||||
return this == ShrikeCFG.this.entry();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#getMethod()
|
||||
*/
|
||||
public IMethod getMethod() {
|
||||
return ShrikeCFG.this.getMethod();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return hashBase + getNumber();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof BasicBlock) && ((BasicBlock) o).getMethod().equals(getMethod())
|
||||
&& ((BasicBlock) o).getNumber() == getNumber();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#getNumber()
|
||||
*/
|
||||
public int getNumber() {
|
||||
return getGraphNodeId();
|
||||
}
|
||||
|
||||
public Iterator<IInstruction> iterateAllInstructions() {
|
||||
return new ArrayIterator<IInstruction>(getInstructions(),getFirstInstructionIndex(),getLastInstructionIndex());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer s = new StringBuffer("");
|
||||
for (Iterator it = iterateNodes(); it.hasNext();) {
|
||||
BasicBlock bb = (BasicBlock) it.next();
|
||||
s.append("BB").append(getNumber(bb)).append("\n");
|
||||
for (int j = bb.getFirstInstructionIndex(); j <= bb.getLastInstructionIndex(); j++) {
|
||||
s.append(" ").append(j).append(" ").append(getInstructions()[j]).append("\n");
|
||||
}
|
||||
|
||||
Iterator<IBasicBlock> succNodes = getSuccNodes(bb);
|
||||
while (succNodes.hasNext()) {
|
||||
s.append(" -> BB").append(getNumber(succNodes.next())).append("\n");
|
||||
}
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getMaxStackHeight.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getMaxStackHeight() {
|
||||
return method.getMaxStackHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getMaxLocals
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getMaxLocals() {
|
||||
return method.getMaxLocals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exceptionHandlers.
|
||||
*
|
||||
* @return Set
|
||||
*/
|
||||
public Set<ExceptionHandler> getExceptionHandlers() {
|
||||
return exceptionHandlers;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getProgramCounter(int)
|
||||
*/
|
||||
public int getProgramCounter(int index) {
|
||||
try {
|
||||
return method.getBytecodeIndex(index);
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* A waring when we fail to resolve the type of an exception
|
||||
*/
|
||||
private static class FailedExceptionResolutionWarning extends Warning {
|
||||
|
||||
final TypeReference T;
|
||||
|
||||
FailedExceptionResolutionWarning(TypeReference T) {
|
||||
super(Warning.MODERATE);
|
||||
this.T = T;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return getClass().toString() + " : " + T;
|
||||
}
|
||||
|
||||
public static FailedExceptionResolutionWarning create(TypeReference T) {
|
||||
return new FailedExceptionResolutionWarning(T);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,696 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.cfg;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.shrikeBT.IInstruction;
|
||||
import com.ibm.wala.ssa.ISSABasicBlock;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAThrowInstruction;
|
||||
import com.ibm.wala.util.IteratorPlusOne;
|
||||
import com.ibm.wala.util.collections.EmptyIterator;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.util.graph.impl.NumberedNodeIterator;
|
||||
import com.ibm.wala.util.intset.BitVector;
|
||||
import com.ibm.wala.util.intset.FixedSizeBitVector;
|
||||
import com.ibm.wala.util.intset.IntSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* This provides a view of a control flow graph with two exits, one for normal
|
||||
* returns and one for exceptional exits.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class TwoExitCFG implements ControlFlowGraph {
|
||||
|
||||
/**
|
||||
* DEBUG_LEVEL: 0 No output 1 Print some simple stats and warning information
|
||||
* 2 Detailed debugging
|
||||
*/
|
||||
static final int DEBUG_LEVEL = 0;
|
||||
|
||||
/**
|
||||
* A "normal" cfg with one exit node
|
||||
*/
|
||||
private final ControlFlowGraph delegate;
|
||||
|
||||
/**
|
||||
* A distinguished basic block representing the exceptional exit.
|
||||
*/
|
||||
private final IBasicBlock exceptionalExit = new ExceptionalExitBlock();
|
||||
|
||||
/**
|
||||
* Numbers of the "normal" predecessors of the delegate's exit() node
|
||||
*/
|
||||
private FixedSizeBitVector normalPred;
|
||||
|
||||
/**
|
||||
* Numbers of the "exceptional" predecessors of the delegate's exit() node
|
||||
*/
|
||||
private FixedSizeBitVector exceptionalPred;
|
||||
|
||||
/**
|
||||
* Cached here for efficiency: the "number" of the delegate's exit() node
|
||||
*/
|
||||
private final int delegateExitNumber;
|
||||
|
||||
/**
|
||||
* compute edges lazily
|
||||
*/
|
||||
private boolean edgesAreComputed = false;
|
||||
|
||||
/**
|
||||
* @param delegate
|
||||
* A "normal" cfg with one exit node
|
||||
*/
|
||||
public TwoExitCFG(ControlFlowGraph delegate) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(!(delegate instanceof TwoExitCFG), "bad recursion");
|
||||
}
|
||||
this.delegate = delegate;
|
||||
this.delegateExitNumber = delegate.getNumber(delegate.exit());
|
||||
}
|
||||
|
||||
private void ensureEdgesReady() {
|
||||
if (!edgesAreComputed) {
|
||||
computeEdges(delegate);
|
||||
edgesAreComputed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param delegate
|
||||
*/
|
||||
private void computeEdges(ControlFlowGraph delegate) {
|
||||
normalPred = (delegate instanceof AbstractCFG) ? ((AbstractCFG) delegate).getNormalToExit() : new FixedSizeBitVector(delegate
|
||||
.getMaxNumber() + 1);
|
||||
exceptionalPred = (delegate instanceof AbstractCFG) ? ((AbstractCFG) delegate).getExceptionalToExit() : new FixedSizeBitVector(
|
||||
delegate.getMaxNumber() + 1);
|
||||
if (!(delegate instanceof AbstractCFG)) {
|
||||
IInstruction[] instructions = delegate.getInstructions();
|
||||
for (Iterator it = delegate.getPredNodes(delegate.exit()); it.hasNext();) {
|
||||
IBasicBlock b = (IBasicBlock) it.next();
|
||||
if (b.getLastInstructionIndex() >= 0) {
|
||||
IInstruction last = instructions[b.getLastInstructionIndex()];
|
||||
if (last != null && last.isPEI()) {
|
||||
exceptionalPred.set(b.getNumber());
|
||||
// occasionally for weird CFGs we may actually fall
|
||||
// thru to the exit. TODO: perhaps enforce an invariant
|
||||
// that all "normal" predecessors of exit end in return.
|
||||
if (!(last instanceof SSAThrowInstruction)) {
|
||||
if (b.getLastInstructionIndex() == instructions.length - 1) {
|
||||
normalPred.set(b.getNumber());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
normalPred.set(b.getNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#entry()
|
||||
*/
|
||||
public IBasicBlock entry() {
|
||||
return delegate.entry();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#exit()
|
||||
*/
|
||||
public IBasicBlock exit() {
|
||||
Assertions.UNREACHABLE("Don't call me");
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getCatchBlocks()
|
||||
*/
|
||||
public BitVector getCatchBlocks() {
|
||||
return delegate.getCatchBlocks();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getBlockForInstruction(int)
|
||||
*/
|
||||
public IBasicBlock getBlockForInstruction(int index) {
|
||||
return delegate.getBlockForInstruction(index);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getInstructions()
|
||||
*/
|
||||
public IInstruction[] getInstructions() {
|
||||
return delegate.getInstructions();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getProgramCounter(int)
|
||||
*/
|
||||
public int getProgramCounter(int index) {
|
||||
return delegate.getProgramCounter(index);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.Graph#removeNodeAndEdges(java.lang.Object)
|
||||
*/
|
||||
public void removeNodeAndEdges(IBasicBlock N) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NumberedNodeManager#getNumber(java.lang.Object)
|
||||
*/
|
||||
public int getNumber(IBasicBlock N) {
|
||||
if (N.equals(exceptionalExit)) {
|
||||
return getMaxNumber();
|
||||
} else {
|
||||
return delegate.getNumber(N);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NumberedNodeManager#getNode(int)
|
||||
*/
|
||||
public IBasicBlock getNode(int number) {
|
||||
return (number == getMaxNumber()) ? exceptionalExit : delegate.getNode(number);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NumberedNodeManager#getMaxNumber()
|
||||
*/
|
||||
public int getMaxNumber() {
|
||||
return delegate.getMaxNumber() + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#iterateNodes()
|
||||
*/
|
||||
public Iterator<IBasicBlock> iterateNodes() {
|
||||
return new IteratorPlusOne<IBasicBlock>(delegate.iterateNodes(), exceptionalExit);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#getNumberOfNodes()
|
||||
*/
|
||||
public int getNumberOfNodes() {
|
||||
return delegate.getNumberOfNodes() + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#addNode(java.lang.Object)
|
||||
*/
|
||||
public void addNode(IBasicBlock n) {
|
||||
Assertions.UNREACHABLE();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#removeNode(java.lang.Object)
|
||||
*/
|
||||
public void removeNode(IBasicBlock n) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NodeManager#containsNode(java.lang.Object)
|
||||
*/
|
||||
public boolean containsNode(IBasicBlock N) {
|
||||
return delegate.containsNode(N) || N.equals(exceptionalExit);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodes(java.lang.Object)
|
||||
*/
|
||||
public Iterator<? extends IBasicBlock> getPredNodes(IBasicBlock N) {
|
||||
if (N.equals(exceptionalExit)) {
|
||||
return delegate.getExceptionalPredecessors(delegate.exit()).iterator();
|
||||
} else if (N.equals(delegate.exit())) {
|
||||
return delegate.getNormalPredecessors(delegate.exit()).iterator();
|
||||
} else {
|
||||
return delegate.getPredNodes(N);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodeCount(java.lang.Object)
|
||||
*/
|
||||
public int getPredNodeCount(IBasicBlock N) {
|
||||
ensureEdgesReady();
|
||||
if (N.equals(delegate.exit())) {
|
||||
return normalPred.populationCount();
|
||||
} else if (N.equals(exceptionalExit)) {
|
||||
return exceptionalPred.populationCount();
|
||||
} else {
|
||||
return delegate.getPredNodeCount(N);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodes(java.lang.Object)
|
||||
*/
|
||||
public Iterator<? extends IBasicBlock> getSuccNodes(IBasicBlock N) {
|
||||
if (DEBUG_LEVEL > 1) {
|
||||
Trace.println("TwoExitCFG: getSuccNodes " + N);
|
||||
}
|
||||
ensureEdgesReady();
|
||||
IBasicBlock bb = (IBasicBlock) N;
|
||||
if (N.equals(exceptionalExit)) {
|
||||
return EmptyIterator.instance();
|
||||
} else if (exceptionalPred.get(bb.getNumber())) {
|
||||
if (normalPred.get(bb.getNumber())) {
|
||||
return new IteratorPlusOne<IBasicBlock>(delegate.getSuccNodes(N), exceptionalExit);
|
||||
} else {
|
||||
return new SubstitutionIterator(delegate.getSuccNodes(N));
|
||||
}
|
||||
} else {
|
||||
return delegate.getSuccNodes(N);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodeCount(java.lang.Object)
|
||||
*/
|
||||
public int getSuccNodeCount(IBasicBlock N) {
|
||||
if (N.equals(exceptionalExit)) {
|
||||
return 0;
|
||||
} else {
|
||||
ensureEdgesReady();
|
||||
int result = delegate.getSuccNodeCount(N);
|
||||
IBasicBlock bb = (IBasicBlock) N;
|
||||
if (exceptionalPred.get(bb.getNumber()) && normalPred.get(bb.getNumber())) {
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.EdgeManager#addEdge(java.lang.Object,
|
||||
* java.lang.Object)
|
||||
*/
|
||||
public void addEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public void removeEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public boolean hasEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
Assertions.UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.EdgeManager#removeEdges(java.lang.Object)
|
||||
*/
|
||||
public void removeAllIncidentEdges(IBasicBlock node) {
|
||||
Assertions.UNREACHABLE();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* An additional basic block to model exceptional exits
|
||||
*/
|
||||
public final class ExceptionalExitBlock implements ISSABasicBlock {
|
||||
|
||||
public ControlFlowGraph getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#getFirstInstructionIndex()
|
||||
*/
|
||||
public int getFirstInstructionIndex() {
|
||||
Assertions.UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#getLastInstructionIndex()
|
||||
*/
|
||||
public int getLastInstructionIndex() {
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#isCatchBlock()
|
||||
*/
|
||||
public boolean isCatchBlock() {
|
||||
Assertions.UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#isExitBlock()
|
||||
*/
|
||||
public boolean isExitBlock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#isEntryBlock()
|
||||
*/
|
||||
public boolean isEntryBlock() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#getMethod()
|
||||
*/
|
||||
public IMethod getMethod() {
|
||||
return delegate.getMethod();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.INodeWithNumber#getGraphNodeId()
|
||||
*/
|
||||
public int getGraphNodeId() {
|
||||
Assertions.UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.INodeWithNumber#setGraphNodeId(int)
|
||||
*/
|
||||
public void setGraphNodeId(int number) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object arg0) {
|
||||
if (arg0 instanceof ExceptionalExitBlock) {
|
||||
ExceptionalExitBlock other = (ExceptionalExitBlock) arg0;
|
||||
return delegate.exit().equals(other.getDelegate().exit());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return delegate.exit().hashCode() * 8467;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "Exceptional Exit[ " + getMethod() + "]";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.IBasicBlock#getNumber()
|
||||
*/
|
||||
public int getNumber() {
|
||||
return getMaxNumber();
|
||||
}
|
||||
|
||||
public Iterator iteratePhis() {
|
||||
return Collections.EMPTY_LIST.iterator();
|
||||
}
|
||||
|
||||
public Iterator iteratePis() {
|
||||
return Collections.EMPTY_LIST.iterator();
|
||||
}
|
||||
|
||||
public Iterator<IInstruction> iterateAllInstructions() {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
|
||||
public SSAInstruction getLastInstruction() {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getMethod()
|
||||
*/
|
||||
public IMethod getMethod() {
|
||||
return delegate.getMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
* An iterator that substitutes exceptionalExit for exit()
|
||||
*/
|
||||
private class SubstitutionIterator implements Iterator<IBasicBlock> {
|
||||
private final Iterator it;
|
||||
|
||||
SubstitutionIterator(Iterator it) {
|
||||
this.it = it;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#remove()
|
||||
*/
|
||||
public void remove() {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#hasNext()
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.util.Iterator#next()
|
||||
*/
|
||||
public IBasicBlock next() {
|
||||
IBasicBlock n = (IBasicBlock) it.next();
|
||||
if (n.getNumber() == delegateExitNumber) {
|
||||
return exceptionalExit;
|
||||
} else {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getExceptionalSuccessors(com.ibm.wala.cfg.IBasicBlock)
|
||||
*/
|
||||
public Collection<IBasicBlock> getExceptionalSuccessors(IBasicBlock b) {
|
||||
if (b.equals(exceptionalExit)) {
|
||||
return Collections.emptySet();
|
||||
} else {
|
||||
HashSet<IBasicBlock> c = HashSetFactory.make(getSuccNodeCount(b));
|
||||
for (Iterator<IBasicBlock> it = delegate.getExceptionalSuccessors(b).iterator(); it.hasNext(); ) {
|
||||
IBasicBlock o = it.next();
|
||||
if (o.equals(delegate.exit())) {
|
||||
c.add(exceptionalExit);
|
||||
} else {
|
||||
c.add(o);
|
||||
}
|
||||
}
|
||||
if (DEBUG_LEVEL > 1) {
|
||||
Trace.println("Used delegate " + delegate.getClass());
|
||||
Trace.println("Exceptional succ of " + b + " " + c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#getNormalSuccessors(com.ibm.wala.cfg.IBasicBlock)
|
||||
*/
|
||||
public Collection<IBasicBlock> getNormalSuccessors(IBasicBlock b) {
|
||||
if (b.equals(exceptionalExit)) {
|
||||
return Collections.emptySet();
|
||||
} else {
|
||||
return delegate.getNormalSuccessors(b);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A distinguished basic block representing the normal exit
|
||||
*/
|
||||
public IBasicBlock getNormalExit() {
|
||||
return delegate.exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A distinguished basic block representing the exceptional exit
|
||||
*/
|
||||
public IBasicBlock getExceptionalExit() {
|
||||
return exceptionalExit;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer result = new StringBuffer("Two-Exit CFG");
|
||||
result.append("\ndelegate\n" + delegate);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.util.graph.NumberedNodeManager#iterateNodes(com.ibm.wala.util.intset.IntSet)
|
||||
*/
|
||||
public Iterator<IBasicBlock> iterateNodes(IntSet s) {
|
||||
return new NumberedNodeIterator<IBasicBlock>(s, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public void removeIncomingEdges(IBasicBlock node) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*/
|
||||
public void removeOutgoingEdges(IBasicBlock node) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
|
||||
}
|
||||
|
||||
public Collection<IBasicBlock> getExceptionalPredecessors(IBasicBlock b) {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Collection<IBasicBlock> getNormalPredecessors(IBasicBlock b) {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
public IntSet getSuccNodeNumbers(IBasicBlock node) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
public IntSet getPredNodeNumbers(IBasicBlock node) {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the delegate.
|
||||
*/
|
||||
public ControlFlowGraph getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.cfg;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.shrikeBT.ConditionalBranchInstruction;
|
||||
import com.ibm.wala.ssa.SSAConditionalBranchInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSASwitchInstruction;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
public class Util {
|
||||
|
||||
public static SSAInstruction getLastInstruction(ControlFlowGraph G, IBasicBlock b) {
|
||||
return (SSAInstruction) G.getInstructions()[b.getLastInstructionIndex()];
|
||||
}
|
||||
|
||||
public static boolean endsWithConditionalBranch(ControlFlowGraph G, IBasicBlock b) {
|
||||
return getLastInstruction(G, b) instanceof SSAConditionalBranchInstruction;
|
||||
}
|
||||
|
||||
public static SSAConditionalBranchInstruction getConditionalBranch(ControlFlowGraph G, IBasicBlock b) {
|
||||
return (SSAConditionalBranchInstruction) getLastInstruction(G, b);
|
||||
}
|
||||
|
||||
public static boolean endsWithSwitch(ControlFlowGraph G, IBasicBlock b) {
|
||||
return getLastInstruction(G, b) instanceof SSASwitchInstruction;
|
||||
}
|
||||
|
||||
public static SSASwitchInstruction getSwitch(ControlFlowGraph G, IBasicBlock b) {
|
||||
return (SSASwitchInstruction) getLastInstruction(G, b);
|
||||
}
|
||||
|
||||
public static IBasicBlock getFallThruBlock(ControlFlowGraph G, IBasicBlock b) {
|
||||
return G.getBlockForInstruction(b.getLastInstructionIndex() + 1);
|
||||
}
|
||||
|
||||
public static IBasicBlock getFalseSuccessor(ControlFlowGraph G, IBasicBlock b) {
|
||||
return getFallThruBlock(G, b);
|
||||
}
|
||||
|
||||
public static IBasicBlock getTrueSuccessor(ControlFlowGraph G, IBasicBlock b) {
|
||||
IBasicBlock fs = getFalseSuccessor(G, b);
|
||||
for (Iterator ss = G.getSuccNodes(b); ss.hasNext();) {
|
||||
IBasicBlock s = (IBasicBlock) ss.next();
|
||||
if (s != fs)
|
||||
return s;
|
||||
}
|
||||
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IBasicBlock resolveSwitch(ControlFlowGraph G, IBasicBlock b, int c) {
|
||||
SSASwitchInstruction s = getSwitch(G, b);
|
||||
int[] casesAndLabels = s.getCasesAndLabels();
|
||||
for (int i = 0; i < casesAndLabels.length; i += 2)
|
||||
if (casesAndLabels[i] == c)
|
||||
return G.getBlockForInstruction(casesAndLabels[i + 1]);
|
||||
|
||||
return G.getBlockForInstruction(s.getDefault());
|
||||
}
|
||||
|
||||
public static IBasicBlock resolveBranch(ControlFlowGraph G, IBasicBlock bb, int c1, int c2) {
|
||||
SSAConditionalBranchInstruction c = getConditionalBranch(G, bb);
|
||||
switch ((ConditionalBranchInstruction.Operator)c.getOperator()) {
|
||||
case EQ:
|
||||
if (c1 == c2)
|
||||
return getTrueSuccessor(G, bb);
|
||||
else
|
||||
return getFalseSuccessor(G, bb);
|
||||
case NE:
|
||||
if (c1 != c2)
|
||||
return getTrueSuccessor(G, bb);
|
||||
else
|
||||
return getFalseSuccessor(G, bb);
|
||||
case LT:
|
||||
if (c1 < c2)
|
||||
return getTrueSuccessor(G, bb);
|
||||
else
|
||||
return getFalseSuccessor(G, bb);
|
||||
case GE:
|
||||
if (c1 >= c2)
|
||||
return getTrueSuccessor(G, bb);
|
||||
else
|
||||
return getFalseSuccessor(G, bb);
|
||||
case GT:
|
||||
if (c1 > c2)
|
||||
return getTrueSuccessor(G, bb);
|
||||
else
|
||||
return getFalseSuccessor(G, bb);
|
||||
case LE:
|
||||
if (c1 <= c2)
|
||||
return getTrueSuccessor(G, bb);
|
||||
else
|
||||
return getFalseSuccessor(G, bb);
|
||||
}
|
||||
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.cfg.ControlFlowGraph#whichPred(com.ibm.wala.cfg.IBasicBlock,
|
||||
* com.ibm.wala.cfg.IBasicBlock)
|
||||
*/
|
||||
public static int whichPred(ControlFlowGraph cfg, IBasicBlock a, IBasicBlock b) {
|
||||
int i = 0;
|
||||
for (Iterator it = cfg.getPredNodes(b); it.hasNext();) {
|
||||
if (it.next().equals(a)) {
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
Assertions.UNREACHABLE("Invalid: a must be a predecessor of b! " + a + " " + b);
|
||||
return -1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,532 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.cfg.cdg;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
|
||||
import com.ibm.wala.cfg.ControlFlowGraph;
|
||||
import com.ibm.wala.cfg.IBasicBlock;
|
||||
import com.ibm.wala.util.collections.EmptyIterator;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.graph.AbstractNumberedGraph;
|
||||
import com.ibm.wala.util.graph.EdgeManager;
|
||||
import com.ibm.wala.util.graph.NodeManager;
|
||||
|
||||
/**
|
||||
* Control Dependence Graph
|
||||
*
|
||||
* TODO: document me!
|
||||
*
|
||||
* @author Mangala Gowri Nanda
|
||||
*
|
||||
*/
|
||||
public class BVControlDependenceGraph extends AbstractNumberedGraph<IBasicBlock> {
|
||||
|
||||
/**
|
||||
* Governing control flow-graph. The control dependence graph is computed from
|
||||
* this cfg.
|
||||
*/
|
||||
private final ControlFlowGraph cfg;
|
||||
|
||||
/**
|
||||
* the EdgeManager for the CDG. It implements the edge part of the standard
|
||||
* Graph abstraction, using the control-dependence egdes of the cdg.
|
||||
*/
|
||||
private final EdgeManager<IBasicBlock> edgeManager;
|
||||
|
||||
private boolean ignoreUnreachableCode = false;
|
||||
|
||||
private final HashMap<IBasicBlock, BasicBlock> bbMap = new HashMap<IBasicBlock, BasicBlock>();
|
||||
|
||||
private Vector<BasicBlock> seen = new Vector<BasicBlock>();
|
||||
|
||||
private BasicBlock entry;
|
||||
|
||||
private Vector<BasicBlock> entryBlocks = new Vector<BasicBlock>();
|
||||
|
||||
private BasicBlock exitnode;
|
||||
|
||||
private int count = 0;
|
||||
|
||||
private int cfgCount = 0;
|
||||
|
||||
private final int isz = 32;
|
||||
|
||||
private final int BitMasks[] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080,
|
||||
0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
|
||||
0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
|
||||
0x10000000, 0x20000000, 0x40000000, 0x80000000 };
|
||||
|
||||
private int BitvectorSize = 0;
|
||||
|
||||
private int bitvectors[][];
|
||||
|
||||
/**
|
||||
* @param cfg
|
||||
* governing control flow graph wantEdgeLabels is always true
|
||||
*/
|
||||
public BVControlDependenceGraph(ControlFlowGraph cfg) {
|
||||
this(cfg, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cfg
|
||||
* governing control flow graph wantEdgeLabels is always true
|
||||
*/
|
||||
public BVControlDependenceGraph(ControlFlowGraph cfg, boolean ignoreUnreachableCode) {
|
||||
this.cfg = cfg;
|
||||
this.ignoreUnreachableCode = ignoreUnreachableCode;
|
||||
buildParallelGraph();
|
||||
buildCDG();
|
||||
this.edgeManager = constructGraphEdges();
|
||||
}
|
||||
|
||||
public ControlFlowGraph getUnderlyingCFG() {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the set of edge labels for the control flow edges that cause the
|
||||
* given edge in the CDG.
|
||||
*/
|
||||
public Set<? extends Object> getEdgeLabels(Object src, Object dst) {
|
||||
BasicBlock csrc = (BasicBlock) bbMap.get(src);
|
||||
if (csrc == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
BasicBlock cdst = (BasicBlock) bbMap.get(dst);
|
||||
if (cdst == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return csrc.getLabels(cdst);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*/
|
||||
public NodeManager<IBasicBlock> getNodeManager() {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*/
|
||||
public EdgeManager<IBasicBlock> getEdgeManager() {
|
||||
return edgeManager;
|
||||
}
|
||||
|
||||
private void buildParallelGraph() {
|
||||
for (Iterator<? extends IBasicBlock> it = cfg.iterateNodes(); it.hasNext();) {
|
||||
IBasicBlock bb = it.next();
|
||||
BasicBlock cdgbb = new BasicBlock(bb);
|
||||
bbMap.put(bb, cdgbb);
|
||||
cfgCount++;
|
||||
}
|
||||
|
||||
Object entryBB = cfg.entry(); // original entry node
|
||||
entry = new BasicBlock(null); // parallel entry BasicBlock
|
||||
exitnode = (BasicBlock) bbMap.get(cfg.exit());
|
||||
entryBlocks.add(entry);
|
||||
|
||||
for (Iterator<? extends IBasicBlock> it = cfg.iterateNodes(); it.hasNext();) {
|
||||
IBasicBlock bb = it.next();
|
||||
BasicBlock cdgbb = (BasicBlock) bbMap.get(bb);
|
||||
|
||||
// kludge for handling multi-entry CFGs
|
||||
if (!ignoreUnreachableCode && bb != entryBB) {
|
||||
if (cfg.getPredNodeCount(bb) == 0) {
|
||||
entryBlocks.add(cdgbb);
|
||||
}
|
||||
}
|
||||
|
||||
// build cfg edges for the parallel graph
|
||||
for (Iterator succ = cfg.getSuccNodes(bb); succ.hasNext();) {
|
||||
Object sbb = succ.next();
|
||||
BasicBlock cdgsbb = (BasicBlock) bbMap.get(sbb);
|
||||
cfgEdge(cdgbb, cdgsbb);
|
||||
}
|
||||
}
|
||||
|
||||
// link parallel entry to original entry
|
||||
cfgEdge(entry, (BasicBlock) bbMap.get(cfg.entry()));
|
||||
// link parallel entry to exit
|
||||
cfgEdge(entry, exitnode);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the heart of the CDG computation. A simple bitvector
|
||||
* implementation.
|
||||
*/
|
||||
private void buildCDG() {
|
||||
// count and index the nodes
|
||||
count(exitnode);
|
||||
for (int i = 0; i < entryBlocks.size(); i++) {
|
||||
BasicBlock en = (BasicBlock) entryBlocks.get(i);
|
||||
count(en);
|
||||
}
|
||||
|
||||
// initialize bitvectors
|
||||
count = seen.size();
|
||||
if (!ignoreUnreachableCode && count != cfgCount + 1) {
|
||||
System.out.println("Strange! count=" + count + ", cfgCount=" + cfgCount);
|
||||
}
|
||||
|
||||
BitvectorSize = count / isz + ((count % isz != 0) ? 1 : 0);
|
||||
bitvectors = new int[count][BitvectorSize];
|
||||
|
||||
// initialize the exitnode first
|
||||
exitnode.index = 0;
|
||||
ClearVector(0);
|
||||
SetBitInVector(0, 0);
|
||||
|
||||
// initialize the rest of the blocks
|
||||
for (int i = 1; i < count; i++) {
|
||||
BasicBlock bb = (BasicBlock) seen.get(i);
|
||||
bb.index = i;
|
||||
SetVector(i);
|
||||
}
|
||||
|
||||
// iterate till all post dominators are done
|
||||
boolean change = true;
|
||||
while (change) {
|
||||
change = false;
|
||||
for (int i = 1; i < count; i++) {
|
||||
BasicBlock sb = (BasicBlock) seen.get(i);
|
||||
Vector succ = sb.getSuccessors();
|
||||
for (int j = 0; j < succ.size(); j++) {
|
||||
if (intersect(sb.index, ((BasicBlock) succ.get(j)).index)) {
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// to find the control dependence
|
||||
for (int n = count - 1; n >= 0; n--) {
|
||||
int i, j, k, tx;
|
||||
BasicBlock bb = (BasicBlock) seen.get(n);
|
||||
Vector succ = bb.getSuccessors();
|
||||
if (succ.size() > 1) {
|
||||
for (int m = 0; m < succ.size(); m++) {
|
||||
BasicBlock sb = (BasicBlock) succ.get(m);
|
||||
for (i = 0, k = 0; i < BitvectorSize; i++) {
|
||||
// postdominates sb but does not postdominate bb
|
||||
tx = bitvectors[sb.index][i] & ~bitvectors[bb.index][i];
|
||||
for (j = 0; j < isz; j++, k++) {
|
||||
if (k >= count)
|
||||
break;
|
||||
|
||||
if (GetBit(tx, BitMasks[j]) != 0) {
|
||||
cdEdge(bb, (BasicBlock) seen.get(i * isz + j), sb.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If bb postdominates one of its successors sb, it is control dependent
|
||||
// on itself with label sb
|
||||
for (int m = 0; m < succ.size(); m++) {
|
||||
BasicBlock sb = (BasicBlock) succ.get(m);
|
||||
if (postdominates(sb.index, bb.index)) {
|
||||
cdEdge(bb, bb, sb.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* EdgeManager
|
||||
*/
|
||||
private EdgeManager<IBasicBlock> constructGraphEdges() {
|
||||
return new EdgeManager<IBasicBlock>() {
|
||||
public Iterator<IBasicBlock> getPredNodes(IBasicBlock N) {
|
||||
BasicBlock cbb = (BasicBlock) bbMap.get(N);
|
||||
if (cbb == null) {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
return cbb.getPredNodes();
|
||||
}
|
||||
|
||||
public int getPredNodeCount(IBasicBlock N) {
|
||||
BasicBlock cbb = (BasicBlock) bbMap.get(N);
|
||||
if (cbb == null)
|
||||
return 0;
|
||||
return cbb.getPredNodeCount();
|
||||
}
|
||||
|
||||
public Iterator<IBasicBlock> getSuccNodes(IBasicBlock N) {
|
||||
BasicBlock cbb = (BasicBlock) bbMap.get(N);
|
||||
if (cbb == null) {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
return cbb.getSuccNodes();
|
||||
}
|
||||
|
||||
public int getSuccNodeCount(IBasicBlock N) {
|
||||
BasicBlock cbb = (BasicBlock) bbMap.get(N);
|
||||
if (cbb == null)
|
||||
return 0;
|
||||
return cbb.getSuccNodeCount();
|
||||
}
|
||||
|
||||
public boolean hasEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
BasicBlock csrc = (BasicBlock) bbMap.get(src);
|
||||
if (csrc == null)
|
||||
return false;
|
||||
BasicBlock cdst = (BasicBlock) bbMap.get(dst);
|
||||
if (cdst == null)
|
||||
return false;
|
||||
return csrc.hasCDSuccessor(cdst);
|
||||
}
|
||||
|
||||
public void addEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeAllIncidentEdges(IBasicBlock node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeIncomingEdges(IBasicBlock node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeOutgoingEdges(IBasicBlock node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (Iterator<? extends IBasicBlock> ns = iterateNodes(); ns.hasNext();) {
|
||||
IBasicBlock n = ns.next();
|
||||
sb.append(n.toString()).append("\n");
|
||||
for (Iterator<? extends IBasicBlock> ss = getSuccNodes(n); ss.hasNext();) {
|
||||
Object s = ss.next();
|
||||
sb.append(" --> ").append(s);
|
||||
for (Iterator labels = getEdgeLabels(n, s).iterator(); labels.hasNext();)
|
||||
sb.append("\n label: ").append(labels.next());
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void count(BasicBlock bb) {
|
||||
// postorder
|
||||
if (bb.mark)
|
||||
return;
|
||||
bb.mark = true;
|
||||
|
||||
Vector succ = bb.getSuccessors();
|
||||
for (int i = 0; i < succ.size(); i++) {
|
||||
BasicBlock bs = (BasicBlock) succ.get(i);
|
||||
count(bs);
|
||||
}
|
||||
seen.add(bb);
|
||||
}
|
||||
|
||||
private void cfgEdge(BasicBlock b1, BasicBlock b2) {
|
||||
b2.linkPredecessor(b1);
|
||||
b1.linkSuccessor(b2);
|
||||
}
|
||||
|
||||
private void cdEdge(BasicBlock b1, BasicBlock b2, IBasicBlock label) {
|
||||
if (b1 == entry)
|
||||
return;
|
||||
b2.linkCDpredecessor(b1);
|
||||
b1.linkCDsuccessor(b2, label);
|
||||
}
|
||||
|
||||
private void ClearVector(int bb) {
|
||||
for (int i = 0; i < BitvectorSize; i++) {
|
||||
bitvectors[bb][i] = ClearAllBits();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetVector(int bb) {
|
||||
for (int i = 0; i < BitvectorSize; i++) {
|
||||
bitvectors[bb][i] = SetAllBits();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetBitInVector(int bb, int index) {
|
||||
int div = index / isz;
|
||||
int mod = index % isz;
|
||||
bitvectors[bb][div] = SetBit(bitvectors[bb][div], BitMasks[mod]);
|
||||
}
|
||||
|
||||
private boolean intersect(int b1, int b2) {
|
||||
int div = b1 / isz;
|
||||
int mod = b1 % isz;
|
||||
boolean change = false;
|
||||
for (int i = 0; i < BitvectorSize; i++) {
|
||||
int save = bitvectors[b1][i];
|
||||
bitvectors[b1][i] &= bitvectors[b2][i];
|
||||
if (i == div)
|
||||
bitvectors[b1][i] = SetBit(bitvectors[b1][i], BitMasks[mod]);
|
||||
if (save != bitvectors[b1][i])
|
||||
change = true;
|
||||
}
|
||||
return change;
|
||||
}
|
||||
|
||||
private boolean postdominates(int b1, int b2) {
|
||||
int div = b2 / isz;
|
||||
int mod = b2 % isz;
|
||||
return (GetBit(bitvectors[b1][div], BitMasks[mod]) != 0);
|
||||
}
|
||||
|
||||
private int SetBit(int flg, int msk) {
|
||||
return flg |= msk;
|
||||
}
|
||||
|
||||
/*
|
||||
* private int ClearBit(int flg, int msk){ return flg &= ~msk; }
|
||||
*/
|
||||
|
||||
private int GetBit(int flg, int msk) {
|
||||
return flg & msk;
|
||||
}
|
||||
|
||||
private int ClearAllBits() {
|
||||
return 0x00000000;
|
||||
}
|
||||
|
||||
private int SetAllBits() {
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
public static class BasicBlock {
|
||||
|
||||
protected final IBasicBlock item;
|
||||
|
||||
protected boolean mark = false;
|
||||
|
||||
protected int index;
|
||||
|
||||
private Vector<BasicBlock> predecessors = new Vector<BasicBlock>(2);
|
||||
|
||||
private Vector<BasicBlock> successors = new Vector<BasicBlock>(2);
|
||||
|
||||
private Vector<IBasicBlock> cdPred = new Vector<IBasicBlock>(2);
|
||||
|
||||
private Vector<IBasicBlock> cdSucc = new Vector<IBasicBlock>(2);
|
||||
|
||||
private HashMap<IBasicBlock, Set<IBasicBlock>> labelMap = new HashMap<IBasicBlock, Set<IBasicBlock>>();
|
||||
|
||||
private BasicBlock(IBasicBlock item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return item.toString();
|
||||
}
|
||||
|
||||
private void linkPredecessor(BasicBlock bb) {
|
||||
Assertions._assert(bb != null);
|
||||
|
||||
if (!predecessors.contains(bb))
|
||||
predecessors.add(bb);
|
||||
}
|
||||
|
||||
/*
|
||||
* private int countPredecessors () { return predecessors.size(); }
|
||||
*
|
||||
* private BasicBlock getPredecessor ( int idx ) { return (BasicBlock)
|
||||
* predecessors.get(idx); }
|
||||
*
|
||||
* private Vector getPredecessors () { return predecessors; }
|
||||
*/
|
||||
|
||||
private void linkSuccessor(BasicBlock bb) {
|
||||
Assertions._assert(bb != null);
|
||||
|
||||
if (!successors.contains(bb))
|
||||
successors.add(bb);
|
||||
}
|
||||
|
||||
/*
|
||||
* private int countSuccessors () { return successors.size(); }
|
||||
*
|
||||
* private BasicBlock getSuccessor ( int idx ) { return (BasicBlock)
|
||||
* successors.get(idx); }
|
||||
*/
|
||||
|
||||
private Vector getSuccessors() {
|
||||
return successors;
|
||||
}
|
||||
|
||||
private void linkCDpredecessor(BasicBlock bb) {
|
||||
Assertions._assert(bb != null);
|
||||
|
||||
if (!cdPred.contains(bb.item))
|
||||
cdPred.add(bb.item);
|
||||
}
|
||||
|
||||
private int getPredNodeCount() {
|
||||
return cdPred.size();
|
||||
}
|
||||
|
||||
private Iterator<IBasicBlock> getPredNodes() {
|
||||
return cdPred.iterator();
|
||||
}
|
||||
|
||||
private void linkCDsuccessor(BasicBlock bb, IBasicBlock label) {
|
||||
Assertions._assert(bb != null);
|
||||
|
||||
if (!cdSucc.contains(bb.item)) {
|
||||
cdSucc.add(bb.item);
|
||||
}
|
||||
Set<IBasicBlock> labelSet = labelMap.get(bb.item);
|
||||
if (labelSet == null) {
|
||||
labelSet = new HashSet<IBasicBlock>(2);
|
||||
labelMap.put(bb.item, labelSet);
|
||||
}
|
||||
if (label != null && !labelSet.contains(label))
|
||||
labelSet.add(label);
|
||||
}
|
||||
|
||||
private int getSuccNodeCount() {
|
||||
return cdSucc.size();
|
||||
}
|
||||
|
||||
private Iterator<IBasicBlock> getSuccNodes() {
|
||||
return cdSucc.iterator();
|
||||
}
|
||||
|
||||
private Set<IBasicBlock> getLabels(BasicBlock succ) {
|
||||
Set<IBasicBlock> ret = labelMap.get(succ.item);
|
||||
if (ret == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private boolean hasCDSuccessor(BasicBlock succ) {
|
||||
if (cdSucc.contains(succ.item))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // end of BasicBlock
|
||||
}
|
|
@ -0,0 +1,254 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.cfg.cdg;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.cfg.ControlFlowGraph;
|
||||
import com.ibm.wala.cfg.IBasicBlock;
|
||||
import com.ibm.wala.util.collections.EmptyIterator;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.graph.AbstractNumberedGraph;
|
||||
import com.ibm.wala.util.graph.DominanceFrontiers;
|
||||
import com.ibm.wala.util.graph.EdgeManager;
|
||||
import com.ibm.wala.util.graph.NodeManager;
|
||||
import com.ibm.wala.util.graph.impl.GraphInverter;
|
||||
|
||||
/**
|
||||
* Control Dependence Graph
|
||||
*
|
||||
* @author Julian Dolby
|
||||
*
|
||||
*/
|
||||
public class ControlDependenceGraph extends AbstractNumberedGraph<IBasicBlock> {
|
||||
|
||||
/**
|
||||
* Governing control flow-graph. The control dependence graph is computed from
|
||||
* this cfg.
|
||||
*/
|
||||
private final ControlFlowGraph cfg;
|
||||
|
||||
/**
|
||||
* the EdgeManager for the CDG. It implements the edge part of the standard
|
||||
* Graph abstraction, using the control-dependence egdes of the cdg.
|
||||
*/
|
||||
private final EdgeManager<IBasicBlock> edgeManager;
|
||||
|
||||
/**
|
||||
* If requested, this is a map from parentXchild Pairs representing edges in
|
||||
* the CDG to the labels of the control flow edges that edge corresponds to.
|
||||
* The labels are Boolean.True or Boolean.False for conditionals and an
|
||||
* Integer for a switch label.
|
||||
*/
|
||||
private Map<Pair, Set<Object>> edgeLabels;
|
||||
|
||||
/**
|
||||
* This is the heart of the CDG computation. Based on Cytron et al., this is
|
||||
* the reverse dominance frontier based algorithm for computing control
|
||||
* dependence edges.
|
||||
*
|
||||
* @return Map: node n -> {x : n is control-dependent on x}
|
||||
*/
|
||||
private Map<IBasicBlock, Set<IBasicBlock>> buildControlDependence(boolean wantEdgeLabels) {
|
||||
Map<IBasicBlock, Set<IBasicBlock>> controlDependence = new HashMap<IBasicBlock, Set<IBasicBlock>>(cfg.getNumberOfNodes());
|
||||
|
||||
DominanceFrontiers<IBasicBlock> RDF = new DominanceFrontiers<IBasicBlock>(GraphInverter.invert(cfg), cfg.exit());
|
||||
|
||||
if (wantEdgeLabels) {
|
||||
edgeLabels = HashMapFactory.make();
|
||||
}
|
||||
|
||||
for (Iterator<? extends IBasicBlock> ns = cfg.iterateNodes(); ns.hasNext();) {
|
||||
controlDependence.put(ns.next(), new HashSet<IBasicBlock>(2));
|
||||
}
|
||||
|
||||
for (Iterator<? extends IBasicBlock> ns = cfg.iterateNodes(); ns.hasNext();) {
|
||||
IBasicBlock y = ns.next();
|
||||
for (Iterator<IBasicBlock> ns2 = RDF.getDominanceFrontier(y); ns2.hasNext();) {
|
||||
IBasicBlock x = ns2.next();
|
||||
controlDependence.get(x).add(y);
|
||||
if (wantEdgeLabels) {
|
||||
Set<Object> labels = new HashSet<Object>();
|
||||
edgeLabels.put(new Pair<Object, Object>(x, y), labels);
|
||||
for (Iterator<? extends IBasicBlock> ss = cfg.getSuccNodes(x); ss.hasNext();) {
|
||||
IBasicBlock s = ss.next();
|
||||
if (RDF.isDominatedBy(s, y)) {
|
||||
labels.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return controlDependence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the control-dependence edges in a forward direction (i.e. edges from
|
||||
* control parents to control children), this method creates an EdgeManager
|
||||
* that provides the edge half of the Graph abstraction.
|
||||
*/
|
||||
private EdgeManager<IBasicBlock> constructGraphEdges(final Map<IBasicBlock, Set<IBasicBlock>> forwardEdges) {
|
||||
return new EdgeManager<IBasicBlock>() {
|
||||
Map<IBasicBlock, Set<IBasicBlock>> backwardEdges = new HashMap<IBasicBlock, Set<IBasicBlock>>(forwardEdges.size());
|
||||
{
|
||||
for (Iterator<? extends IBasicBlock> x = cfg.iterateNodes(); x.hasNext();) {
|
||||
Set<IBasicBlock> s = HashSetFactory.make();
|
||||
backwardEdges.put(x.next(), s);
|
||||
}
|
||||
for (Iterator<IBasicBlock> ps = forwardEdges.keySet().iterator(); ps.hasNext();) {
|
||||
IBasicBlock p = ps.next();
|
||||
for (Iterator ns = ((Set) forwardEdges.get(p)).iterator(); ns.hasNext();) {
|
||||
Object n = ns.next();
|
||||
backwardEdges.get(n).add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<IBasicBlock> getPredNodes(IBasicBlock N) {
|
||||
if (backwardEdges.containsKey(N))
|
||||
return backwardEdges.get(N).iterator();
|
||||
else
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
|
||||
public int getPredNodeCount(IBasicBlock N) {
|
||||
if (backwardEdges.containsKey(N))
|
||||
return ((Set) backwardEdges.get(N)).size();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Iterator<IBasicBlock> getSuccNodes(IBasicBlock N) {
|
||||
if (forwardEdges.containsKey(N))
|
||||
return forwardEdges.get(N).iterator();
|
||||
else
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
|
||||
public int getSuccNodeCount(IBasicBlock N) {
|
||||
if (forwardEdges.containsKey(N))
|
||||
return ((Set) forwardEdges.get(N)).size();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean hasEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
return forwardEdges.containsKey(src) && ((Set) forwardEdges.get(src)).contains(dst);
|
||||
}
|
||||
|
||||
public void addEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeAllIncidentEdges(IBasicBlock node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeIncomingEdges(IBasicBlock node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeOutgoingEdges(IBasicBlock node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (Iterator<? extends IBasicBlock> ns = iterateNodes(); ns.hasNext();) {
|
||||
IBasicBlock n = ns.next();
|
||||
sb.append(n.toString()).append("\n");
|
||||
for (Iterator ss = getSuccNodes(n); ss.hasNext();) {
|
||||
Object s = ss.next();
|
||||
sb.append(" --> ").append(s);
|
||||
if (edgeLabels != null)
|
||||
for (Iterator labels = ((Set) edgeLabels.get(new Pair<IBasicBlock, Object>(n, s))).iterator(); labels.hasNext();)
|
||||
sb.append("\n label: ").append(labels.next());
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cfg
|
||||
* governing control flow graph
|
||||
* @param wantEdgeLabels
|
||||
* whether to compute edge labels for CDG edges
|
||||
*/
|
||||
public ControlDependenceGraph(ControlFlowGraph cfg, boolean wantEdgeLabels) {
|
||||
this.cfg = cfg;
|
||||
this.edgeManager = constructGraphEdges(buildControlDependence(wantEdgeLabels));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cfg
|
||||
* governing control flow graph
|
||||
*/
|
||||
public ControlDependenceGraph(ControlFlowGraph cfg) {
|
||||
this(cfg, false);
|
||||
}
|
||||
|
||||
public ControlFlowGraph getUnderlyingCFG() {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the set of edge labels for the control flow edges that cause the
|
||||
* given edge in the CDG. Requires that the CDG be constructed with
|
||||
* wantEdgeLabels being true.
|
||||
*/
|
||||
public Set<Object> getEdgeLabels(Object from, Object to) {
|
||||
return edgeLabels.get(new Pair<Object, Object>(from, to));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*/
|
||||
public NodeManager<IBasicBlock> getNodeManager() {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*/
|
||||
public EdgeManager<IBasicBlock> getEdgeManager() {
|
||||
return edgeManager;
|
||||
}
|
||||
|
||||
public boolean controlEquivalent(IBasicBlock bb1, IBasicBlock bb2) {
|
||||
if (getPredNodeCount(bb1) != getPredNodeCount(bb2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Iterator pbs1 = getPredNodes(bb1); pbs1.hasNext();) {
|
||||
if (!hasEdge((IBasicBlock) pbs1.next(), bb2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
This package supports a control-dependence graph.
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,5 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
This package provides control-flow graph utilities.
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,76 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.util.collections.NonNullSingletonIterator;
|
||||
import com.ibm.wala.util.config.FileProvider;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
public abstract class AbstractURLModule implements Module, ModuleEntry {
|
||||
|
||||
private final URL url;
|
||||
|
||||
public AbstractURLModule(URL url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public URL getURL() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
try {
|
||||
URLConnection con = url.openConnection();
|
||||
if (con instanceof JarURLConnection)
|
||||
return ((JarURLConnection) con).getEntryName();
|
||||
else
|
||||
return FileProvider.filePathFromURL(url);
|
||||
} catch (IOException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
try {
|
||||
return url.openConnection().getInputStream();
|
||||
} catch (IOException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isModuleFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Module asModule() {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Iterator<ModuleEntry> getEntries() {
|
||||
return new NonNullSingletonIterator<ModuleEntry>(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,354 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.shrikeBT.Constants;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.Atom;
|
||||
import com.ibm.wala.util.collections.EmptyIterator;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
* Implementation of IClass for array classes.
|
||||
*
|
||||
* @author Alan Donovan
|
||||
* @author sfink
|
||||
*/
|
||||
public class ArrayClass implements IClass, Constants {
|
||||
|
||||
/**
|
||||
* Package-visible constructor; only for use by ArrayClassLoader class.
|
||||
* 'loader' must be the Primordial IClassLoader.
|
||||
*
|
||||
* [WHY? -- array classes are loaded by the element classloader??]
|
||||
*/
|
||||
ArrayClass(TypeReference type, IClassLoader loader) {
|
||||
this.type = type;
|
||||
this.loader = loader;
|
||||
if (Assertions.verifyAssertions) {
|
||||
TypeReference elementType = type.getInnermostElementType();
|
||||
if (!elementType.isPrimitiveType()) {
|
||||
IClass klass = loader.lookupClass(elementType.getName());
|
||||
if (klass == null) {
|
||||
Assertions.UNREACHABLE("caller should not attempt to create an array with type " + type);
|
||||
}
|
||||
} else {
|
||||
Assertions._assert(loader.getReference().equals(ClassLoaderReference.Primordial));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final TypeReference type;
|
||||
|
||||
private final IClassLoader loader;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getClassLoader()
|
||||
*/
|
||||
public IClassLoader getClassLoader() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getName()
|
||||
*/
|
||||
public TypeName getName() {
|
||||
return getReference().getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#isInterface()
|
||||
*/
|
||||
public boolean isInterface() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#isAbstract()
|
||||
*/
|
||||
public boolean isAbstract() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getModifiers()
|
||||
*/
|
||||
public int getModifiers() {
|
||||
return ACC_PUBLIC | ACC_FINAL;
|
||||
}
|
||||
|
||||
public String getQualifiedNameForReflection() {
|
||||
return type.getName().toString(); // XXX is this the right string?
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getSuperclass()
|
||||
*/
|
||||
public IClass getSuperclass() {
|
||||
try {
|
||||
IClass elt = getElementClass();
|
||||
|
||||
Assertions._assert(getReference().getArrayElementType().isPrimitiveType() || elt != null);
|
||||
|
||||
// super is Ljava/lang/Object in two cases:
|
||||
// 1) [Ljava/lang/Object
|
||||
// 2) [? for primitive arrays (null from getElementClass)
|
||||
if (elt == null || elt.getReference() == TypeReference.JavaLangObject) {
|
||||
return loader.lookupClass(TypeReference.JavaLangObject.getName());
|
||||
}
|
||||
|
||||
// else it is array of super of element type (yuck)
|
||||
else {
|
||||
TypeReference eltSuperRef = elt.getSuperclass().getReference();
|
||||
TypeReference superRef = TypeReference.findOrCreateArrayOf(eltSuperRef);
|
||||
return elt.getSuperclass().getClassLoader().lookupClass(superRef.getName());
|
||||
}
|
||||
} catch (ClassHierarchyException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getMethod(com.ibm.wala.classLoader.Selector)
|
||||
*/
|
||||
public IMethod getMethod(Selector sig) {
|
||||
return loader.lookupClass(TypeReference.JavaLangObject.getName()).getMethod(sig);
|
||||
}
|
||||
|
||||
public IField getField(Atom name) {
|
||||
return getSuperclass().getField(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredMethods()
|
||||
*/
|
||||
public Iterator<IMethod> getDeclaredMethods() {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
|
||||
public int getNumberOfDeclaredMethods() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getReference()
|
||||
*/
|
||||
public TypeReference getReference() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getSourceFileName()
|
||||
*/
|
||||
public String getSourceFileName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getClassInitializer()
|
||||
*/
|
||||
public IMethod getClassInitializer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#isArrayClass()
|
||||
*/
|
||||
public boolean isArrayClass() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return getReference().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the IClass that represents the array element type, or null if the
|
||||
* element type is a primitive
|
||||
*/
|
||||
public IClass getElementClass() {
|
||||
TypeReference elementType = getReference().getArrayElementType();
|
||||
if (elementType.isPrimitiveType()) {
|
||||
return null;
|
||||
}
|
||||
return loader.lookupClass(elementType.getName());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return type.hashCode();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredFields()
|
||||
*/
|
||||
public Collection<IField> getDeclaredInstanceFields() {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredStaticFields()
|
||||
*/
|
||||
public Collection<IField> getDeclaredStaticFields() {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllImplementedInterfaces()
|
||||
*/
|
||||
public Collection<IClass> getAllImplementedInterfaces() {
|
||||
HashSet<IClass> result = HashSetFactory.make(2);
|
||||
result.add(loader.lookupClass(TypeReference.array_interfaces[0]));
|
||||
result.add(loader.lookupClass(TypeReference.array_interfaces[1]));
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllAncestorInterfaces()
|
||||
*/
|
||||
public Collection<IClass> getAllAncestorInterfaces() {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#isReferenceType()
|
||||
*/
|
||||
public boolean isReferenceType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getDimensionality() {
|
||||
return getReference().getDimensionality();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the IClass that represents the innermost array element type, or
|
||||
* null if the element type is a primitive
|
||||
*/
|
||||
public IClass getInnermostElementClass() {
|
||||
TypeReference elementType = getReference().getInnermostElementType();
|
||||
if (elementType.isPrimitiveType()) {
|
||||
return null;
|
||||
}
|
||||
return loader.lookupClass(elementType.getName());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDirectInterfaces()
|
||||
*/
|
||||
public Collection<IClass> getDirectInterfaces() {
|
||||
// TODO Auto-generated method stub
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ArrayClass) {
|
||||
ArrayClass other = (ArrayClass) obj;
|
||||
return loader.equals(other.loader) && type.equals(other.type);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllInstanceFields()
|
||||
*/
|
||||
public Collection<IField> getAllInstanceFields() throws ClassHierarchyException {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllStaticFields()
|
||||
*/
|
||||
public Collection<IField> getAllStaticFields() throws ClassHierarchyException {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllMethods()
|
||||
*/
|
||||
public Collection getAllMethods() throws ClassHierarchyException {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllFields()
|
||||
*/
|
||||
public Collection<IField> getAllFields() throws ClassHierarchyException {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
* Pseudo-classloader for all array classes; all other IClassLoader
|
||||
* implementations should delegate to this one for array classes only.
|
||||
*
|
||||
* @author Stephen Fink
|
||||
*/
|
||||
public class ArrayClassLoader {
|
||||
|
||||
private final static boolean DEBUG = false;
|
||||
|
||||
/**
|
||||
* map: TypeReference -> ArrayClass
|
||||
*/
|
||||
private HashMap<TypeReference, ArrayClass> arrayClasses = HashMapFactory.make();
|
||||
|
||||
/**
|
||||
* @param className
|
||||
* name of the array class
|
||||
* @param delegator
|
||||
* class loader to look up element type with
|
||||
*/
|
||||
public IClass lookupClass(TypeName className, IClassLoader delegator) {
|
||||
if (DEBUG) {
|
||||
Assertions._assert(className.toString().startsWith("["));
|
||||
}
|
||||
|
||||
TypeReference type = TypeReference.findOrCreate(delegator.getReference(), className);
|
||||
ArrayClass arrayClass = arrayClasses.get(type);
|
||||
if (arrayClass == null) {
|
||||
TypeReference elementType = type.getArrayElementType();
|
||||
if (elementType.isPrimitiveType()) {
|
||||
TypeReference aRef = TypeReference.findOrCreateArrayOf(elementType);
|
||||
arrayClass = arrayClasses.get(aRef);
|
||||
IClassLoader primordial = getRootClassLoader(delegator);
|
||||
if (arrayClass == null) {
|
||||
arrayClasses.put(aRef, arrayClass = new ArrayClass(aRef, primordial));
|
||||
}
|
||||
} else {
|
||||
// check that the element class is loadable. If not, return null.
|
||||
if (delegator.lookupClass(elementType.getName()) == null) {
|
||||
return null;
|
||||
}
|
||||
arrayClass = new ArrayClass(type, delegator);
|
||||
}
|
||||
arrayClasses.put(type, arrayClass);
|
||||
}
|
||||
return arrayClass;
|
||||
}
|
||||
|
||||
private static IClassLoader getRootClassLoader(IClassLoader l) {
|
||||
while (l.getParent() != null) {
|
||||
l = l.getParent();
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class BinaryDirectoryTreeModule extends DirectoryTreeModule {
|
||||
|
||||
public BinaryDirectoryTreeModule(File root) {
|
||||
super(root);
|
||||
}
|
||||
|
||||
protected boolean includeFile(File file) {
|
||||
return file.getName().endsWith("class");
|
||||
}
|
||||
|
||||
protected FileModule makeFile(File file) {
|
||||
return new ClassFileModule(file);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.ContextItem;
|
||||
import com.ibm.wala.shrikeBT.BytecodeConstants;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* Simple object that represents a static call site (ie., an invoke instruction
|
||||
* in the bytecode)
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public abstract class CallSiteReference extends ProgramCounter implements BytecodeConstants, ContextItem {
|
||||
|
||||
final private MethodReference declaredTarget;
|
||||
|
||||
/**
|
||||
* @param programCounter
|
||||
* @param declaredTarget
|
||||
*/
|
||||
protected CallSiteReference(int programCounter, MethodReference declaredTarget) {
|
||||
super(programCounter);
|
||||
this.declaredTarget = declaredTarget;
|
||||
}
|
||||
|
||||
// the following atrocities are needed to save a word of space by
|
||||
// declaring these classes static, so they don't keep a pointer
|
||||
// to the enclosing environment
|
||||
// Java makes you type!
|
||||
static class StaticCall extends CallSiteReference {
|
||||
StaticCall(int programCounter, MethodReference declaredTarget) {
|
||||
super(programCounter, declaredTarget);
|
||||
}
|
||||
|
||||
public IInvokeInstruction.IDispatch getInvocationCode() {
|
||||
return IInvokeInstruction.Dispatch.STATIC;
|
||||
}
|
||||
}
|
||||
|
||||
static class SpecialCall extends CallSiteReference {
|
||||
SpecialCall(int programCounter, MethodReference declaredTarget) {
|
||||
super(programCounter, declaredTarget);
|
||||
}
|
||||
|
||||
public IInvokeInstruction.IDispatch getInvocationCode() {
|
||||
return IInvokeInstruction.Dispatch.SPECIAL;
|
||||
}
|
||||
}
|
||||
|
||||
static class VirtualCall extends CallSiteReference {
|
||||
VirtualCall(int programCounter, MethodReference declaredTarget) {
|
||||
super(programCounter, declaredTarget);
|
||||
}
|
||||
|
||||
public IInvokeInstruction.IDispatch getInvocationCode() {
|
||||
return IInvokeInstruction.Dispatch.VIRTUAL;
|
||||
}
|
||||
}
|
||||
|
||||
static class InterfaceCall extends CallSiteReference {
|
||||
InterfaceCall(int programCounter, MethodReference declaredTarget) {
|
||||
super(programCounter, declaredTarget);
|
||||
}
|
||||
|
||||
public IInvokeInstruction.IDispatch getInvocationCode() {
|
||||
return IInvokeInstruction.Dispatch.INTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This factory method plays a little game to avoid storing the invocation
|
||||
* code in the object; this saves a byte (probably actually a whole word) in
|
||||
* each created object.
|
||||
*
|
||||
* TODO: Consider canonicalization?
|
||||
*/
|
||||
public static CallSiteReference make(int programCounter, MethodReference declaredTarget,
|
||||
IInvokeInstruction.IDispatch invocationCode) {
|
||||
|
||||
if (invocationCode == IInvokeInstruction.Dispatch.SPECIAL)
|
||||
return new SpecialCall(programCounter, declaredTarget);
|
||||
if (invocationCode == IInvokeInstruction.Dispatch.VIRTUAL)
|
||||
return new VirtualCall(programCounter, declaredTarget);
|
||||
if (invocationCode == IInvokeInstruction.Dispatch.INTERFACE)
|
||||
return new InterfaceCall(programCounter, declaredTarget);
|
||||
if (invocationCode == IInvokeInstruction.Dispatch.STATIC)
|
||||
return new StaticCall(programCounter, declaredTarget);
|
||||
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Method that this call site calls. This represents the method
|
||||
* declared in the invoke instruction only.
|
||||
*/
|
||||
public MethodReference getDeclaredTarget() {
|
||||
return declaredTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return one of INVOKESPECIAL, INVOKESTATIC, INVOKEVIRTUAL, or
|
||||
* INVOKEINTERFACE
|
||||
*/
|
||||
abstract public IInvokeInstruction.IDispatch getInvocationCode();
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "invoke" + getInvocationString(getInvocationCode()) + " " + declaredTarget + "@" + getProgramCounter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getInvocationString.
|
||||
*
|
||||
* @param invocationCode
|
||||
* @return String
|
||||
*/
|
||||
protected String getInvocationString(IInvokeInstruction.IDispatch invocationCode) {
|
||||
if (invocationCode == IInvokeInstruction.Dispatch.STATIC)
|
||||
return "static";
|
||||
if (invocationCode == IInvokeInstruction.Dispatch.SPECIAL)
|
||||
return "special";
|
||||
if (invocationCode == IInvokeInstruction.Dispatch.VIRTUAL)
|
||||
return "virtual";
|
||||
if (invocationCode == IInvokeInstruction.Dispatch.INTERFACE)
|
||||
return "interface";
|
||||
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getInvocationString() {
|
||||
return getInvocationString(getInvocationCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this an invokeinterface call site?
|
||||
*/
|
||||
public final boolean isInterface() {
|
||||
return (getInvocationCode() == IInvokeInstruction.Dispatch.INTERFACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this an invokevirtual call site?
|
||||
*/
|
||||
public final boolean isVirtual() {
|
||||
return (getInvocationCode() == IInvokeInstruction.Dispatch.VIRTUAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this an invokespecial call site?
|
||||
*/
|
||||
public final boolean isSpecial() {
|
||||
return (getInvocationCode() == IInvokeInstruction.Dispatch.SPECIAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this an invokestatic call site?
|
||||
*/
|
||||
public boolean isStatic() {
|
||||
return (getInvocationCode() == IInvokeInstruction.Dispatch.STATIC);
|
||||
}
|
||||
|
||||
public boolean isFixed() {
|
||||
return isStatic() || isSpecial();
|
||||
}
|
||||
|
||||
public boolean isDispatch() {
|
||||
return isVirtual() || isInterface();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.util.ImmutableByteArray;
|
||||
import com.ibm.wala.util.ShrikeClassReaderHandle;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* A module which is a wrapper around a .class file
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class ClassFileModule extends FileModule implements Module, ModuleEntry {
|
||||
|
||||
private final String className;
|
||||
|
||||
public ClassFileModule(File f) {
|
||||
super(f);
|
||||
// this is delicate: TODO, clean it up a bit.
|
||||
ShrikeClassReaderHandle reader = new ShrikeClassReaderHandle(this);
|
||||
ImmutableByteArray name = null;
|
||||
try {
|
||||
name = ImmutableByteArray.make(reader.get().getName());
|
||||
} catch (InvalidClassFileException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
className = name.toString();
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "ClassFileModule:" + getFile();
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isClassFile()
|
||||
*/
|
||||
public boolean isClassFile() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getClassName()
|
||||
*/
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isSourceFile()
|
||||
*/
|
||||
public boolean isSourceFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
*/
|
||||
public interface ClassLoaderFactory {
|
||||
|
||||
/**
|
||||
* Return a class loader corresponding to a given
|
||||
* class loader identifier. Create one if necessary.
|
||||
* @param classLoaderReference identifier for the desired class loader
|
||||
* @return IClassLoader
|
||||
*/
|
||||
IClassLoader getLoader(ClassLoaderReference classLoaderReference, ClassHierarchy cha, AnalysisScope scope)
|
||||
throws IOException;
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.warnings.Warning;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
* An implementation of the class loader factory that produces ClassLoaderImpls
|
||||
*/
|
||||
public class ClassLoaderFactoryImpl implements ClassLoaderFactory {
|
||||
|
||||
/**
|
||||
* Set of classes that class loaders should ignore; classloaders should
|
||||
* pretend these classes don't exit.
|
||||
*/
|
||||
private SetOfClasses exclusions;
|
||||
|
||||
/**
|
||||
* An object to track warnings
|
||||
*/
|
||||
private final WarningSet warnings;
|
||||
|
||||
/**
|
||||
* A Mapping from ClassLoaderReference to IClassLoader
|
||||
*/
|
||||
private HashMap<ClassLoaderReference, IClassLoader> map = HashMapFactory.make(3);
|
||||
|
||||
/**
|
||||
* @param exclusions
|
||||
* A set of classes that class loaders should pretend don't exist.
|
||||
*/
|
||||
public ClassLoaderFactoryImpl(SetOfClasses exclusions, WarningSet warnings) {
|
||||
this.exclusions = exclusions;
|
||||
this.warnings = warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a class loader corresponding to a given class loader identifier.
|
||||
* Create one if necessary.
|
||||
*
|
||||
* @param classLoaderReference
|
||||
* identifier for the desired class loader
|
||||
* @return IClassLoader
|
||||
*/
|
||||
public IClassLoader getLoader(ClassLoaderReference classLoaderReference, ClassHierarchy cha, AnalysisScope scope)
|
||||
throws IOException {
|
||||
IClassLoader result = map.get(classLoaderReference);
|
||||
if (result == null) {
|
||||
ClassLoaderReference parentRef = classLoaderReference.getParent();
|
||||
IClassLoader parent = null;
|
||||
if (parentRef != null) {
|
||||
parent = getLoader(parentRef, cha, scope);
|
||||
}
|
||||
IClassLoader cl = makeNewClassLoader(classLoaderReference, cha, parent, scope);
|
||||
map.put(classLoaderReference, cl);
|
||||
result = cl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new class loader for a given key
|
||||
*
|
||||
* @param classLoaderReference
|
||||
* the key
|
||||
* @param parent
|
||||
* parent classloader to be used for delegation
|
||||
* @return a new ClassLoaderImpl
|
||||
* @throws IOException
|
||||
* if the desired loader cannot be instantiated, usually because the
|
||||
* specified module can't be found.
|
||||
*/
|
||||
protected IClassLoader makeNewClassLoader(ClassLoaderReference classLoaderReference, ClassHierarchy cha, IClassLoader parent,
|
||||
AnalysisScope scope) throws IOException {
|
||||
String implClass = scope.getLoaderImpl(classLoaderReference);
|
||||
IClassLoader cl;
|
||||
if (implClass == null) {
|
||||
cl = new ClassLoaderImpl(classLoaderReference, scope.getArrayClassLoader(), parent, exclusions, scope.getModules(classLoaderReference), cha, warnings);
|
||||
} else
|
||||
try {
|
||||
Class impl = Class.forName(implClass);
|
||||
Constructor ctor = impl.getDeclaredConstructor(new Class[] { ClassLoaderReference.class, IClassLoader.class,
|
||||
SetOfClasses.class, ClassHierarchy.class, WarningSet.class });
|
||||
cl = (IClassLoader) ctor.newInstance(new Object[] { classLoaderReference, parent, exclusions, cha, warnings });
|
||||
} catch (Exception e) {
|
||||
warnings.add(InvalidClassLoaderImplementation.create(implClass));
|
||||
cl = new ClassLoaderImpl(classLoaderReference, scope.getArrayClassLoader(), parent, exclusions, scope.getModules(classLoaderReference), cha, warnings);
|
||||
}
|
||||
cl.init(scope.getModules(classLoaderReference));
|
||||
return cl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* A waring when we fail to load an appropriate class loader implementation
|
||||
*/
|
||||
private static class InvalidClassLoaderImplementation extends Warning {
|
||||
|
||||
final String impl;
|
||||
InvalidClassLoaderImplementation(String impl) {
|
||||
super(Warning.SEVERE);
|
||||
this.impl = impl;
|
||||
}
|
||||
public String getMsg() {
|
||||
return getClass().toString() + " : " + impl;
|
||||
}
|
||||
public static InvalidClassLoaderImplementation create(String impl) {
|
||||
return new InvalidClassLoaderImplementation(impl);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return the set of classes that will be ignored.
|
||||
*/
|
||||
public SetOfClasses getExclusions() {
|
||||
return exclusions;
|
||||
}
|
||||
|
||||
public WarningSet getWarnings() {
|
||||
return warnings;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,490 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.util.Atom;
|
||||
import com.ibm.wala.util.ShrikeClassReaderHandle;
|
||||
import com.ibm.wala.util.collections.HashCodeComparator;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.collections.Iterator2Collection;
|
||||
import com.ibm.wala.util.collections.ToStringComparator;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.util.warnings.Warning;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* A class loader that reads class definitions from a set of Modules.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class ClassLoaderImpl implements IClassLoader {
|
||||
private static final int DEBUG_LEVEL = 0;
|
||||
|
||||
/**
|
||||
* classes to ignore
|
||||
*/
|
||||
private SetOfClasses exclusions;
|
||||
|
||||
/**
|
||||
* Identity for this class loader
|
||||
*/
|
||||
private ClassLoaderReference loader;
|
||||
|
||||
/**
|
||||
* A mapping from class name (TypeName) to IClass
|
||||
*/
|
||||
protected final Map<TypeName, IClass> loadedClasses = HashMapFactory.make();
|
||||
|
||||
/**
|
||||
* A mapping from class name (TypeName) to String (source file name)
|
||||
*/
|
||||
private final Map<TypeName, String> sourceMap = HashMapFactory.make();
|
||||
|
||||
/**
|
||||
* An object to track warnings
|
||||
*/
|
||||
private final WarningSet warnings;
|
||||
|
||||
/**
|
||||
* Parent classloader
|
||||
*/
|
||||
private IClassLoader parent;
|
||||
|
||||
/**
|
||||
* Governing class hierarchy
|
||||
*/
|
||||
protected final ClassHierarchy cha;
|
||||
|
||||
/**
|
||||
* an object to delegate to for loading of array classes
|
||||
*/
|
||||
private final ArrayClassLoader arrayClassLoader;
|
||||
|
||||
/**
|
||||
* Constructor for ModuleSetClassLoader.
|
||||
*
|
||||
* @param loader
|
||||
* class loader reference identifying this loader
|
||||
* @param parent
|
||||
* parent loader for delegation
|
||||
* @param exclusions
|
||||
* set of classes to exclude from loading
|
||||
*/
|
||||
public ClassLoaderImpl(ClassLoaderReference loader, ArrayClassLoader arrayClassLoader, IClassLoader parent,
|
||||
SetOfClasses exclusions, Set modules, ClassHierarchy cha, WarningSet warnings) {
|
||||
|
||||
this.arrayClassLoader = arrayClassLoader;
|
||||
this.parent = parent;
|
||||
this.loader = loader;
|
||||
this.exclusions = exclusions;
|
||||
this.cha = cha;
|
||||
this.warnings = warnings;
|
||||
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("Creating class loader for " + loader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Set of (ModuleEntry) source files found in a module.
|
||||
*
|
||||
* @param M
|
||||
* the module
|
||||
* @return the Set of source files in the module
|
||||
* @throws IOException
|
||||
*/
|
||||
private Set<ModuleEntry> getSourceFiles(Module M) throws IOException {
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("Get source files for " + M);
|
||||
}
|
||||
TreeSet<ModuleEntry> sortedEntries = new TreeSet<ModuleEntry>(HashCodeComparator.instance());
|
||||
sortedEntries.addAll(new Iterator2Collection<ModuleEntry>(M.getEntries()));
|
||||
|
||||
HashSet<ModuleEntry> result = HashSetFactory.make();
|
||||
for (Iterator it = sortedEntries.iterator(); it.hasNext();) {
|
||||
ModuleEntry entry = (ModuleEntry) it.next();
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("consider entry for source information: " + entry);
|
||||
}
|
||||
if (entry.isSourceFile()) {
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("found source file: " + entry);
|
||||
}
|
||||
result.add(entry);
|
||||
} else if (entry.isModuleFile()) {
|
||||
result.addAll(getSourceFiles(entry.asModule()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Set of (ModuleEntry) class files found in a module.
|
||||
*
|
||||
* @param M
|
||||
* the module
|
||||
* @return the Set of class Files in the module
|
||||
* @throws IOException
|
||||
*/
|
||||
private Set<ModuleEntry> getClassFiles(Module M) throws IOException {
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("Get class files for " + M);
|
||||
}
|
||||
TreeSet<ModuleEntry> sortedEntries = new TreeSet<ModuleEntry>(HashCodeComparator.instance());
|
||||
sortedEntries.addAll(new Iterator2Collection<ModuleEntry>(M.getEntries()));
|
||||
|
||||
HashSet<ModuleEntry> result = HashSetFactory.make();
|
||||
for (Iterator it = sortedEntries.iterator(); it.hasNext();) {
|
||||
ModuleEntry entry = (ModuleEntry) it.next();
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("ClassLoaderImpl.getClassFiles:Got entry: " + entry);
|
||||
}
|
||||
if (entry.isClassFile()) {
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("result contains: " + entry);
|
||||
}
|
||||
result.add(entry);
|
||||
} else if (entry.isModuleFile()) {
|
||||
Set<ModuleEntry> s = getClassFiles(entry.asModule());
|
||||
removeClassFiles(s, result);
|
||||
result.addAll(s);
|
||||
} else {
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("Ignoring entry: " + entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove from s any class file module entries which already are in t
|
||||
*
|
||||
* @param s
|
||||
* @param t
|
||||
*/
|
||||
private void removeClassFiles(Set<ModuleEntry> s, Set<ModuleEntry> t) {
|
||||
Set<String> old = new HashSet<String>();
|
||||
for (Iterator<ModuleEntry> it = t.iterator(); it.hasNext();) {
|
||||
ModuleEntry m = it.next();
|
||||
old.add(m.getClassName());
|
||||
}
|
||||
HashSet<ModuleEntry> toRemove = new HashSet<ModuleEntry>();
|
||||
for (Iterator<ModuleEntry> it = s.iterator(); it.hasNext();) {
|
||||
ModuleEntry m = it.next();
|
||||
if (old.contains(m.getClassName())) {
|
||||
toRemove.add(m);
|
||||
}
|
||||
}
|
||||
s.removeAll(toRemove);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Set of IClasses, which represents all classes this class loader
|
||||
* can load.
|
||||
*/
|
||||
private Collection<IClass> getAllClasses() {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(loadedClasses != null);
|
||||
}
|
||||
|
||||
return loadedClasses.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the set of classes loaded by this object.
|
||||
*/
|
||||
private void loadAllClasses(Collection<ModuleEntry> moduleEntries) {
|
||||
for (Iterator<ModuleEntry> it = moduleEntries.iterator(); it.hasNext();) {
|
||||
ModuleEntry entry = it.next();
|
||||
if (!entry.isClassFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String className = entry.getClassName().replace('.', '/');
|
||||
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("Consider " + className);
|
||||
}
|
||||
|
||||
if (exclusions != null && exclusions.contains(className)) {
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("Excluding " + className);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ShrikeClassReaderHandle reader = new ShrikeClassReaderHandle(entry);
|
||||
|
||||
className = "L" + className;
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("Load class " + className);
|
||||
}
|
||||
try {
|
||||
TypeName T = TypeName.string2TypeName(className);
|
||||
if (loadedClasses.get(T) != null) {
|
||||
warnings.add(MultipleImplementationsWarning.create(className));
|
||||
} else {
|
||||
ShrikeCTClassWrapper klass = new ShrikeCTClassWrapper(reader, this, cha, warnings);
|
||||
if (klass.getReference().getName().equals(T)) {
|
||||
loadedClasses.put(T, new ShrikeCTClassWrapper(reader, this, cha, warnings));
|
||||
if (DEBUG_LEVEL > 1) {
|
||||
Trace.println("put " + T + " ");
|
||||
}
|
||||
} else {
|
||||
warnings.add(InvalidClassFile.create(className));
|
||||
}
|
||||
}
|
||||
} catch (InvalidClassFileException e) {
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("Ignoring class " + className + " due to InvalidClassFileException");
|
||||
}
|
||||
warnings.add(InvalidClassFile.create(className));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* A waring when we find more than one implementation of a given class name
|
||||
*/
|
||||
private static class MultipleImplementationsWarning extends Warning {
|
||||
|
||||
final String className;
|
||||
|
||||
MultipleImplementationsWarning(String className) {
|
||||
super(Warning.SEVERE);
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return getClass().toString() + " : " + className;
|
||||
}
|
||||
|
||||
public static MultipleImplementationsWarning create(String className) {
|
||||
return new MultipleImplementationsWarning(className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* A waring when we encounter InvalidClassFileException
|
||||
*/
|
||||
private static class InvalidClassFile extends Warning {
|
||||
|
||||
final String className;
|
||||
|
||||
InvalidClassFile(String className) {
|
||||
super(Warning.SEVERE);
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return getClass().toString() + " : " + className;
|
||||
}
|
||||
|
||||
public static InvalidClassFile create(String className) {
|
||||
return new InvalidClassFile(className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up mapping from type name to Module Entry
|
||||
*/
|
||||
protected void loadAllSources(Set<ModuleEntry> sourceModules) {
|
||||
|
||||
for (Iterator<ModuleEntry> it = sourceModules.iterator(); it.hasNext();) {
|
||||
ModuleEntry entry = it.next();
|
||||
String className = entry.getClassName().replace('.', '/');
|
||||
className = className.replace(File.separatorChar, '/');
|
||||
className = "L" + ((className.startsWith("/")) ? className.substring(1) : className);
|
||||
TypeName T = TypeName.string2TypeName(className);
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("adding to source map: " + T + " -> " + entry.getName());
|
||||
}
|
||||
sourceMap.put(T, entry.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize internal data structures
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void init(Set modules) throws IOException {
|
||||
|
||||
// use tree set to keep things sorted ... for deterministic class loading
|
||||
TreeSet<Module> archives = new TreeSet<Module>(ToStringComparator.instance());
|
||||
for (Iterator i = modules.iterator(); i.hasNext();) {
|
||||
Module M = (Module) i.next();
|
||||
if (DEBUG_LEVEL > 0) {
|
||||
Trace.println("add archive: " + M);
|
||||
}
|
||||
archives.add(M);
|
||||
}
|
||||
Set<ModuleEntry> classModuleEntries = new HashSet<ModuleEntry>();
|
||||
Set<ModuleEntry> sourceModuleEntries = new HashSet<ModuleEntry>();
|
||||
for (Iterator<Module> it = archives.iterator(); it.hasNext();) {
|
||||
Module archive = it.next();
|
||||
Set<ModuleEntry> classFiles = getClassFiles(archive);
|
||||
removeClassFiles(classFiles, classModuleEntries);
|
||||
for (Iterator<ModuleEntry> it2 = classFiles.iterator(); it2.hasNext();) {
|
||||
ModuleEntry file = it2.next();
|
||||
classModuleEntries.add(file);
|
||||
}
|
||||
Set<ModuleEntry> sourceFiles = getSourceFiles(archive);
|
||||
for (Iterator<ModuleEntry> it2 = sourceFiles.iterator(); it2.hasNext();) {
|
||||
ModuleEntry file = it2.next();
|
||||
sourceModuleEntries.add(file);
|
||||
}
|
||||
}
|
||||
loadAllClasses(classModuleEntries);
|
||||
loadAllSources(sourceModuleEntries);
|
||||
}
|
||||
|
||||
public ClassLoaderReference getReference() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
public Iterator<IClass> iterateAllClasses() {
|
||||
return getAllClasses().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* This version returns null instead of throwing ClassNotFoundException.
|
||||
*/
|
||||
private IClass lookupClassInternal(TypeName className) {
|
||||
if (DEBUG_LEVEL > 1) {
|
||||
Trace.println(this + ": lookupClassInternal " + className);
|
||||
}
|
||||
|
||||
// try delegating first.
|
||||
ClassLoaderImpl parent = (ClassLoaderImpl) getParent();
|
||||
if (parent != null) {
|
||||
IClass result = parent.lookupClassInternal(className);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
// delegating failed. Try our own namespace.
|
||||
return loadedClasses.get(className);
|
||||
}
|
||||
|
||||
public IClass lookupClass(TypeName className) {
|
||||
if (DEBUG_LEVEL > 1) {
|
||||
Trace.println(this + ": lookupClass " + className);
|
||||
}
|
||||
|
||||
// treat arrays specially:
|
||||
if (className.isArrayType()) {
|
||||
return arrayClassLoader.lookupClass(className, this);
|
||||
}
|
||||
|
||||
// try delegating first.
|
||||
ClassLoaderImpl parent = (ClassLoaderImpl) getParent();
|
||||
if (parent != null) {
|
||||
IClass result = parent.lookupClassInternal(className);
|
||||
if (result != null) {
|
||||
if (DEBUG_LEVEL > 1) {
|
||||
Trace.println(this + ": returning class from parent: " + result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// delegating failed. Try our own namespace.
|
||||
IClass result = loadedClasses.get(className);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getParent.
|
||||
*/
|
||||
public IClassLoader getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public Atom getName() {
|
||||
return loader.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return getName().toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClassLoader#getNumberOfClasses()
|
||||
*/
|
||||
public int getNumberOfClasses() {
|
||||
return getAllClasses().size();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClassLoader#getNumberOfMethods()
|
||||
*/
|
||||
public int getNumberOfMethods() {
|
||||
int result = 0;
|
||||
for (Iterator<IClass> it = iterateAllClasses(); it.hasNext();) {
|
||||
IClass klass = it.next();
|
||||
for (Iterator i2 = klass.getDeclaredMethods(); i2.hasNext();) {
|
||||
i2.next();
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClassLoader#getSourceFileName(com.ibm.wala.classLoader.IClass)
|
||||
*/
|
||||
public String getSourceFileName(IClass klass) {
|
||||
return sourceMap.get(klass.getName());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClassLoader#removeAll(java.util.Collection)
|
||||
*/
|
||||
public void removeAll(Collection<IClass> toRemove) {
|
||||
for (Iterator<IClass> it = toRemove.iterator(); it.hasNext();) {
|
||||
IClass klass = it.next();
|
||||
loadedClasses.remove(klass.getName());
|
||||
sourceMap.remove(klass.getName());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,365 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
|
||||
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
|
||||
import com.ibm.wala.ssa.SSACheckCastInstruction;
|
||||
import com.ibm.wala.ssa.SSAGetCaughtExceptionInstruction;
|
||||
import com.ibm.wala.ssa.SSAGetInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSANewInstruction;
|
||||
import com.ibm.wala.ssa.SSAOptions;
|
||||
import com.ibm.wala.ssa.SSAPutInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction.Visitor;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* This class can scan an IMethod and generate a list of call sites in the
|
||||
* method.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class CodeScanner {
|
||||
|
||||
/**
|
||||
* @return iterator of call site references.
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public static Iterator<CallSiteReference> iterateCallSites(IMethod m, WarningSet warnings) throws InvalidClassFileException {
|
||||
if (m.isSynthetic()) {
|
||||
SyntheticMethod sm = (SyntheticMethod) m;
|
||||
return getCallSites(sm.getStatements(SSAOptions.defaultOptions(), warnings)).iterator();
|
||||
} else {
|
||||
return getCallSitesFromShrikeBT((ShrikeCTMethodWrapper) m);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterator of FieldReference
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public static Iterator iterateFieldsRead(IMethod m, WarningSet warnings) throws InvalidClassFileException {
|
||||
if (m.isSynthetic()) {
|
||||
SyntheticMethod sm = (SyntheticMethod) m;
|
||||
return getFieldsRead(sm.getStatements(SSAOptions.defaultOptions(), warnings)).iterator();
|
||||
} else {
|
||||
return getFieldsReadFromShrikeBT((ShrikeCTMethodWrapper) m).iterator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterator of FieldReference
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public static Iterator iterateFieldsWritten(IMethod m, WarningSet warnings) throws InvalidClassFileException {
|
||||
if (m.isSynthetic()) {
|
||||
SyntheticMethod sm = (SyntheticMethod) m;
|
||||
return getFieldsWritten(sm.getStatements(SSAOptions.defaultOptions(), warnings)).iterator();
|
||||
} else {
|
||||
return getFieldsWrittenFromShrikeBT((ShrikeCTMethodWrapper) m).iterator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterator of TypeReference.
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public static Iterator<NewSiteReference> iterateNewSites(IMethod m, WarningSet warnings) throws InvalidClassFileException {
|
||||
if (m.isSynthetic()) {
|
||||
SyntheticMethod sm = (SyntheticMethod) m;
|
||||
return getNewSites(sm.getStatements(SSAOptions.defaultOptions(), warnings)).iterator();
|
||||
} else {
|
||||
return getNewSitesFromShrikeBT((ShrikeCTMethodWrapper) m);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasObjectArrayLoad(IMethod m, WarningSet warnings) throws InvalidClassFileException {
|
||||
if (m.isSynthetic()) {
|
||||
SyntheticMethod sm = (SyntheticMethod) m;
|
||||
return hasObjectArrayLoad(sm.getStatements(SSAOptions.defaultOptions(), warnings));
|
||||
} else {
|
||||
return hasShrikeBTObjectArrayLoad((ShrikeCTMethodWrapper) m);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasObjectArrayStore(IMethod m, WarningSet warnings) throws InvalidClassFileException {
|
||||
if (m.isSynthetic()) {
|
||||
SyntheticMethod sm = (SyntheticMethod) m;
|
||||
return hasObjectArrayStore(sm.getStatements(SSAOptions.defaultOptions(), warnings));
|
||||
} else {
|
||||
return hasShrikeBTObjectArrayStore((ShrikeCTMethodWrapper) m);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set getCaughtExceptions(IMethod m, WarningSet warnings) throws InvalidClassFileException {
|
||||
if (m.isSynthetic()) {
|
||||
SyntheticMethod sm = (SyntheticMethod) m;
|
||||
return getCaughtExceptions(sm.getStatements(SSAOptions.defaultOptions(), warnings));
|
||||
} else {
|
||||
return getShrikeBTCaughtExceptions((ShrikeCTMethodWrapper) m);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the types this method may cast to
|
||||
*
|
||||
* @return iterator of TypeReference
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public static Iterator iterateCastTypes(IMethod m, WarningSet warnings) throws InvalidClassFileException {
|
||||
if (m.isSynthetic()) {
|
||||
SyntheticMethod sm = (SyntheticMethod) m;
|
||||
return iterateCastTypes(sm.getStatements(SSAOptions.defaultOptions(), warnings));
|
||||
} else {
|
||||
return iterateShrikeBTCastTypes((ShrikeCTMethodWrapper) m);
|
||||
}
|
||||
}
|
||||
|
||||
private static Iterator iterateShrikeBTCastTypes(ShrikeCTMethodWrapper wrapper) throws InvalidClassFileException {
|
||||
return wrapper.getCastTypes();
|
||||
}
|
||||
|
||||
private static Set getShrikeBTCaughtExceptions(ShrikeCTMethodWrapper method) throws InvalidClassFileException {
|
||||
return method.getCaughtExceptionTypes();
|
||||
}
|
||||
|
||||
private static boolean hasShrikeBTObjectArrayStore(ShrikeCTMethodWrapper M) throws InvalidClassFileException {
|
||||
for (Iterator it = M.getArraysWritten(); it.hasNext();) {
|
||||
TypeReference t = (TypeReference) it.next();
|
||||
if (t.isReferenceType()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Iterator<CallSiteReference> getCallSitesFromShrikeBT(ShrikeCTMethodWrapper M) throws InvalidClassFileException {
|
||||
return M.getCallSites();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param M
|
||||
* @return Iterator of TypeReference
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
private static Iterator<NewSiteReference> getNewSitesFromShrikeBT(ShrikeCTMethodWrapper M) throws InvalidClassFileException {
|
||||
return M.getNewSites();
|
||||
}
|
||||
|
||||
private static List<FieldReference> getFieldsReadFromShrikeBT(ShrikeCTMethodWrapper M) throws InvalidClassFileException {
|
||||
// TODO move the logic here from ShrikeCTMethodWrapper
|
||||
LinkedList<FieldReference> result = new LinkedList<FieldReference>();
|
||||
for (Iterator<FieldReference> it = M.getFieldsRead(); it.hasNext();) {
|
||||
result.add(it.next());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<FieldReference> getFieldsWrittenFromShrikeBT(ShrikeCTMethodWrapper M) throws InvalidClassFileException {
|
||||
// TODO move the logic here from ShrikeCTMethodWrapper
|
||||
LinkedList<FieldReference> result = new LinkedList<FieldReference>();
|
||||
for (Iterator<FieldReference> it = M.getFieldsWritten(); it.hasNext();) {
|
||||
result.add(it.next());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean hasShrikeBTObjectArrayLoad(ShrikeCTMethodWrapper M) throws InvalidClassFileException {
|
||||
for (Iterator it = M.getArraysRead(); it.hasNext();) {
|
||||
TypeReference t = (TypeReference) it.next();
|
||||
if (t.isReferenceType()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Set <TypeReference>
|
||||
*/
|
||||
public static Set<TypeReference> getCaughtExceptions(SSAInstruction[] statements) {
|
||||
final HashSet<TypeReference> result = HashSetFactory.make(10);
|
||||
Visitor v = new Visitor() {
|
||||
public void visitGetCaughtException(SSAGetCaughtExceptionInstruction instruction) {
|
||||
Collection<TypeReference> t = instruction.getExceptionTypes();
|
||||
result.addAll(t);
|
||||
}
|
||||
};
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
SSAInstruction s = statements[i];
|
||||
if (s != null) {
|
||||
s.visit(v);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public static Iterator<TypeReference> iterateCastTypes(SSAInstruction[] statements) {
|
||||
final HashSet<TypeReference> result = HashSetFactory.make(10);
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
if (statements[i] != null) {
|
||||
if (statements[i] instanceof SSACheckCastInstruction) {
|
||||
SSACheckCastInstruction c = (SSACheckCastInstruction) statements[i];
|
||||
result.add(c.getDeclaredResultType());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param statements
|
||||
* list of ssa statements
|
||||
* @return List of InvokeInstruction
|
||||
*/
|
||||
private static List<CallSiteReference> getCallSites(SSAInstruction[] statements) {
|
||||
final List<CallSiteReference> result = new LinkedList<CallSiteReference>();
|
||||
Visitor v = new Visitor() {
|
||||
public void visitInvoke(SSAInvokeInstruction instruction) {
|
||||
result.add(instruction.getCallSite());
|
||||
}
|
||||
};
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
SSAInstruction s = statements[i];
|
||||
if (s != null) {
|
||||
s.visit(v);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param statements
|
||||
* list of ssa statements
|
||||
* @return List of InvokeInstruction
|
||||
*/
|
||||
private static List<NewSiteReference> getNewSites(SSAInstruction[] statements) {
|
||||
final List<NewSiteReference> result = new LinkedList<NewSiteReference>();
|
||||
Visitor v = new Visitor() {
|
||||
public void visitNew(SSANewInstruction instruction) {
|
||||
result.add(instruction.getNewSite());
|
||||
}
|
||||
};
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
SSAInstruction s = statements[i];
|
||||
if (s != null) {
|
||||
s.visit(v);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param statements
|
||||
* list of ssa statements
|
||||
* @return List of FieldReference
|
||||
*/
|
||||
public static List<FieldReference> getFieldsRead(SSAInstruction[] statements) {
|
||||
final List<FieldReference> result = new LinkedList<FieldReference>();
|
||||
Visitor v = new Visitor() {
|
||||
public void visitGet(SSAGetInstruction instruction) {
|
||||
result.add(instruction.getDeclaredField());
|
||||
}
|
||||
};
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
SSAInstruction s = statements[i];
|
||||
if (s != null) {
|
||||
s.visit(v);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param statements
|
||||
* list of ssa statements
|
||||
* @return List of FieldReference
|
||||
*/
|
||||
public static List<FieldReference> getFieldsWritten(SSAInstruction[] statements) {
|
||||
final List<FieldReference> result = new LinkedList<FieldReference>();
|
||||
Visitor v = new Visitor() {
|
||||
public void visitPut(SSAPutInstruction instruction) {
|
||||
result.add(instruction.getDeclaredField());
|
||||
}
|
||||
};
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
SSAInstruction s = statements[i];
|
||||
if (s != null) {
|
||||
s.visit(v);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean hasObjectArrayLoad(SSAInstruction[] statements) {
|
||||
|
||||
class ScanVisitor extends Visitor {
|
||||
boolean foundOne = false;
|
||||
|
||||
public void visitArrayLoad(SSAArrayLoadInstruction instruction) {
|
||||
if (!instruction.typeIsPrimitive()) {
|
||||
foundOne = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ScanVisitor v = new ScanVisitor();
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
SSAInstruction s = statements[i];
|
||||
if (s != null) {
|
||||
s.visit(v);
|
||||
}
|
||||
if (v.foundOne) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasObjectArrayStore(SSAInstruction[] statements) {
|
||||
|
||||
class ScanVisitor extends Visitor {
|
||||
boolean foundOne = false;
|
||||
|
||||
public void visitArrayStore(SSAArrayStoreInstruction instruction) {
|
||||
if (!instruction.typeIsPrimitive()) {
|
||||
foundOne = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ScanVisitor v = new ScanVisitor();
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
SSAInstruction s = statements[i];
|
||||
if (s != null) {
|
||||
s.visit(v);
|
||||
}
|
||||
if (v.foundOne) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class DirectoryTreeModule implements Module {
|
||||
|
||||
protected final File root;
|
||||
|
||||
DirectoryTreeModule(File root) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
protected abstract FileModule makeFile(File file);
|
||||
|
||||
protected abstract boolean includeFile(File file);
|
||||
|
||||
private Set<ModuleEntry> getEntriesRecursive(File dir) {
|
||||
Set<ModuleEntry> result = new HashSet<ModuleEntry>();
|
||||
File[] files = dir.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (files[i].isDirectory())
|
||||
result.addAll(getEntriesRecursive(files[i]));
|
||||
else if (includeFile(files[i]))
|
||||
result.add(makeFile(files[i]));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Iterator<ModuleEntry> getEntries() {
|
||||
return getEntriesRecursive(root).iterator();
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return root.getAbsolutePath();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.shrikeCT.ClassConstants;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.Atom;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* Implementation of a canonical field reference. TODO: canonicalize these?
|
||||
* TODO: don't cache fieldType here .. move to class?
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public final class FieldImpl implements IField {
|
||||
|
||||
private final IClass declaringClass;
|
||||
private final FieldReference fieldRef;
|
||||
private final int accessFlags;
|
||||
|
||||
/**
|
||||
* constructor when the field type is not a primitive
|
||||
*/
|
||||
public FieldImpl(IClass declaringClass, FieldReference canonicalRef,int accessFlags) {
|
||||
this.declaringClass = declaringClass;
|
||||
this.fieldRef = canonicalRef;
|
||||
this.accessFlags = accessFlags;
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(declaringClass != null);
|
||||
Assertions._assert(fieldRef != null);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMember#getDeclaringClass()
|
||||
*/
|
||||
public IClass getDeclaringClass() {
|
||||
return declaringClass;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
// instanceof is OK because this class is final
|
||||
if (obj instanceof FieldImpl) {
|
||||
FieldImpl other = (FieldImpl) obj;
|
||||
return fieldRef.equals(other.fieldRef) && declaringClass.equals(other.declaringClass);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return 87049 * declaringClass.hashCode() + fieldRef.hashCode();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
FieldReference fr = getFieldReference();
|
||||
return fr.toString();
|
||||
}
|
||||
|
||||
public FieldReference getFieldReference() {
|
||||
return FieldReference.findOrCreate(getDeclaringClass().getReference(), getName(), getFieldTypeReference());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMember#getName()
|
||||
*/
|
||||
public Atom getName() {
|
||||
return fieldRef.getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IField#getFieldTypeReference()
|
||||
*/
|
||||
public TypeReference getFieldTypeReference() {
|
||||
return fieldRef.getFieldType();
|
||||
}
|
||||
|
||||
public boolean isStatic() {
|
||||
return ((accessFlags & ClassConstants.ACC_STATIC) != 0);
|
||||
}
|
||||
|
||||
|
||||
public boolean isFinal() {
|
||||
return ((accessFlags & ClassConstants.ACC_FINAL) != 0);
|
||||
}
|
||||
|
||||
public boolean isPrivate() {
|
||||
return ((accessFlags & ClassConstants.ACC_PRIVATE) != 0);
|
||||
}
|
||||
|
||||
public boolean isProtected() {
|
||||
return ((accessFlags & ClassConstants.ACC_PROTECTED) != 0);
|
||||
}
|
||||
|
||||
public boolean isPublic() {
|
||||
return ((accessFlags & ClassConstants.ACC_PUBLIC) != 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.util.collections.NonNullSingletonIterator;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* A module which is a wrapper around a file in the filesystem
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public abstract class FileModule implements Module, ModuleEntry {
|
||||
|
||||
private final File file;
|
||||
|
||||
public FileModule(File f) {
|
||||
this.file = f;
|
||||
}
|
||||
|
||||
public String getAbsolutePath() {
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.Module#getEntries()
|
||||
*/
|
||||
public Iterator<ModuleEntry> getEntries() {
|
||||
return new NonNullSingletonIterator<ModuleEntry>(this);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return file.hashCode();
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.FileModule#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o.getClass().equals(getClass())) {
|
||||
FileModule other = (FileModule)o;
|
||||
return getName().equals(other.getName());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getInputStream()
|
||||
*/
|
||||
public InputStream getInputStream() {
|
||||
try {
|
||||
return new FileInputStream(file);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE("could not read " + file);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isModuleFile()
|
||||
*/
|
||||
public boolean isModuleFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#asModule()
|
||||
*/
|
||||
public Module asModule() {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* @return Returns the file.
|
||||
*/
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.Atom;
|
||||
|
||||
/**
|
||||
*
|
||||
* Basic interface for an object that represents a single Java class
|
||||
* for analysis purposes, including array classes.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public interface IClass {
|
||||
|
||||
/**
|
||||
* Return the object that represents the defining class loader
|
||||
* for this class.
|
||||
* @return the object that represents the defining class loader
|
||||
* for this class.
|
||||
*/
|
||||
IClassLoader getClassLoader();
|
||||
|
||||
/**
|
||||
* Is this class a Java interface?
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isInterface();
|
||||
|
||||
/**
|
||||
* @return true iff this class is abstract
|
||||
*/
|
||||
boolean isAbstract();
|
||||
|
||||
/**
|
||||
* Return the integer that encodes the class's modifiers,
|
||||
* as defined by the JVM specification
|
||||
* @return the integer that encodes the class's modifiers,
|
||||
* as defined by the JVM specification
|
||||
*/
|
||||
int getModifiers();
|
||||
|
||||
/**
|
||||
* @return the superclass, or null if java.lang.Object
|
||||
*/
|
||||
IClass getSuperclass() throws ClassHierarchyException;
|
||||
|
||||
/**
|
||||
* @return Collection of (IClass) interfaces this class directly implements
|
||||
*/
|
||||
Collection<IClass> getDirectInterfaces() throws ClassHierarchyException;
|
||||
|
||||
/**
|
||||
* @return Collection of (IClass) interfaces this class implements, including
|
||||
* all ancestors of interfaces immediately implemented
|
||||
*/
|
||||
Collection<IClass> getAllImplementedInterfaces() throws ClassHierarchyException;
|
||||
|
||||
/**
|
||||
* @return Collection of (IClass) interfaces this class extends, including
|
||||
* transitive ancestors
|
||||
*/
|
||||
Collection<IClass> getAllAncestorInterfaces() throws ClassHierarchyException;
|
||||
|
||||
/**
|
||||
* Finds method matching signature. Delegates to superclass if not
|
||||
* found.
|
||||
*
|
||||
* @param selector a method signature
|
||||
* @return IMethod from this class matching the signature; null
|
||||
* if not found in this class or any superclass.
|
||||
*/
|
||||
IMethod getMethod(Selector selector);
|
||||
|
||||
/**
|
||||
* Finds a field.
|
||||
*/
|
||||
IField getField(Atom name);
|
||||
|
||||
/**
|
||||
* @return canonical TypeReference corresponding to this class
|
||||
*/
|
||||
TypeReference getReference();
|
||||
|
||||
/**
|
||||
* @return String holding the name of the source file that defined
|
||||
* this class, or null if none found
|
||||
*/
|
||||
String getSourceFileName();
|
||||
|
||||
/**
|
||||
* @return the method that is this class's initializer, or null if none
|
||||
*/
|
||||
IMethod getClassInitializer();
|
||||
|
||||
/**
|
||||
* @return true iff the class is an array class.
|
||||
*/
|
||||
boolean isArrayClass();
|
||||
|
||||
/**
|
||||
* @return an Iterator of the IMethods declared by this class.
|
||||
*/
|
||||
Iterator<IMethod> getDeclaredMethods();
|
||||
|
||||
/**
|
||||
* Compute the instance fields declared by this class or any of
|
||||
* its superclasses.
|
||||
*
|
||||
* @return Collection of IFields
|
||||
* @throws ClassHierarchyException
|
||||
*/
|
||||
Collection<IField> getAllInstanceFields() throws ClassHierarchyException;
|
||||
|
||||
/**
|
||||
* Compute the static fields declared by this class or any of
|
||||
* its superclasses.
|
||||
*
|
||||
* @return Collection of IFields
|
||||
* @throws ClassHierarchyException
|
||||
*/
|
||||
Collection<IField> getAllStaticFields() throws ClassHierarchyException;
|
||||
|
||||
/**
|
||||
* Compute the instance and static fields declared by this class or
|
||||
* any of its superclasses.
|
||||
*
|
||||
* @return Collection of IFields
|
||||
* @throws ClassHierarchyException
|
||||
*/
|
||||
Collection<IField> getAllFields() throws ClassHierarchyException;
|
||||
|
||||
/**
|
||||
* Compute the methods declared by this class or
|
||||
* any of its superclasses.
|
||||
*
|
||||
* @return Collection of IMethods
|
||||
* @throws ClassHierarchyException
|
||||
*/
|
||||
Collection getAllMethods() throws ClassHierarchyException;
|
||||
|
||||
/**
|
||||
* Compute the instance fields declared by this class.
|
||||
*
|
||||
* @return Collection of IFields
|
||||
*/
|
||||
Collection<IField> getDeclaredInstanceFields();
|
||||
|
||||
/**
|
||||
* @return Collection of IField
|
||||
*/
|
||||
Collection<IField> getDeclaredStaticFields();
|
||||
|
||||
/**
|
||||
* @return the TypeName for this class
|
||||
*/
|
||||
TypeName getName();
|
||||
|
||||
/**
|
||||
* Does 'this' refer to a reference type? If not, then it refers
|
||||
* to a primitive type.
|
||||
*/
|
||||
boolean isReferenceType();
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.util.Atom;
|
||||
|
||||
/**
|
||||
*
|
||||
* Base class for an object that represents a single
|
||||
* Java classloader for analysis purposes.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public interface IClassLoader {
|
||||
/**
|
||||
* Find and return the IClass defined by this class loader that
|
||||
* corresponds to the given class name.
|
||||
*
|
||||
* @param className name of the class
|
||||
* @return the IClass defined by this class loader that
|
||||
* corresponds to the given class name, or null if not found.
|
||||
*/
|
||||
public abstract IClass lookupClass(TypeName className);
|
||||
|
||||
/**
|
||||
* Return the ClassLoaderReference for this class loader.
|
||||
* @return ClassLoaderReference
|
||||
*/
|
||||
public abstract ClassLoaderReference getReference();
|
||||
|
||||
/**
|
||||
* @return an Iterator of all classees loaded by this loader
|
||||
*/
|
||||
public abstract Iterator<IClass> iterateAllClasses();
|
||||
|
||||
/**
|
||||
* @return the number of classes in scope to be loaded by this loader
|
||||
*/
|
||||
public abstract int getNumberOfClasses();
|
||||
|
||||
/**
|
||||
* @return the unique name that identifies this class loader.
|
||||
*/
|
||||
Atom getName();
|
||||
|
||||
public abstract int getNumberOfMethods();
|
||||
|
||||
/**
|
||||
* @param klass
|
||||
* @return name of source file corresponding to the class
|
||||
*/
|
||||
public abstract String getSourceFileName(IClass klass);
|
||||
|
||||
/**
|
||||
* @return the parent IClassLoader, if any, or null
|
||||
*/
|
||||
public abstract IClassLoader getParent();
|
||||
|
||||
public abstract void init(Set modules) throws IOException;
|
||||
|
||||
/**
|
||||
* blow away references to any classes in the set
|
||||
* @param toRemove Collection<IClass>
|
||||
*/
|
||||
public abstract void removeAll(Collection<IClass> toRemove);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
*/
|
||||
public interface IField extends IMember {
|
||||
|
||||
/**
|
||||
* @return the type of the declared type of the field
|
||||
*/
|
||||
public TypeReference getFieldTypeReference();
|
||||
|
||||
/**
|
||||
* @return FieldReference representing this field
|
||||
*/
|
||||
public FieldReference getFieldReference();
|
||||
|
||||
/**
|
||||
* Is this field final?
|
||||
*/
|
||||
public boolean isFinal();
|
||||
|
||||
public boolean isPrivate();
|
||||
public boolean isProtected();
|
||||
public boolean isPublic();
|
||||
public boolean isStatic();
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.util.Atom;
|
||||
|
||||
/**
|
||||
*
|
||||
* Basic interface for an object that represents a single
|
||||
* Java member (method or field) for analysis purposes.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public interface IMember {
|
||||
|
||||
/**
|
||||
* Return the object that represents the declaring class
|
||||
* for this member.
|
||||
* @return the object that represents the declaring class
|
||||
* for this member.
|
||||
*/
|
||||
IClass getDeclaringClass();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the name of this member
|
||||
*/
|
||||
Atom getName();
|
||||
|
||||
/**
|
||||
* Is this method static?
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isStatic();
|
||||
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.ContextItem;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* Basic interface for an object that represents a single Java method for
|
||||
* analysis purposes.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public interface IMethod extends IMember, ContextItem {
|
||||
|
||||
/**
|
||||
* Is this method synchronized?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isSynchronized();
|
||||
|
||||
/**
|
||||
* Is this method a class initializer?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isClinit();
|
||||
|
||||
/**
|
||||
* Is this method an object initializer?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isInit();
|
||||
|
||||
/**
|
||||
* Is this method native?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isNative();
|
||||
|
||||
/**
|
||||
* Did someone synthesize this method? (As opposed to reading it from a class
|
||||
* file)
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isSynthetic();
|
||||
|
||||
/**
|
||||
* Is this method abstract?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isAbstract();
|
||||
|
||||
/**
|
||||
* Is this method private?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isPrivate();
|
||||
|
||||
/**
|
||||
* Is this method protected?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isProtected();
|
||||
|
||||
/**
|
||||
* Is this method public?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isPublic();
|
||||
|
||||
/**
|
||||
* Is this method final?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isFinal();
|
||||
|
||||
/**
|
||||
* @return canonical MethodReference corresponding to this method
|
||||
*/
|
||||
MethodReference getReference();
|
||||
|
||||
/**
|
||||
* @return maximum number of JVM locals used by this method
|
||||
*/
|
||||
int getMaxLocals();
|
||||
|
||||
/**
|
||||
* @return maximum height of JVM stack used by this method
|
||||
*/
|
||||
int getMaxStackHeight();
|
||||
|
||||
/**
|
||||
* @return true iff this method has at least one exception handler
|
||||
*/
|
||||
boolean hasExceptionHandler();
|
||||
|
||||
/**
|
||||
* Method getParameterType. By convention, for a non-static method,
|
||||
* getParameterType(0) is the this pointer
|
||||
*/
|
||||
TypeReference getParameterType(int i);
|
||||
|
||||
/**
|
||||
* @return the name of the return type for this method
|
||||
*/
|
||||
TypeReference getReturnType();
|
||||
|
||||
/**
|
||||
* Method getNumberOfParameters. This result includes the "this" pointer if
|
||||
* applicable
|
||||
*/
|
||||
int getNumberOfParameters();
|
||||
|
||||
/**
|
||||
* @return an array of the exception types declared by the throws clause for
|
||||
* this method, or null if there are none
|
||||
*/
|
||||
TypeReference[] getDeclaredExceptions();
|
||||
|
||||
/**
|
||||
* @return the source line number corresponding to a particular bytecode
|
||||
* index, or -1 if the information is not available.
|
||||
*/
|
||||
int getLineNumber(int bcIndex);
|
||||
|
||||
/**
|
||||
* @return the (source code) name of the local variable of a given number at
|
||||
* the specified program counter, or null if the information is not
|
||||
* available.
|
||||
*/
|
||||
String getLocalVariableName(int bcIndex, int localNumber);
|
||||
|
||||
/**
|
||||
* Method getSignature. something like:
|
||||
* com.foo.bar.createLargeOrder(IILjava.lang.String;SLjava.sql.Date;)Ljava.lang.Integer;
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getSignature();
|
||||
|
||||
/**
|
||||
* Method getSignature. something like:
|
||||
* createLargeOrder(IILjava.lang.String;SLjava.sql.Date;)Ljava.lang.Integer;
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public Selector getSelector();
|
||||
|
||||
/**
|
||||
* Method getDescriptor. something like:
|
||||
* (IILjava.lang.String;SLjava.sql.Date;)Ljava.lang.Integer;
|
||||
*
|
||||
* @return Descriptor
|
||||
*/
|
||||
Descriptor getDescriptor();
|
||||
|
||||
/**
|
||||
* @return true iff the local variable table information for this method is
|
||||
* available
|
||||
*/
|
||||
boolean hasLocalVariableTable();
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
/**
|
||||
*
|
||||
* An interface for something that carries a location in bytecode
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public interface IProgramCounter {
|
||||
/**
|
||||
* A constant indicating no source line number information is available.
|
||||
*/
|
||||
public static final int NO_SOURCE_LINE_NUMBER = -1;
|
||||
|
||||
/**
|
||||
* Return the program counter (index into the method's bytecode)
|
||||
* for this call site.
|
||||
* @return the program counter (index into the method's bytecode)
|
||||
* for this call site.
|
||||
*
|
||||
*/
|
||||
public abstract int getProgramCounter();
|
||||
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.io.FileSuffixes;
|
||||
|
||||
/**
|
||||
*
|
||||
* An entry in a Jar file.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class JarFileEntry implements ModuleEntry {
|
||||
|
||||
private final String entryName;
|
||||
private final JarFileModule jarFileModule;
|
||||
private final JarFile jarFile;
|
||||
JarFileEntry(String entryName, JarFileModule jarFile) {
|
||||
this.entryName = entryName;
|
||||
this.jarFileModule = jarFile;
|
||||
this.jarFile = jarFile.getJarFile();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return entryName;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isClassFile()
|
||||
*/
|
||||
public boolean isClassFile() {
|
||||
return FileSuffixes.isClassFile(getName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getInputStream()
|
||||
*/
|
||||
public InputStream getInputStream() {
|
||||
try {
|
||||
return jarFile.getInputStream(jarFile.getEntry(entryName));
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getSize()
|
||||
*/
|
||||
public long getSize() {
|
||||
// TODO: cache this?
|
||||
return jarFile.getEntry(entryName).getSize();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
// TODO Auto-generated method stub
|
||||
return jarFile.getName() + ":" + getName();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isModuleFile()
|
||||
*/
|
||||
public boolean isModuleFile() {
|
||||
return FileSuffixes.isJarFile(getName()) || FileSuffixes.isWarFile(getName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#asModule()
|
||||
*/
|
||||
public Module asModule() {
|
||||
return new NestedJarFileModule(jarFileModule,jarFile.getEntry(entryName));
|
||||
}
|
||||
|
||||
public JarFile getJarFile() {
|
||||
return jarFile;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return entryName.hashCode() * 5059 + jarFile.hashCode();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getClassName()
|
||||
*/
|
||||
public String getClassName() {
|
||||
return FileSuffixes.stripSuffix(getName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isSourceFile()
|
||||
*/
|
||||
public boolean isSourceFile() {
|
||||
return FileSuffixes.isSourceFile(getName());
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
return this == obj;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import com.ibm.wala.util.CacheReference;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* A module which is a wrapper around a Jar file
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class JarFileModule implements Module {
|
||||
|
||||
private final JarFile file;
|
||||
|
||||
/**
|
||||
* For efficiency, try to cache the byte[] holding each ZipEntries contents;
|
||||
* this will help avoid multiple unzipping
|
||||
*/
|
||||
private final HashMap<ZipEntry, Object> cache = HashMapFactory.make();
|
||||
|
||||
public JarFileModule(JarFile f) {
|
||||
this.file = f;
|
||||
}
|
||||
|
||||
public String getAbsolutePath() {
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "JarFileModule:" + file.getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.Module#getEntries()
|
||||
*/
|
||||
public Iterator<ModuleEntry> getEntries() {
|
||||
HashSet<ModuleEntry> result = HashSetFactory.make();
|
||||
for (Enumeration e = file.entries(); e.hasMoreElements();) {
|
||||
ZipEntry Z = (ZipEntry) e.nextElement();
|
||||
result.add(new JarFileEntry(Z.getName(), this));
|
||||
}
|
||||
return result.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return file.hashCode();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object arg0) {
|
||||
if (getClass().equals(arg0.getClass())) {
|
||||
JarFileModule other = (JarFileModule) arg0;
|
||||
return file.equals(other.file);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getContents(ZipEntry entry) {
|
||||
byte[] b = (byte[]) CacheReference.get(cache.get(entry));
|
||||
|
||||
if (b != null) {
|
||||
return b;
|
||||
}
|
||||
|
||||
try {
|
||||
InputStream s = file.getInputStream(entry);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
b = new byte[1024];
|
||||
int n = s.read(b);
|
||||
while (n != -1) {
|
||||
out.write(b, 0, n);
|
||||
n = s.read(b);
|
||||
}
|
||||
byte[] bb = out.toByteArray();
|
||||
cache.put(entry, CacheReference.make(bb));
|
||||
s.close();
|
||||
return bb;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public JarFile getJarFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
*
|
||||
* A Module represents a set of files to analyze. eg., a Jar file.
|
||||
* These are persistent (hung onto by ClassLoaderReference) .. so,
|
||||
* a Module should not hold onto a lot of data.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public interface Module {
|
||||
|
||||
/**
|
||||
* @return an Iterator of the ModuleEntries in this Module.
|
||||
*/
|
||||
Iterator<ModuleEntry> getEntries();
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* A ModuleEntry represents a wrapper around a file representation
|
||||
* in a Module.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public interface ModuleEntry {
|
||||
|
||||
/**
|
||||
* @return a String that represents the name of the file described
|
||||
* by this object
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* @return true if the file is a class file.
|
||||
*/
|
||||
boolean isClassFile();
|
||||
|
||||
/**
|
||||
* @return true if the file is a source file.
|
||||
*/
|
||||
boolean isSourceFile();
|
||||
|
||||
InputStream getInputStream();
|
||||
|
||||
/**
|
||||
* @return true iff this module entry (file) represents a module in its own right.
|
||||
* e.g., a jar file which is an entry in another jar file.
|
||||
*/
|
||||
boolean isModuleFile();
|
||||
|
||||
/**
|
||||
* Precondition: isModuleFile().
|
||||
* @return a Module view of this entry.
|
||||
*/
|
||||
Module asModule();
|
||||
|
||||
/**
|
||||
* @return the name of the class represented by this entry
|
||||
* @throws UnsupportedOperationException if !isClassFile() nad !isSourceFile()
|
||||
*/
|
||||
String getClassName();
|
||||
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import com.ibm.wala.shrikeCT.ClassReader;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.util.io.FileSuffixes;
|
||||
|
||||
/**
|
||||
*
|
||||
* A Jar file nested in a parent jar file
|
||||
*
|
||||
* @author sfink
|
||||
*
|
||||
*/
|
||||
public class NestedJarFileModule implements Module {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private final JarFileModule parent;
|
||||
private final ZipEntry entry;
|
||||
|
||||
/**
|
||||
* For efficiency, we cache the byte[] holding each ZipEntry's contents; this
|
||||
* will help avoid multiple unzipping TODO: use a soft reference?
|
||||
*/
|
||||
private HashMap<String, byte[]> cache = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public NestedJarFileModule(JarFileModule parent, ZipEntry entry) {
|
||||
this.parent = parent;
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
public InputStream getInputStream(String name) {
|
||||
populateCache();
|
||||
byte[] b = cache.get(name);
|
||||
return new ByteArrayInputStream(b);
|
||||
}
|
||||
|
||||
private void populateCache() {
|
||||
if (cache != null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
cache = HashMapFactory.make();
|
||||
final byte[] b = parent.getContents(entry);
|
||||
final JarInputStream stream = new JarInputStream(new ByteArrayInputStream(b));
|
||||
for (ZipEntry z = stream.getNextEntry(); z != null; z = stream.getNextEntry()) {
|
||||
if (DEBUG) {
|
||||
Trace.println("got entry: " + z.getName());
|
||||
}
|
||||
if (FileSuffixes.isClassFile(z.getName()) || FileSuffixes.isSourceFile(z.getName())) {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] temp = new byte[1024];
|
||||
int n = stream.read(temp);
|
||||
while (n != -1) {
|
||||
out.write(temp, 0, n);
|
||||
n = stream.read(temp);
|
||||
}
|
||||
|
||||
byte[] bb = out.toByteArray();
|
||||
try {
|
||||
if (FileSuffixes.isClassFile(z.getName())) {
|
||||
// check that we can read without an InvalidClassFileException
|
||||
new ClassReader(bb);
|
||||
}
|
||||
cache.put(z.getName(), bb);
|
||||
} catch (InvalidClassFileException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
protected long getEntrySize(String name) {
|
||||
populateCache();
|
||||
byte[] b = cache.get(name);
|
||||
return b.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.Module#getEntries()
|
||||
*/
|
||||
public Iterator<ModuleEntry> getEntries() {
|
||||
populateCache();
|
||||
final Iterator<String> it = cache.keySet().iterator();
|
||||
return new Iterator<ModuleEntry>() {
|
||||
String next = null;
|
||||
{
|
||||
advance();
|
||||
}
|
||||
|
||||
private void advance() {
|
||||
if (it.hasNext()) {
|
||||
next = it.next();
|
||||
} else {
|
||||
next = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return next != null;
|
||||
}
|
||||
|
||||
public ModuleEntry next() {
|
||||
ModuleEntry result = new Entry(next);
|
||||
advance();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
* an entry in a nested jar file.
|
||||
*/
|
||||
private class Entry implements ModuleEntry {
|
||||
|
||||
private final String name;
|
||||
|
||||
Entry(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isClassFile()
|
||||
*/
|
||||
public boolean isClassFile() {
|
||||
return FileSuffixes.isClassFile(getName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getInputStream()
|
||||
*/
|
||||
public InputStream getInputStream() {
|
||||
return NestedJarFileModule.this.getInputStream(name);
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return NestedJarFileModule.this.getEntrySize(name);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isModuleFile()
|
||||
*/
|
||||
public boolean isModuleFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#asModule()
|
||||
*/
|
||||
public Module asModule() {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "nested entry: " + name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getClassName()
|
||||
*/
|
||||
public String getClassName() {
|
||||
return FileSuffixes.stripSuffix(getName());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isSourceFile()
|
||||
*/
|
||||
public boolean isSourceFile() {
|
||||
return FileSuffixes.isSourceFile(getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "Nested Jar File:" + entry.getName();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents a textual allocation site
|
||||
*
|
||||
* @author dolby
|
||||
*/
|
||||
public class NewSiteReference extends ProgramCounter {
|
||||
|
||||
/**
|
||||
* The type allocated
|
||||
*/
|
||||
private final TypeReference declaredType;
|
||||
|
||||
/**
|
||||
* @param programCounter bytecode index of the allocation site
|
||||
* @param declaredType declared type that is allocated
|
||||
*/
|
||||
public NewSiteReference(int programCounter, TypeReference declaredType) {
|
||||
super(programCounter);
|
||||
this.declaredType = declaredType;
|
||||
}
|
||||
|
||||
public TypeReference getDeclaredType() {
|
||||
return declaredType;
|
||||
}
|
||||
|
||||
public static NewSiteReference make(int programCounter, TypeReference declaredType) {
|
||||
return new NewSiteReference(programCounter, declaredType);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "NEW " + declaredType + "@" + getProgramCounter();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* Simple object that represents a program counter value
|
||||
* (ie., an instruction in the bytecode)
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class ProgramCounter implements IProgramCounter {
|
||||
|
||||
/**
|
||||
* Index into bytecode describing this instruction
|
||||
*/
|
||||
private final int programCounter;
|
||||
|
||||
/**
|
||||
* @param programCounter Index into bytecode describing this instruction
|
||||
*/
|
||||
public ProgramCounter(final int programCounter) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(programCounter >= 0);
|
||||
}
|
||||
this.programCounter = programCounter;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the program counter (index into the method's bytecode)
|
||||
* for this call site.
|
||||
* @return the program counter (index into the method's bytecode)
|
||||
* for this call site.
|
||||
*
|
||||
*/
|
||||
public int getProgramCounter() {
|
||||
return programCounter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A Program Counter value is enough to uniquely identify a call site reference
|
||||
* within a method.
|
||||
*
|
||||
* Note: must use these objects with extreme care; this only works if you never
|
||||
* mix ProgramLocations from different methods in the same collection.
|
||||
*
|
||||
* @see java.lang.Object#equals(Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
return
|
||||
(obj instanceof ProgramCounter)
|
||||
&&
|
||||
((ProgramCounter) obj).programCounter == programCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return programCounter;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "PC@" + programCounter;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,925 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.shrikeBT.ArrayLoadInstruction;
|
||||
import com.ibm.wala.shrikeBT.ArrayStoreInstruction;
|
||||
import com.ibm.wala.shrikeBT.BytecodeConstants;
|
||||
import com.ibm.wala.shrikeBT.CheckCastInstruction;
|
||||
import com.ibm.wala.shrikeBT.Constants;
|
||||
import com.ibm.wala.shrikeBT.Decoder;
|
||||
import com.ibm.wala.shrikeBT.ExceptionHandler;
|
||||
import com.ibm.wala.shrikeBT.GetInstruction;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
import com.ibm.wala.shrikeBT.Instruction;
|
||||
import com.ibm.wala.shrikeBT.InvokeInstruction;
|
||||
import com.ibm.wala.shrikeBT.MonitorInstruction;
|
||||
import com.ibm.wala.shrikeBT.NewInstruction;
|
||||
import com.ibm.wala.shrikeBT.PutInstruction;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.Atom;
|
||||
import com.ibm.wala.util.Exceptions;
|
||||
import com.ibm.wala.util.ImmutableByteArray;
|
||||
import com.ibm.wala.util.ShrikeUtil;
|
||||
import com.ibm.wala.util.bytecode.BytecodeStream;
|
||||
import com.ibm.wala.util.collections.EmptyIterator;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* A wrapper around a Shrike object that represents a method
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public abstract class ShrikeBTMethodWrapper implements IMethod, BytecodeConstants {
|
||||
|
||||
/**
|
||||
* Some verbose progress output?
|
||||
*/
|
||||
private final static boolean verbose = false;
|
||||
|
||||
private static int methodsParsed = 0;
|
||||
|
||||
/**
|
||||
* A wrapper around the declaring class.
|
||||
*/
|
||||
protected final IClass declaringClass;
|
||||
|
||||
/**
|
||||
* Canonical reference for this method
|
||||
*/
|
||||
private MethodReference methodReference;
|
||||
|
||||
// break these out to save some space; they're computed lazily.
|
||||
protected static class BytecodeInfo {
|
||||
Decoder decoder;
|
||||
|
||||
CallSiteReference[] callSites;
|
||||
|
||||
FieldReference[] fieldsWritten;
|
||||
|
||||
FieldReference[] fieldsRead;
|
||||
|
||||
NewSiteReference[] newSites;
|
||||
|
||||
TypeReference[] arraysRead;
|
||||
|
||||
TypeReference[] arraysWritten;
|
||||
|
||||
TypeReference[] implicitExceptions;
|
||||
|
||||
TypeReference[] castTypes;
|
||||
|
||||
boolean hasMonitorOp;
|
||||
|
||||
/**
|
||||
* Mapping from instruction index to program counter.
|
||||
*/
|
||||
private int[] pcMap;
|
||||
|
||||
/**
|
||||
* Cached map representing line number information in ShrikeCT format TODO:
|
||||
* do more careful caching than just soft references
|
||||
*/
|
||||
protected int[] lineNumberMap;
|
||||
|
||||
/**
|
||||
* an array mapping bytecode offsets to arrays representing the local
|
||||
* variable maps for each offset; a local variable map is represented as an
|
||||
* array of localVars*2 elements, containing a pair (nameIndex, typeIndex)
|
||||
* for each local variable; a pair (0,0) indicates there is no information
|
||||
* for that local variable at that offset
|
||||
*/
|
||||
protected int[][] localVariableMap;
|
||||
|
||||
/**
|
||||
* Exception types this method might throw. Computed on demand.
|
||||
*/
|
||||
private TypeReference[] exceptionTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache the information about the method statements.
|
||||
*/
|
||||
protected BytecodeInfo bcInfo;
|
||||
|
||||
public ShrikeBTMethodWrapper(IClass klass) {
|
||||
this.declaringClass = klass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the program counter (bytecode index) for a particular Shrike
|
||||
* instruction index.
|
||||
*
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public int getBytecodeIndex(int instructionIndex) throws InvalidClassFileException {
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
return bcInfo.pcMap[instructionIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an Iterator of CallSiteReferences from this method.
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
Iterator<CallSiteReference> getCallSites() throws InvalidClassFileException {
|
||||
if (isNative()) {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
Iterator<CallSiteReference> empty = EmptyIterator.instance();
|
||||
return (bcInfo.callSites == null) ? empty : Arrays.asList(bcInfo.callSites).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an Iterator of NewlSiteReferences from this method.
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
Iterator<NewSiteReference> getNewSites() throws InvalidClassFileException {
|
||||
if (isNative()) {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
Iterator<NewSiteReference> empty = EmptyIterator.instance();
|
||||
return (bcInfo.newSites == null) ? empty : Arrays.asList(bcInfo.newSites).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Set <TypeReference>, the exceptions that statements in this method
|
||||
* may throw,
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public Collection getImplicitExceptionTypes() throws InvalidClassFileException {
|
||||
if (isNative()) {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
return (bcInfo.implicitExceptions == null) ? Arrays.asList(new TypeReference[0]) : Arrays.asList(bcInfo.implicitExceptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method processBytecodes. Do a cheap pass over the bytecodes to collect some
|
||||
* mapping information. Some methods require this as a pre-req to accessing
|
||||
* ShrikeCT information.
|
||||
*
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public void processBytecodes() throws InvalidClassFileException {
|
||||
if (bcInfo != null) {
|
||||
// already done.
|
||||
return;
|
||||
}
|
||||
bcInfo = new BytecodeInfo();
|
||||
bcInfo.exceptionTypes = computeDeclaredExceptions();
|
||||
|
||||
if (isNative()) {
|
||||
return;
|
||||
}
|
||||
if (verbose) {
|
||||
methodsParsed += 1;
|
||||
if (methodsParsed % 100 == 0) {
|
||||
System.out.println(methodsParsed + " methods processed...");
|
||||
}
|
||||
}
|
||||
|
||||
processBytecodesWithShrikeBT();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true iff this method has a monitorenter or monitorexit
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public boolean hasMonitorOp() throws InvalidClassFileException {
|
||||
if (isNative()) {
|
||||
return false;
|
||||
}
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
return bcInfo.hasMonitorOp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Set of FieldReference
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public Iterator<FieldReference> getFieldsWritten() throws InvalidClassFileException {
|
||||
if (isNative()) {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
if (bcInfo.fieldsWritten == null) {
|
||||
return EmptyIterator.instance();
|
||||
} else {
|
||||
List<FieldReference> l = Arrays.asList(bcInfo.fieldsWritten);
|
||||
return l.iterator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator of FieldReference
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public Iterator<FieldReference> getFieldsRead() throws InvalidClassFileException {
|
||||
if (isNative()) {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
if (bcInfo.fieldsRead == null) {
|
||||
return EmptyIterator.instance();
|
||||
} else {
|
||||
List<FieldReference> l = Arrays.asList(bcInfo.fieldsRead);
|
||||
return l.iterator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator of TypeReference
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public Iterator getArraysRead() throws InvalidClassFileException {
|
||||
if (isNative()) {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
|
||||
return (bcInfo.arraysRead == null) ? EmptyIterator.instance() : Arrays.asList(bcInfo.arraysRead).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator of TypeReference
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public Iterator getArraysWritten() throws InvalidClassFileException {
|
||||
if (isNative()) {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
|
||||
return (bcInfo.arraysWritten == null) ? EmptyIterator.instance() : Arrays.asList(bcInfo.arraysWritten).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator of TypeReference
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public Iterator getCastTypes() throws InvalidClassFileException {
|
||||
if (isNative()) {
|
||||
return EmptyIterator.instance();
|
||||
}
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
|
||||
return (bcInfo.castTypes == null) ? EmptyIterator.instance() : Arrays.asList(bcInfo.castTypes).iterator();
|
||||
}
|
||||
|
||||
protected abstract byte[] getBytecodes();
|
||||
|
||||
/**
|
||||
* Method getBytecodeStream.
|
||||
*
|
||||
* @return the bytecode stream for this method, or null if no bytecodes.
|
||||
*/
|
||||
public BytecodeStream getBytecodeStream() {
|
||||
byte[] bytecodes = getBytecodes();
|
||||
if (bytecodes == null) {
|
||||
return null;
|
||||
} else {
|
||||
return new BytecodeStream(this, bytecodes);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String getMethodName() throws InvalidClassFileException;
|
||||
|
||||
protected abstract String getMethodSignature() throws InvalidClassFileException;
|
||||
|
||||
private MethodReference computeMethodReference() {
|
||||
try {
|
||||
Atom name = Atom.findOrCreateUnicodeAtom(getMethodName());
|
||||
ImmutableByteArray desc = ImmutableByteArray.make(getMethodSignature());
|
||||
Descriptor D = Descriptor.findOrCreate(desc);
|
||||
return
|
||||
MethodReference.findOrCreate(declaringClass.getReference(), name, D);
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public MethodReference getReference() {
|
||||
if (methodReference == null) {
|
||||
methodReference = computeMethodReference();
|
||||
}
|
||||
return methodReference;
|
||||
}
|
||||
|
||||
public boolean isClinit() {
|
||||
return getReference().getSelector().equals(MethodReference.clinitSelector);
|
||||
}
|
||||
|
||||
public boolean isInit() {
|
||||
return getReference().getName().equals(MethodReference.initAtom);
|
||||
}
|
||||
|
||||
protected abstract int getModifiers();
|
||||
|
||||
public boolean isNative() {
|
||||
return ((getModifiers() & Constants.ACC_NATIVE) != 0);
|
||||
}
|
||||
|
||||
public boolean isAbstract() {
|
||||
return ((getModifiers() & Constants.ACC_ABSTRACT) != 0);
|
||||
}
|
||||
|
||||
public boolean isPrivate() {
|
||||
return ((getModifiers() & Constants.ACC_PRIVATE) != 0);
|
||||
}
|
||||
|
||||
public boolean isProtected() {
|
||||
return ((getModifiers() & Constants.ACC_PROTECTED) != 0);
|
||||
}
|
||||
|
||||
public boolean isPublic() {
|
||||
return ((getModifiers() & Constants.ACC_PUBLIC) != 0);
|
||||
}
|
||||
|
||||
public boolean isFinal() {
|
||||
return ((getModifiers() & Constants.ACC_FINAL) != 0);
|
||||
}
|
||||
|
||||
public boolean isSynchronized() {
|
||||
return ((getModifiers() & Constants.ACC_SYNCHRONIZED) != 0);
|
||||
}
|
||||
|
||||
public boolean isStatic() {
|
||||
return ((getModifiers() & Constants.ACC_STATIC) != 0);
|
||||
}
|
||||
|
||||
public boolean isSynthetic() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public IClass getDeclaringClass() {
|
||||
return declaringClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the decoder object for this method, or create one if necessary.
|
||||
*
|
||||
* @return null if the method has no code.
|
||||
*/
|
||||
protected abstract Decoder makeDecoder();
|
||||
|
||||
/**
|
||||
* Walk through the bytecodes and collect trivial information.
|
||||
*
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
protected abstract void processDebugInfo(BytecodeInfo bcInfo) throws InvalidClassFileException;
|
||||
|
||||
|
||||
private void processBytecodesWithShrikeBT() throws InvalidClassFileException {
|
||||
bcInfo.decoder = makeDecoder();
|
||||
if (Assertions.verifyAssertions) {
|
||||
if (!isAbstract() && bcInfo.decoder == null) {
|
||||
Assertions.UNREACHABLE("bad method " + getReference());
|
||||
}
|
||||
}
|
||||
if (bcInfo.decoder == null) {
|
||||
return;
|
||||
}
|
||||
bcInfo.pcMap = bcInfo.decoder.getInstructionsToBytecodes();
|
||||
|
||||
processDebugInfo(bcInfo);
|
||||
|
||||
SimpleVisitor simpleVisitor = new SimpleVisitor();
|
||||
|
||||
Instruction[] instructions = bcInfo.decoder.getInstructions();
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
simpleVisitor.setInstructionIndex(i);
|
||||
instructions[i].visit(simpleVisitor);
|
||||
if (Exceptions.isPEI(instructions[i])) {
|
||||
Collection<TypeReference> t = Exceptions.getIndependentExceptionTypes(instructions[i]);
|
||||
simpleVisitor.implicitExceptions.addAll(t);
|
||||
}
|
||||
}
|
||||
|
||||
// copy the Set results into arrays; will use less
|
||||
// storage
|
||||
copyVisitorSetsToArrays(simpleVisitor);
|
||||
}
|
||||
|
||||
private void copyVisitorSetsToArrays(SimpleVisitor simpleVisitor) {
|
||||
bcInfo.newSites = new NewSiteReference[simpleVisitor.newSites.size()];
|
||||
int i = 0;
|
||||
for (Iterator<NewSiteReference> it = simpleVisitor.newSites.iterator(); it.hasNext();) {
|
||||
bcInfo.newSites[i++] = it.next();
|
||||
}
|
||||
|
||||
bcInfo.fieldsRead = new FieldReference[simpleVisitor.fieldsRead.size()];
|
||||
i = 0;
|
||||
for (Iterator<FieldReference> it = simpleVisitor.fieldsRead.iterator(); it.hasNext();) {
|
||||
bcInfo.fieldsRead[i++] = it.next();
|
||||
}
|
||||
|
||||
bcInfo.fieldsRead = new FieldReference[simpleVisitor.fieldsRead.size()];
|
||||
i = 0;
|
||||
for (Iterator<FieldReference> it = simpleVisitor.fieldsRead.iterator(); it.hasNext();) {
|
||||
bcInfo.fieldsRead[i++] = it.next();
|
||||
}
|
||||
|
||||
bcInfo.fieldsWritten = new FieldReference[simpleVisitor.fieldsWritten.size()];
|
||||
i = 0;
|
||||
for (Iterator<FieldReference> it = simpleVisitor.fieldsWritten.iterator(); it.hasNext();) {
|
||||
bcInfo.fieldsWritten[i++] = it.next();
|
||||
}
|
||||
|
||||
bcInfo.callSites = new CallSiteReference[simpleVisitor.callSites.size()];
|
||||
i = 0;
|
||||
for (Iterator<CallSiteReference> it = simpleVisitor.callSites.iterator(); it.hasNext();) {
|
||||
bcInfo.callSites[i++] = it.next();
|
||||
}
|
||||
|
||||
bcInfo.arraysRead = new TypeReference[simpleVisitor.arraysRead.size()];
|
||||
i = 0;
|
||||
for (Iterator<TypeReference> it = simpleVisitor.arraysRead.iterator(); it.hasNext();) {
|
||||
bcInfo.arraysRead[i++] = it.next();
|
||||
}
|
||||
|
||||
bcInfo.arraysWritten = new TypeReference[simpleVisitor.arraysWritten.size()];
|
||||
i = 0;
|
||||
for (Iterator<TypeReference> it = simpleVisitor.arraysWritten.iterator(); it.hasNext();) {
|
||||
bcInfo.arraysWritten[i++] = it.next();
|
||||
}
|
||||
|
||||
bcInfo.implicitExceptions = new TypeReference[simpleVisitor.implicitExceptions.size()];
|
||||
i = 0;
|
||||
for (Iterator it = simpleVisitor.implicitExceptions.iterator(); it.hasNext();) {
|
||||
bcInfo.implicitExceptions[i++] = (TypeReference) it.next();
|
||||
}
|
||||
|
||||
bcInfo.castTypes = new TypeReference[simpleVisitor.castTypes.size()];
|
||||
i = 0;
|
||||
for (Iterator<TypeReference> it = simpleVisitor.castTypes.iterator(); it.hasNext();) {
|
||||
bcInfo.castTypes[i++] = it.next();
|
||||
}
|
||||
|
||||
bcInfo.hasMonitorOp = simpleVisitor.hasMonitorOp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return getReference().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
// instanceof is OK because this class is final.
|
||||
// if (this.getClass().equals(obj.getClass())) {
|
||||
if (obj instanceof ShrikeBTMethodWrapper) {
|
||||
ShrikeBTMethodWrapper that = (ShrikeBTMethodWrapper) obj;
|
||||
return (getDeclaringClass().equals(that.getDeclaringClass()) && getReference().equals(that.getReference()));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return 9661 * getReference().hashCode();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getMaxLocals()
|
||||
*/
|
||||
public abstract int getMaxLocals();
|
||||
|
||||
// TODO: ShrikeBT should have a getMaxStack method on Decoder, I think.
|
||||
public abstract int getMaxStackHeight();
|
||||
|
||||
public Atom getName() {
|
||||
return getReference().getName();
|
||||
}
|
||||
|
||||
public Descriptor getDescriptor() {
|
||||
return getReference().getDescriptor();
|
||||
}
|
||||
|
||||
private class SimpleVisitor extends Instruction.Visitor {
|
||||
|
||||
// TODO: make a better Set implementation for these.
|
||||
Set<CallSiteReference> callSites = HashSetFactory.make(5);
|
||||
|
||||
Set<FieldReference> fieldsWritten = HashSetFactory.make(5);
|
||||
|
||||
Set<FieldReference> fieldsRead = HashSetFactory.make(5);
|
||||
|
||||
Set<NewSiteReference> newSites = HashSetFactory.make(5);
|
||||
|
||||
Set<TypeReference> arraysRead = HashSetFactory.make(5);
|
||||
|
||||
Set<TypeReference> arraysWritten = HashSetFactory.make(5);
|
||||
|
||||
Set<TypeReference> implicitExceptions = HashSetFactory.make(5);
|
||||
|
||||
Set<TypeReference> castTypes = HashSetFactory.make(5);
|
||||
|
||||
boolean hasMonitorOp;
|
||||
|
||||
private int instructionIndex;
|
||||
|
||||
public void setInstructionIndex(int i) {
|
||||
instructionIndex = i;
|
||||
}
|
||||
|
||||
public int getProgramCounter() throws InvalidClassFileException {
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
return bcInfo.pcMap[instructionIndex];
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.shrikeBT.Instruction.Visitor#visitMonitor(com.ibm.wala.shrikeBT.MonitorInstruction)
|
||||
*/
|
||||
public void visitMonitor(MonitorInstruction instruction) {
|
||||
hasMonitorOp = true;
|
||||
}
|
||||
|
||||
public void visitNew(NewInstruction instruction) {
|
||||
ClassLoaderReference loader = getReference().getDeclaringClass().getClassLoader();
|
||||
TypeReference t = ShrikeUtil.makeTypeReference(loader, instruction.getType());
|
||||
try {
|
||||
newSites.add(NewSiteReference.make(getProgramCounter(), t));
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
public void visitGet(GetInstruction instruction) {
|
||||
ClassLoaderReference loader = getReference().getDeclaringClass().getClassLoader();
|
||||
FieldReference f = ShrikeUtil.makeFieldReference(loader, instruction.getClassType(), instruction.getFieldName(), instruction
|
||||
.getFieldType());
|
||||
fieldsRead.add(f);
|
||||
}
|
||||
|
||||
public void visitPut(PutInstruction instruction) {
|
||||
ClassLoaderReference loader = getReference().getDeclaringClass().getClassLoader();
|
||||
FieldReference f = ShrikeUtil.makeFieldReference(loader, instruction.getClassType(), instruction.getFieldName(), instruction
|
||||
.getFieldType());
|
||||
fieldsWritten.add(f);
|
||||
}
|
||||
|
||||
public void visitInvoke(InvokeInstruction instruction) {
|
||||
ClassLoaderReference loader = getReference().getDeclaringClass().getClassLoader();
|
||||
MethodReference m = ShrikeUtil.makeMethodReference(loader, instruction.getClassType(), instruction.getMethodName(),
|
||||
instruction.getMethodSignature());
|
||||
int programCounter = 0;
|
||||
try {
|
||||
programCounter = getProgramCounter();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
CallSiteReference site = null;
|
||||
int nParams = m.getNumberOfParameters();
|
||||
switch (instruction.getInvocationMode()) {
|
||||
case Constants.OP_invokestatic:
|
||||
site = CallSiteReference.make(programCounter, m, IInvokeInstruction.Dispatch.STATIC);
|
||||
break;
|
||||
case Constants.OP_invokeinterface:
|
||||
site = CallSiteReference.make(programCounter, m, IInvokeInstruction.Dispatch.INTERFACE);
|
||||
nParams++;
|
||||
break;
|
||||
case Constants.OP_invokespecial:
|
||||
site = CallSiteReference.make(programCounter, m, IInvokeInstruction.Dispatch.SPECIAL);
|
||||
nParams++;
|
||||
break;
|
||||
case Constants.OP_invokevirtual:
|
||||
site = CallSiteReference.make(programCounter, m, IInvokeInstruction.Dispatch.VIRTUAL);
|
||||
nParams++;
|
||||
break;
|
||||
default:
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
callSites.add(site);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.shrikeBT.Instruction.Visitor#visitArrayLoad(com.ibm.wala.shrikeBT.ArrayLoadInstruction)
|
||||
*/
|
||||
public void visitArrayLoad(ArrayLoadInstruction instruction) {
|
||||
arraysRead.add(ShrikeUtil.makeTypeReference(getDeclaringClass().getClassLoader().getReference(), instruction.getType()));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.shrikeBT.Instruction.Visitor#visitArrayStore(com.ibm.wala.shrikeBT.ArrayStoreInstruction)
|
||||
*/
|
||||
public void visitArrayStore(ArrayStoreInstruction instruction) {
|
||||
arraysWritten.add(ShrikeUtil.makeTypeReference(getDeclaringClass().getClassLoader().getReference(), instruction.getType()));
|
||||
}
|
||||
|
||||
public void visitCheckCast(CheckCastInstruction instruction) {
|
||||
castTypes.add(ShrikeUtil.makeTypeReference(getDeclaringClass().getClassLoader().getReference(), instruction.getType()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getInstructions.
|
||||
*
|
||||
* @return Instruction[]
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public Instruction[] getInstructions() throws InvalidClassFileException {
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
if (bcInfo.decoder == null) {
|
||||
return null;
|
||||
} else {
|
||||
return bcInfo.decoder.getInstructions();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getHandlers.
|
||||
*
|
||||
* @return ExceptionHandler[][]
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public ExceptionHandler[][] getHandlers() throws InvalidClassFileException {
|
||||
if (bcInfo == null) {
|
||||
processBytecodes();
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
if (bcInfo.decoder == null) {
|
||||
return null;
|
||||
} else {
|
||||
return bcInfo.decoder.getHandlers();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getParameterType. By convention, for a non-static method,
|
||||
* getParameterType(0) is the this pointer
|
||||
*
|
||||
* @param i
|
||||
* @return TypeReference
|
||||
*/
|
||||
public TypeReference getParameterType(int i) {
|
||||
if (!isStatic()) {
|
||||
if (i == 0)
|
||||
return declaringClass.getReference();
|
||||
else
|
||||
return getReference().getParameterType(i - 1);
|
||||
} else {
|
||||
return getReference().getParameterType(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getNumberOfParameters. This result includes the "this" pointer if
|
||||
* applicable
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getNumberOfParameters() {
|
||||
if (isStatic() || isClinit()) {
|
||||
return getReference().getNumberOfParameters();
|
||||
} else {
|
||||
return getReference().getNumberOfParameters() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#hasExceptionHandler()
|
||||
*/
|
||||
public abstract boolean hasExceptionHandler();
|
||||
|
||||
/**
|
||||
* Clients should not modify the returned array. TODO: clone to avoid the
|
||||
* problem?
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getDeclaredExceptions()
|
||||
*/
|
||||
public TypeReference[] getDeclaredExceptions() {
|
||||
|
||||
if (bcInfo == null) {
|
||||
try {
|
||||
processBytecodes();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
return (bcInfo.exceptionTypes == null) ? new TypeReference[0] : bcInfo.exceptionTypes;
|
||||
}
|
||||
|
||||
protected abstract String[] getDeclaredExceptionTypeNames() throws InvalidClassFileException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getDeclaredExceptions()
|
||||
*/
|
||||
private TypeReference[] computeDeclaredExceptions() {
|
||||
try {
|
||||
String[] strings = getDeclaredExceptionTypeNames();
|
||||
if (strings == null) return null;
|
||||
|
||||
ClassLoaderReference loader = getDeclaringClass().getClassLoader().getReference();
|
||||
|
||||
TypeReference[] result = new TypeReference[strings.length];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = TypeReference.findOrCreate(loader, TypeName.findOrCreate(ImmutableByteArray.make("L" + strings[i])));
|
||||
}
|
||||
return result;
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getLineNumber(int)
|
||||
*/
|
||||
public int getLineNumber(int bcIndex) {
|
||||
if (bcInfo == null) {
|
||||
try {
|
||||
processBytecodes();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
return (bcInfo.lineNumberMap == null) ? -1 : bcInfo.lineNumberMap[bcIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Set <TypeReference>
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public Set<TypeReference> getCaughtExceptionTypes() throws InvalidClassFileException {
|
||||
|
||||
ExceptionHandler[][] handlers = getHandlers();
|
||||
if (handlers == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
HashSet<TypeReference> result = HashSetFactory.make(10);
|
||||
ClassLoaderReference loader = getReference().getDeclaringClass().getClassLoader();
|
||||
for (int i = 0; i < handlers.length; i++) {
|
||||
for (int j = 0; j < handlers[i].length; j++) {
|
||||
TypeReference t = ShrikeUtil.makeTypeReference(loader, handlers[i][j].getCatchClass());
|
||||
if (t == null) {
|
||||
t = TypeReference.JavaLangThrowable;
|
||||
}
|
||||
result.add(t);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getSignature()
|
||||
*/
|
||||
public String getSignature() {
|
||||
return getReference().getSignature();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getSelector()
|
||||
*/
|
||||
public Selector getSelector() {
|
||||
return getReference().getSelector();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getLocalVariableName(int, int)
|
||||
*/
|
||||
|
||||
public abstract String getLocalVariableName(int bcIndex, int localNumber);
|
||||
|
||||
/*
|
||||
* TODO: cache for efficiency? (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#hasLocalVariableTable()
|
||||
*/
|
||||
public abstract boolean hasLocalVariableTable();
|
||||
|
||||
/**
|
||||
* Clear all optional cached data associated with this class
|
||||
*/
|
||||
public void clearCaches() {
|
||||
bcInfo = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,836 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyWarning;
|
||||
import com.ibm.wala.shrikeBT.Constants;
|
||||
import com.ibm.wala.shrikeCT.ClassConstants;
|
||||
import com.ibm.wala.shrikeCT.ClassReader;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.Atom;
|
||||
import com.ibm.wala.util.ImmutableByteArray;
|
||||
import com.ibm.wala.util.ShrikeClassReaderHandle;
|
||||
import com.ibm.wala.util.collections.BimodalMap;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.collections.SmallMap;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.util.warnings.Warning;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* A wrapper around a java.lang.Class object
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public final class ShrikeCTClassWrapper implements IClass {
|
||||
|
||||
static final boolean DEBUG = false;
|
||||
|
||||
/**
|
||||
* The Shrike object that knows how to read the class file
|
||||
*/
|
||||
private final ShrikeClassReaderHandle reader;
|
||||
|
||||
/**
|
||||
* The object that loaded this class.
|
||||
*/
|
||||
private final IClassLoader loader;
|
||||
|
||||
/**
|
||||
* Governing class hierarchy for this class
|
||||
*/
|
||||
private final ClassHierarchy cha;
|
||||
|
||||
/**
|
||||
* A mapping from Selector to IMethod
|
||||
*
|
||||
* TODO: get rid of this for classes (though keep it for interfaces) instead
|
||||
* ... use a VMT.
|
||||
*/
|
||||
private Map<Selector, IMethod> methodMap;
|
||||
|
||||
/**
|
||||
* A mapping from Selector to IMethod used to cache method lookups from
|
||||
* superclasses
|
||||
*/
|
||||
private Map<Selector, IMethod> inheritCache;
|
||||
|
||||
/**
|
||||
* Canonical type representation
|
||||
*/
|
||||
private TypeReference typeReference;
|
||||
|
||||
/**
|
||||
* An object to track warnings
|
||||
*/
|
||||
private final WarningSet warnings;
|
||||
|
||||
/**
|
||||
* superclass
|
||||
*/
|
||||
private IClass superClass;
|
||||
|
||||
/**
|
||||
* Compute the superclass lazily.
|
||||
*/
|
||||
private boolean superclassComputed = false;
|
||||
|
||||
/**
|
||||
* An Atom which holds the name of the super class. We cache this for
|
||||
* efficiency reasons.
|
||||
*/
|
||||
private ImmutableByteArray superName;
|
||||
|
||||
/**
|
||||
* The names of interfaces for this class. We cache this for efficiency
|
||||
* reasons.
|
||||
*/
|
||||
private ImmutableByteArray[] interfaceNames;
|
||||
|
||||
/**
|
||||
* The IClasses that represent all interfaces this class implements (if it's a
|
||||
* class) or extends (it it's an interface)
|
||||
*/
|
||||
private Collection<IClass> allInterfaces = null;
|
||||
|
||||
/**
|
||||
* The instance fields declared in this class.
|
||||
*/
|
||||
private IField[] instanceFields;
|
||||
|
||||
/**
|
||||
* The static fields declared in this class.
|
||||
*/
|
||||
private IField[] staticFields;
|
||||
|
||||
/**
|
||||
* JVM-level modifiers; cached here for efficiency
|
||||
*/
|
||||
private int modifiers;
|
||||
|
||||
/**
|
||||
* hash code; cached here for efficiency
|
||||
*/
|
||||
private final int hashCode;
|
||||
|
||||
/**
|
||||
* @param reader
|
||||
* @param loader
|
||||
* @param cha
|
||||
* @param warnings
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public ShrikeCTClassWrapper(ShrikeClassReaderHandle reader, IClassLoader loader, ClassHierarchy cha, WarningSet warnings)
|
||||
throws InvalidClassFileException {
|
||||
if (reader == null)
|
||||
throw new NullPointerException();
|
||||
this.reader = reader;
|
||||
this.loader = loader;
|
||||
this.cha = cha;
|
||||
this.warnings = warnings;
|
||||
computeTypeReference();
|
||||
this.hashCode = 2161 * getReference().hashCode();
|
||||
// as long as the reader is around, pull more data out
|
||||
// of it before the soft reference to it disappears
|
||||
computeSuperName();
|
||||
computeModifiers();
|
||||
computeInterfaceNames();
|
||||
computeFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the fields declared by this class
|
||||
*
|
||||
* @throws InvalidClassFileException
|
||||
* iff Shrike fails to read the class file correctly
|
||||
*/
|
||||
private void computeFields() throws InvalidClassFileException {
|
||||
ClassReader cr = reader.get();
|
||||
int fieldCount = cr.getFieldCount();
|
||||
List<FieldImpl> instanceList = new ArrayList<FieldImpl>(fieldCount);
|
||||
List<FieldImpl> staticList = new ArrayList<FieldImpl>(fieldCount);
|
||||
try {
|
||||
for (int i = 0; i < fieldCount; i++) {
|
||||
int accessFlags = cr.getFieldAccessFlags(i);
|
||||
Atom name = Atom.findOrCreateUnicodeAtom(cr.getFieldName(i));
|
||||
ImmutableByteArray b = ImmutableByteArray.make(cr.getFieldType(i));
|
||||
|
||||
if ((accessFlags & ClassConstants.ACC_STATIC) == 0) {
|
||||
addFieldToList(instanceList, name, b, accessFlags);
|
||||
} else {
|
||||
addFieldToList(staticList, name, b, accessFlags);
|
||||
}
|
||||
}
|
||||
instanceFields = new IField[instanceList.size()];
|
||||
populateFieldArrayFromList(instanceList, instanceFields);
|
||||
staticFields = new IField[staticList.size()];
|
||||
populateFieldArrayFromList(staticList, staticFields);
|
||||
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
private void populateFieldArrayFromList(List<FieldImpl> L, IField[] A) {
|
||||
Iterator<FieldImpl> it = L.iterator();
|
||||
for (int i = 0; i < A.length; i++) {
|
||||
A[i] = it.next();
|
||||
}
|
||||
}
|
||||
|
||||
private void addFieldToList(List<FieldImpl> L, Atom name, ImmutableByteArray fieldType, int accessFlags) {
|
||||
TypeName T = null;
|
||||
if (fieldType.get(fieldType.length() - 1) == ';') {
|
||||
T = TypeName.findOrCreate(fieldType, 0, fieldType.length() - 1);
|
||||
} else {
|
||||
T = TypeName.findOrCreate(fieldType);
|
||||
}
|
||||
TypeReference type = TypeReference.findOrCreate(getClassLoader().getReference(), T);
|
||||
FieldReference fr = FieldReference.findOrCreate(getReference(), name, type);
|
||||
FieldImpl f = new FieldImpl(this, fr, accessFlags);
|
||||
L.add(f);
|
||||
}
|
||||
|
||||
public IClassLoader getClassLoader() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
boolean result = ((modifiers & Constants.ACC_INTERFACE) != 0);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#isAbstract()
|
||||
*/
|
||||
public boolean isAbstract() {
|
||||
boolean result = ((modifiers & Constants.ACC_ABSTRACT) != 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
private void computeModifiers() throws InvalidClassFileException {
|
||||
modifiers = reader.get().getAccessFlags();
|
||||
}
|
||||
|
||||
public int getModifiers() {
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that this is called from the constructor, at which point this class is
|
||||
* not yet ready to actually load the superclass. Instead, we pull out the
|
||||
* name of the superclass and cache it here, to avoid hitting the reader
|
||||
* later.
|
||||
*/
|
||||
private void computeSuperName() {
|
||||
try {
|
||||
String s = reader.get().getSuperName();
|
||||
if (s != null) {
|
||||
superName = ImmutableByteArray.make("L" + s);
|
||||
}
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
private void computeSuperclass() {
|
||||
superclassComputed = true;
|
||||
|
||||
if (superName == null) {
|
||||
if (!getReference().equals(TypeReference.JavaLangObject)) {
|
||||
superClass = loader.lookupClass(TypeReference.JavaLangObject.getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
superClass = loader.lookupClass(TypeName.findOrCreate(superName));
|
||||
if (DEBUG) {
|
||||
Trace.println("got superclass " + superClass + " for " + this);
|
||||
}
|
||||
}
|
||||
|
||||
public IClass getSuperclass() throws ClassHierarchyException {
|
||||
if (!superclassComputed) {
|
||||
computeSuperclass();
|
||||
}
|
||||
if (superClass == null && !getReference().equals(TypeReference.JavaLangObject)) {
|
||||
try {
|
||||
throw new ClassHierarchyException("No superclass " + reader.get().getSuperName() + " found for " + this);
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return superClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that this is called from the constructor, at which point this class is
|
||||
* not yet ready to actually load the interfaces. Instead, we pull out the
|
||||
* name of the interfaces and cache it here, to avoid hitting the reader
|
||||
* later.
|
||||
*/
|
||||
private void computeInterfaceNames() {
|
||||
try {
|
||||
String[] s = reader.get().getInterfaceNames();
|
||||
interfaceNames = new ImmutableByteArray[s.length];
|
||||
for (int i = 0; i < interfaceNames.length; i++) {
|
||||
interfaceNames[i] = ImmutableByteArray.make("L" + s[i]);
|
||||
}
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getAllInterfacesAsCollection.
|
||||
*
|
||||
* @return Collection of IClasses, representing the interfaces this class
|
||||
* implements.
|
||||
*/
|
||||
private Collection<IClass> computeAllInterfacesAsCollection() throws ClassHierarchyException {
|
||||
Collection<IClass> c = getDirectInterfaces();
|
||||
Set<IClass> result = HashSetFactory.make();
|
||||
for (Iterator<IClass> it = c.iterator(); it.hasNext();) {
|
||||
IClass klass = it.next();
|
||||
if (klass.isInterface()) {
|
||||
result.add(klass);
|
||||
} else {
|
||||
warnings.add(ClassHierarchyWarning.create("expected an interface " + klass));
|
||||
}
|
||||
}
|
||||
for (Iterator<IClass> it = c.iterator(); it.hasNext();) {
|
||||
ShrikeCTClassWrapper I = (ShrikeCTClassWrapper) it.next();
|
||||
if (I.isInterface()) {
|
||||
result.addAll(I.computeAllInterfacesAsCollection());
|
||||
} else {
|
||||
warnings.add(ClassHierarchyWarning.create("expected an interface " + I));
|
||||
}
|
||||
}
|
||||
|
||||
// now add any interfaces from the super class
|
||||
ShrikeCTClassWrapper sup = null;
|
||||
try {
|
||||
sup = (ShrikeCTClassWrapper) getSuperclass();
|
||||
} catch (ClassHierarchyException e1) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
if (sup != null) {
|
||||
result.addAll(sup.computeAllInterfacesAsCollection());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDirectInterfaces()
|
||||
*/
|
||||
public Collection<IClass> getDirectInterfaces() {
|
||||
return array2IClassSet(interfaceNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method array2Set.
|
||||
*
|
||||
* @param interfaces
|
||||
* a set of class names
|
||||
* @return Set of all IClasses that can be loaded corresponding to the class
|
||||
* names in the interfaces array; raise warnings if classes can not be
|
||||
* loaded
|
||||
*/
|
||||
private Collection<IClass> array2IClassSet(ImmutableByteArray[] interfaces) {
|
||||
ArrayList<IClass> result = new ArrayList<IClass>(interfaces.length);
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
ImmutableByteArray name = interfaces[i];
|
||||
IClass klass = null;
|
||||
klass = loader.lookupClass(TypeName.findOrCreate(name));
|
||||
if (klass == null) {
|
||||
warnings.add(ClassNotFoundWarning.create(name));
|
||||
} else {
|
||||
result.add(klass);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
* A warning for when we get a class not found exception
|
||||
*/
|
||||
private static class ClassNotFoundWarning extends Warning {
|
||||
|
||||
final ImmutableByteArray className;
|
||||
|
||||
ClassNotFoundWarning(ImmutableByteArray className) {
|
||||
super(Warning.SEVERE);
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return getClass().toString() + " : " + className;
|
||||
}
|
||||
|
||||
public static ClassNotFoundWarning create(ImmutableByteArray className) {
|
||||
return new ClassNotFoundWarning(className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set up the methodMap mapping
|
||||
*/
|
||||
private void computeMethodMap() throws InvalidClassFileException {
|
||||
|
||||
if (methodMap == null) {
|
||||
ShrikeCTMethodWrapper[] methods = computeDeclaredMethods();
|
||||
if (methods.length > 5) {
|
||||
methodMap = HashMapFactory.make(methods.length);
|
||||
} else {
|
||||
methodMap = new SmallMap<Selector, IMethod>();
|
||||
}
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
ShrikeCTMethodWrapper m = methods[i];
|
||||
methodMap.put(m.getReference().getSelector(), m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize the declared methods array
|
||||
*
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
private ShrikeCTMethodWrapper[] computeDeclaredMethods() throws InvalidClassFileException {
|
||||
int methodCount = reader.get().getMethodCount();
|
||||
ShrikeCTMethodWrapper[] result = new ShrikeCTMethodWrapper[methodCount];
|
||||
for (int i = 0; i < methodCount; i++) {
|
||||
ShrikeCTMethodWrapper m = new ShrikeCTMethodWrapper(this, i);
|
||||
if (DEBUG) {
|
||||
Trace.println("Register method " + m + " for class " + this);
|
||||
}
|
||||
result[i] = m;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getMethod(com.ibm.wala.types.Selector)
|
||||
*/
|
||||
public IMethod getMethod(Selector selector) {
|
||||
if (DEBUG) {
|
||||
Trace.println("getMethod " + selector + " in " + this);
|
||||
}
|
||||
|
||||
if (methodMap == null) {
|
||||
try {
|
||||
computeMethodMap();
|
||||
} catch (InvalidClassFileException e1) {
|
||||
e1.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// my methods + cached parent stuff
|
||||
IMethod result = (IMethod) methodMap.get(selector);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
if (inheritCache != null) {
|
||||
result = inheritCache.get(selector);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// check parent, caching if found
|
||||
try {
|
||||
if (!selector.equals(MethodReference.clinitSelector) && !selector.equals(MethodReference.initSelector)) {
|
||||
ShrikeCTClassWrapper superclass = (ShrikeCTClassWrapper) getSuperclass();
|
||||
if (superclass != null) {
|
||||
IMethod inherit = superclass.getMethod(selector);
|
||||
if (inherit != null) {
|
||||
if (inheritCache == null) {
|
||||
inheritCache = new BimodalMap<Selector, IMethod>(5);
|
||||
}
|
||||
inheritCache.put(selector, inherit);
|
||||
return inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassHierarchyException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
// didn't find it yet. special logic for interfaces
|
||||
try {
|
||||
if (isInterface()) {
|
||||
// try each superinterface
|
||||
for (Iterator it = getAllAncestorInterfaces().iterator(); it.hasNext();) {
|
||||
IClass k = (IClass) it.next();
|
||||
result = k.getMethod(selector);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch (ClassHierarchyException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE("Bad method lookup in " + this);
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
private final HashMap<Atom, IField> fieldMap = new HashMap<Atom, IField>(5);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getField(com.ibm.wala.util.Atom)
|
||||
*/
|
||||
public IField getField(Atom name) {
|
||||
if (fieldMap.containsKey(name)) {
|
||||
return fieldMap.get(name);
|
||||
} else {
|
||||
IField f = findDeclaredField(name);
|
||||
if (f != null) {
|
||||
fieldMap.put(name, f);
|
||||
return f;
|
||||
} else if (superClass != null) {
|
||||
f = superClass.getField(name);
|
||||
if (f != null) {
|
||||
fieldMap.put(name, f);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private IField findDeclaredField(Atom name) {
|
||||
for (int i = 0; i < instanceFields.length; i++) {
|
||||
if (instanceFields[i].getName() == name) {
|
||||
return instanceFields[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < staticFields.length; i++) {
|
||||
if (staticFields[i].getName() == name) {
|
||||
return staticFields[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize the TypeReference field for this instance
|
||||
*
|
||||
* @throws InvalidClassFileException
|
||||
* iff Shrike can't read this class
|
||||
*/
|
||||
private void computeTypeReference() throws InvalidClassFileException {
|
||||
String className = "L" + reader.get().getName();
|
||||
ImmutableByteArray name = ImmutableByteArray.make(className);
|
||||
|
||||
typeReference = TypeReference.findOrCreate(getClassLoader().getReference(), TypeName.findOrCreate(name));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getReference()
|
||||
*/
|
||||
public TypeReference getReference() {
|
||||
return typeReference;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getSourceFileName()
|
||||
*/
|
||||
public String getSourceFileName() {
|
||||
return loader.getSourceFileName(this);
|
||||
}
|
||||
|
||||
public Collection<IClass> getAllImplementedInterfaces() throws ClassHierarchyException {
|
||||
if (Assertions.verifyAssertions) {
|
||||
if (isInterface()) {
|
||||
Assertions.UNREACHABLE("shouldn't ask for implemented interfaces of " + this);
|
||||
}
|
||||
}
|
||||
if (allInterfaces != null) {
|
||||
return allInterfaces;
|
||||
} else {
|
||||
Collection<IClass> C = computeAllInterfacesAsCollection();
|
||||
allInterfaces = Collections.unmodifiableCollection(C);
|
||||
return allInterfaces;
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<IClass> getAllAncestorInterfaces() throws ClassHierarchyException {
|
||||
if (Assertions.verifyAssertions) {
|
||||
if (!isInterface()) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (allInterfaces != null) {
|
||||
return allInterfaces;
|
||||
} else {
|
||||
Collection<IClass> C = computeAllInterfacesAsCollection();
|
||||
allInterfaces = Collections.unmodifiableCollection(C);
|
||||
return allInterfaces;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return getReference().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
// it's ok to use instanceof since this class is final
|
||||
// if (this.getClass().equals(obj.getClass())) {
|
||||
if (obj instanceof ShrikeCTClassWrapper) {
|
||||
return getReference().equals(((ShrikeCTClassWrapper) obj).getReference());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getReader.
|
||||
*/
|
||||
public ClassReader getReader() {
|
||||
try {
|
||||
return reader.get();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IClass#getClassInitializer()
|
||||
*/
|
||||
public IMethod getClassInitializer() {
|
||||
if (methodMap == null) {
|
||||
try {
|
||||
computeMethodMap();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return (IMethod) methodMap.get(MethodReference.clinitSelector);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredMethods()
|
||||
*/
|
||||
public Iterator<IMethod> getDeclaredMethods() {
|
||||
if (methodMap == null) {
|
||||
try {
|
||||
computeMethodMap();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return methodMap.values().iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#isArrayClass()
|
||||
*/
|
||||
public boolean isArrayClass() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public ClassHierarchy getClassHierarchy() {
|
||||
return cha;
|
||||
}
|
||||
|
||||
public WarningSet getWarnings() {
|
||||
return warnings;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredFields()
|
||||
*/
|
||||
public Collection<IField> getDeclaredInstanceFields() {
|
||||
return Collections.unmodifiableList(Arrays.asList(instanceFields));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDeclaredFields()
|
||||
*/
|
||||
public Collection<IField> getDeclaredStaticFields() {
|
||||
return Collections.unmodifiableList(Arrays.asList(staticFields));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getName()
|
||||
*/
|
||||
public TypeName getName() {
|
||||
return getReference().getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#isReferenceType()
|
||||
*/
|
||||
public boolean isReferenceType() {
|
||||
return getReference().isReferenceType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all optional cached data associated with this class
|
||||
*/
|
||||
public void clearSoftCaches() {
|
||||
// toss optional information from each method.
|
||||
if (methodMap != null) {
|
||||
for (Iterator it = getDeclaredMethods(); it.hasNext();) {
|
||||
ShrikeCTMethodWrapper m = (ShrikeCTMethodWrapper) it.next();
|
||||
m.clearCaches();
|
||||
}
|
||||
}
|
||||
// clear the methodMap cache
|
||||
// SJF: don't do this!!! makes it hard to clear caches on methods.
|
||||
// methodMap = null;
|
||||
inheritCache = null;
|
||||
// clear the cached interfaces
|
||||
allInterfaces = null;
|
||||
// toss away the Shrike reader
|
||||
reader.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllInstanceFields()
|
||||
*/
|
||||
public Collection<IField> getAllInstanceFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new LinkedList<IField>(getDeclaredInstanceFields());
|
||||
IClass s = getSuperclass();
|
||||
while (s != null) {
|
||||
result.addAll(s.getDeclaredInstanceFields());
|
||||
s = s.getSuperclass();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllStaticFields()
|
||||
*/
|
||||
public Collection<IField> getAllStaticFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new LinkedList<IField>(getDeclaredStaticFields());
|
||||
IClass s = getSuperclass();
|
||||
while (s != null) {
|
||||
result.addAll(s.getDeclaredStaticFields());
|
||||
s = s.getSuperclass();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllMethods()
|
||||
*/
|
||||
public Collection<IMethod> getAllMethods() throws ClassHierarchyException {
|
||||
Collection<IMethod> result = new LinkedList<IMethod>();
|
||||
Iterator<IMethod> declaredMethods = getDeclaredMethods();
|
||||
while (declaredMethods.hasNext()) {
|
||||
result.add(declaredMethods.next());
|
||||
}
|
||||
IClass s = getSuperclass();
|
||||
while (s != null) {
|
||||
Iterator<IMethod> superDeclaredMethods = s.getDeclaredMethods();
|
||||
while (superDeclaredMethods.hasNext()) {
|
||||
result.add(superDeclaredMethods.next());
|
||||
}
|
||||
s = s.getSuperclass();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IClass#getAllFields()
|
||||
*/
|
||||
public Collection<IField> getAllFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new LinkedList<IField>();
|
||||
result.addAll(getAllInstanceFields());
|
||||
result.addAll(getAllStaticFields());
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.shrikeBT.Decoder;
|
||||
import com.ibm.wala.shrikeBT.shrikeCT.CTDecoder;
|
||||
import com.ibm.wala.shrikeCT.ClassReader;
|
||||
import com.ibm.wala.shrikeCT.CodeReader;
|
||||
import com.ibm.wala.shrikeCT.ExceptionsReader;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.shrikeCT.LineNumberTableReader;
|
||||
import com.ibm.wala.shrikeCT.LocalVariableTableReader;
|
||||
import com.ibm.wala.shrikeCT.ClassReader.AttrIterator;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
/**
|
||||
*
|
||||
* A wrapper around a Shrike object that represents a method
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public final class ShrikeCTMethodWrapper extends ShrikeBTMethodWrapper {
|
||||
|
||||
/**
|
||||
* The index of this method in the declaring class's method list according to
|
||||
* Shrike CT.
|
||||
*/
|
||||
private int shrikeMethodIndex;
|
||||
|
||||
/**
|
||||
* JVM-level modifiers for this method a value of -1 means "uninitialized"
|
||||
*/
|
||||
private int modifiers = -1;
|
||||
|
||||
public ShrikeCTMethodWrapper(IClass klass, int index) {
|
||||
super(klass);
|
||||
this.shrikeMethodIndex = index;
|
||||
}
|
||||
|
||||
public byte[] getBytecodes() {
|
||||
CodeReader code = getCodeReader();
|
||||
if (code == null) {
|
||||
return null;
|
||||
} else {
|
||||
return code.getBytecode();
|
||||
}
|
||||
}
|
||||
|
||||
protected String getMethodName() throws InvalidClassFileException {
|
||||
ClassReader reader = getClassReader();
|
||||
return reader.getMethodName(shrikeMethodIndex);
|
||||
}
|
||||
|
||||
protected String getMethodSignature() throws InvalidClassFileException {
|
||||
ClassReader reader = getClassReader();
|
||||
return reader.getMethodType(shrikeMethodIndex);
|
||||
}
|
||||
|
||||
protected int getModifiers() {
|
||||
if (modifiers == -1) {
|
||||
modifiers = getClassReader().getMethodAccessFlags(shrikeMethodIndex);
|
||||
}
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
protected Decoder makeDecoder() {
|
||||
CodeReader reader = getCodeReader();
|
||||
if (reader == null) {
|
||||
return null;
|
||||
}
|
||||
final Decoder d = new CTDecoder(reader);
|
||||
try {
|
||||
d.decode();
|
||||
} catch (Decoder.InvalidBytecodeException ex) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
public int getMaxLocals() {
|
||||
CodeReader reader = getCodeReader();
|
||||
return reader.getMaxLocals();
|
||||
}
|
||||
|
||||
public int getMaxStackHeight() {
|
||||
CodeReader reader = getCodeReader();
|
||||
// note that Shrike returns the maximum index in the zero-indexed stack
|
||||
// array.
|
||||
// Instead, we want the max number of entries on the stack.
|
||||
// So we add 1.
|
||||
// Additionally, ShrikeBT may add additional stack entries with
|
||||
// Constant instructions. We add an additional 1 to account for this,
|
||||
// which seems to handle all ShrikeBT code generation patterns.
|
||||
// TODO: ShrikeBT should have a getMaxStack method on Decoder, I think.
|
||||
return reader.getMaxStack() + 2;
|
||||
}
|
||||
|
||||
public boolean hasExceptionHandler() {
|
||||
CodeReader reader = getCodeReader();
|
||||
if (reader == null)
|
||||
return false;
|
||||
int[] handlers = reader.getRawHandlers();
|
||||
return handlers != null && handlers.length > 0;
|
||||
}
|
||||
|
||||
protected String[] getDeclaredExceptionTypeNames() throws InvalidClassFileException {
|
||||
ExceptionsReader reader = getExceptionReader();
|
||||
if (reader == null) {
|
||||
return null;
|
||||
} else {
|
||||
return reader.getClasses();
|
||||
}
|
||||
}
|
||||
|
||||
protected void processDebugInfo(BytecodeInfo bcInfo) throws InvalidClassFileException {
|
||||
CodeReader cr = getCodeReader();
|
||||
bcInfo.lineNumberMap = LineNumberTableReader.makeBytecodeToSourceMap(cr);
|
||||
bcInfo.localVariableMap = LocalVariableTableReader.makeVarMap(cr);
|
||||
}
|
||||
|
||||
|
||||
public String getLocalVariableName(int bcIndex, int localNumber) {
|
||||
if (bcInfo == null) {
|
||||
try {
|
||||
processBytecodes();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(bcInfo != null);
|
||||
}
|
||||
int[][] map = bcInfo.localVariableMap;
|
||||
|
||||
if (localNumber > getMaxLocals()) {
|
||||
throw new IllegalArgumentException("illegal local number: " + localNumber + ", method " + getName() + " uses at most "
|
||||
+ getMaxLocals());
|
||||
}
|
||||
|
||||
if (map == null) {
|
||||
return null;
|
||||
} else {
|
||||
int[] localPairs = map[bcIndex];
|
||||
int localIndex = localNumber * 2;
|
||||
if (localPairs == null || localIndex >= localPairs.length) {
|
||||
// no information about the specified local at this program point
|
||||
return null;
|
||||
}
|
||||
int nameIndex = localPairs[localIndex];
|
||||
if (nameIndex == 0) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
return getClassReader().getCP().getCPUtf8(nameIndex);
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: cache for efficiency? (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#hasLocalVariableTable()
|
||||
*/
|
||||
public boolean hasLocalVariableTable() {
|
||||
try {
|
||||
ClassReader.AttrIterator iter = new ClassReader.AttrIterator();
|
||||
getCodeReader().initAttributeIterator(iter);
|
||||
for (; iter.isValid(); iter.advance()) {
|
||||
if (iter.getName().equals("LocalVariableTable")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private ClassReader getClassReader() {
|
||||
return ((ShrikeCTClassWrapper)getDeclaringClass()).getReader();
|
||||
}
|
||||
|
||||
private CodeReader getCodeReader() {
|
||||
ClassReader.AttrIterator iter = new AttrIterator();
|
||||
getClassReader().initMethodAttributeIterator(shrikeMethodIndex, iter);
|
||||
|
||||
// search for the code attribute
|
||||
CodeReader code = null;
|
||||
try {
|
||||
for (; iter.isValid(); iter.advance()) {
|
||||
if (iter.getName().toString().equals("Code")) {
|
||||
code = new CodeReader(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
private ExceptionsReader getExceptionReader() {
|
||||
ClassReader.AttrIterator iter = new AttrIterator();
|
||||
getClassReader().initMethodAttributeIterator(shrikeMethodIndex, iter);
|
||||
|
||||
// search for the desired attribute
|
||||
ExceptionsReader result = null;
|
||||
try {
|
||||
for (; iter.isValid(); iter.advance()) {
|
||||
if (iter.getName().toString().equals("Exceptions")) {
|
||||
result = new ExceptionsReader(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public TypeReference getReturnType() {
|
||||
return getReference().getReturnType();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.cfg.ControlFlowGraph;
|
||||
import com.ibm.wala.cfg.ShrikeCFG;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.IRFactory;
|
||||
import com.ibm.wala.ssa.SSABuilder;
|
||||
import com.ibm.wala.ssa.SSACFG;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAOptions;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.analysis.DeadAssignmentElimination;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
* @author Julian Dolby
|
||||
*
|
||||
*/
|
||||
public class ShrikeIRFactory implements IRFactory {
|
||||
|
||||
public final static boolean buildLocalMap = true;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ssa.IRFactory#makeCFG(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.wala.ipa.cha.ClassHierarchy,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public ControlFlowGraph makeCFG(final IMethod method, Context C, final ClassHierarchy cha, final WarningSet warnings) {
|
||||
return new ShrikeCFG((ShrikeCTMethodWrapper) method, warnings, cha);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.ssa.IRFactory#makeIR(com.ibm.wala.classLoader.IMethod,
|
||||
* com.ibm.wala.ipa.cha.ClassHierarchy, com.ibm.wala.ssa.SSAOptions,
|
||||
* com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public IR makeIR(final IMethod method, Context C, final ClassHierarchy cha, final SSAOptions options, final WarningSet warnings) {
|
||||
// This should be a method from Shrike
|
||||
Assertions._assert(method instanceof ShrikeCTMethodWrapper);
|
||||
|
||||
// Set up some ShrikeCT mapping information before constructing SSA
|
||||
try {
|
||||
((ShrikeCTMethodWrapper) method).processBytecodes();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
com.ibm.wala.shrikeBT.Instruction[] shrikeInstructions;
|
||||
try {
|
||||
shrikeInstructions = ((ShrikeCTMethodWrapper) method).getInstructions();
|
||||
} catch (InvalidClassFileException e) {
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
shrikeInstructions = null;
|
||||
}
|
||||
final ShrikeCFG shrikeCFG = (ShrikeCFG) makeCFG(method, C, cha, warnings);
|
||||
|
||||
final SymbolTable symbolTable = new SymbolTable(method.getNumberOfParameters());
|
||||
final SSAInstruction[] newInstrs = new SSAInstruction[shrikeInstructions.length];
|
||||
|
||||
final SSACFG newCfg = new SSACFG(method, shrikeCFG, newInstrs, warnings);
|
||||
|
||||
return new IR(method, newInstrs, symbolTable, newCfg, options) {
|
||||
private final SSA2LocalMap localMap;
|
||||
|
||||
/**
|
||||
* Remove any phis that are dead assignments.
|
||||
*
|
||||
* TODO: move this elsewhere?
|
||||
*/
|
||||
private void eliminateDeadPhis() {
|
||||
DeadAssignmentElimination.perform(this);
|
||||
}
|
||||
|
||||
public SSA2LocalMap getLocalMap() {
|
||||
return localMap;
|
||||
}
|
||||
|
||||
{
|
||||
SSABuilder builder = new SSABuilder((ShrikeCTMethodWrapper) method, cha, newCfg, shrikeCFG, newInstrs, symbolTable,
|
||||
buildLocalMap, options.getUsePiNodes(), warnings);
|
||||
builder.build();
|
||||
if (buildLocalMap)
|
||||
localMap = builder.getLocalMap();
|
||||
else
|
||||
localMap = null;
|
||||
|
||||
eliminateDeadPhis();
|
||||
|
||||
setupLocationMap();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class SourceDirectoryTreeModule extends DirectoryTreeModule {
|
||||
|
||||
public SourceDirectoryTreeModule(File root) {
|
||||
super( root );
|
||||
}
|
||||
|
||||
protected boolean includeFile(File file) {
|
||||
return file.getName().endsWith("java");
|
||||
}
|
||||
|
||||
protected FileModule makeFile(File file) {
|
||||
return new SourceFileModule(file, root.getAbsolutePath());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.ibm.wala.util.io.FileSuffixes;
|
||||
|
||||
/**
|
||||
*
|
||||
* A module which is a wrapper around a .java file
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public class SourceFileModule extends FileModule implements Module, ModuleEntry {
|
||||
|
||||
private final String fileName;
|
||||
public SourceFileModule(File f, String fileName) {
|
||||
super(f);
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public SourceFileModule(File f, SourceFileModule clonedFrom) {
|
||||
super(f);
|
||||
this.fileName = clonedFrom.fileName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "SourceFileModule:" + getFile().toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isClassFile()
|
||||
*/
|
||||
public boolean isClassFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#getClassName()
|
||||
*/
|
||||
public String getClassName() {
|
||||
return FileSuffixes.stripSuffix(fileName).replace(File.separator.charAt(0), '/');
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.ModuleEntry#isSourceFile()
|
||||
*/
|
||||
public boolean isSourceFile() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
public class SourceURLModule extends AbstractURLModule {
|
||||
|
||||
public SourceURLModule(URL url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
public boolean isClassFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSourceFile() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* A Class that exists nowhere in bytecode.
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public abstract class SyntheticClass implements IClass {
|
||||
|
||||
private final TypeReference T;
|
||||
|
||||
private final ClassHierarchy cha;
|
||||
/**
|
||||
* @param T type reference describing this class
|
||||
*/
|
||||
public SyntheticClass(TypeReference T, ClassHierarchy cha) {
|
||||
super();
|
||||
this.T = T;
|
||||
this.cha = cha;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, a synthetic class is "loaded" by the primordial loader.
|
||||
* Subclasses may override as necessary.
|
||||
* @see com.ibm.wala.classLoader.IClass#getClassLoader()
|
||||
*/
|
||||
public IClassLoader getClassLoader() {
|
||||
return cha.getLoader(ClassLoaderReference.Primordial);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.IClass#isInterface()
|
||||
*/
|
||||
public boolean isInterface() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.IClass#isAbstract()
|
||||
*/
|
||||
public boolean isAbstract() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.IClass#getReference()
|
||||
*/
|
||||
public TypeReference getReference() {
|
||||
return T;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.IClass#getSourceFileName()
|
||||
*/
|
||||
public String getSourceFileName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.IClass#isArrayClass()
|
||||
*/
|
||||
public boolean isArrayClass() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,360 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.classLoader;
|
||||
|
||||
import com.ibm.wala.cfg.InducedCFG;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAOptions;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.Atom;
|
||||
import com.ibm.wala.util.bytecode.BytecodeStream;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
/**
|
||||
* @author sfink
|
||||
*
|
||||
*/
|
||||
public class SyntheticMethod implements IMethod {
|
||||
|
||||
public final static SSAInstruction[] NO_STATEMENTS = new SSAInstruction[0];
|
||||
|
||||
private final MethodReference method;
|
||||
|
||||
private final IMethod resolvedMethod;
|
||||
|
||||
private final IClass declaringClass;
|
||||
|
||||
private final boolean isStatic;
|
||||
|
||||
private final boolean isFactory;
|
||||
|
||||
|
||||
public SyntheticMethod(MethodReference method, IClass declaringClass, boolean isStatic, boolean isFactory) {
|
||||
super();
|
||||
this.method = method;
|
||||
this.resolvedMethod = null;
|
||||
this.declaringClass = declaringClass;
|
||||
this.isStatic = isStatic;
|
||||
this.isFactory = isFactory;
|
||||
}
|
||||
|
||||
|
||||
public SyntheticMethod(IMethod method, IClass declaringClass, boolean isStatic, boolean isFactory) {
|
||||
super();
|
||||
this.resolvedMethod = method;
|
||||
this.method = resolvedMethod.getReference();
|
||||
this.declaringClass = declaringClass;
|
||||
this.isStatic = isStatic;
|
||||
this.isFactory = isFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#isClinit()
|
||||
*/
|
||||
public boolean isClinit() {
|
||||
return method.getSelector().equals(MethodReference.clinitSelector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#isInit()
|
||||
*/
|
||||
public boolean isInit() {
|
||||
return method.getSelector().equals(MethodReference.initSelector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#isStatic()
|
||||
*/
|
||||
public boolean isStatic() {
|
||||
return isStatic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#isNative()
|
||||
*/
|
||||
public boolean isNative() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#isAbstract()
|
||||
*/
|
||||
public boolean isAbstract() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#isPrivate()
|
||||
*/
|
||||
public boolean isPrivate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isProtected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPublic() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#isFinal()
|
||||
*/
|
||||
public boolean isFinal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#isAbstract()
|
||||
*/
|
||||
public boolean isSynchronized() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#isSynthetic()
|
||||
*/
|
||||
public boolean isSynthetic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#getReference()
|
||||
*/
|
||||
public MethodReference getReference() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public InducedCFG makeControlFlowGraph() {
|
||||
return new InducedCFG(getStatements(new WarningSet()), this, Everywhere.EVERYWHERE);
|
||||
}
|
||||
|
||||
public BytecodeStream getBytecodeStream() {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#getMaxLocals()
|
||||
*/
|
||||
public int getMaxLocals() {
|
||||
Assertions.UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMethod#getMaxStackHeight()
|
||||
*/
|
||||
public int getMaxStackHeight() {
|
||||
Assertions.UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.classLoader.IMember#getDeclaringClass()
|
||||
*/
|
||||
public IClass getDeclaringClass() {
|
||||
return declaringClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(Object)
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (getClass().equals(obj.getClass())) {
|
||||
SyntheticMethod other = (SyntheticMethod) obj;
|
||||
return (method.equals(other.method));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return method.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer s = new StringBuffer("synthetic ");
|
||||
if (isFactoryMethod()) {
|
||||
s.append(" factory ");
|
||||
}
|
||||
s.append(method.toString());
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#hasExceptionHandler()
|
||||
*/
|
||||
public boolean hasExceptionHandler() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasPoison() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getPoison() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte getPoisonLevel() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getStatements(com.ibm.wala.util.WarningSet)
|
||||
*/
|
||||
public SSAInstruction[] getStatements(SSAOptions options, WarningSet warnings) {
|
||||
return NO_STATEMENTS;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getIR(com.ibm.wala.util.WarningSet)
|
||||
*/
|
||||
public IR makeIR(SSAOptions options, WarningSet warnings) {
|
||||
Assertions.UNREACHABLE("haven't implemented IR yet for class " + getClass());
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getParameterType(int)
|
||||
*/
|
||||
public TypeReference getParameterType(int i) {
|
||||
if (isStatic()) {
|
||||
return method.getParameterType(i);
|
||||
} else {
|
||||
if (i == 0) {
|
||||
return method.getDeclaringClass();
|
||||
} else {
|
||||
return method.getParameterType(i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getNumberOfParameters()
|
||||
*/
|
||||
public int getNumberOfParameters() {
|
||||
int n = method.getNumberOfParameters();
|
||||
return isStatic() ? n : n + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getDeclaredExceptions()
|
||||
*/
|
||||
public TypeReference[] getDeclaredExceptions() {
|
||||
if (resolvedMethod == null) {
|
||||
return null;
|
||||
} else {
|
||||
return resolvedMethod.getDeclaredExceptions();
|
||||
}
|
||||
}
|
||||
|
||||
public Atom getName() {
|
||||
return method.getSelector().getName();
|
||||
}
|
||||
|
||||
public Descriptor getDescriptor() {
|
||||
return method.getSelector().getDescriptor();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getLineNumber(int)
|
||||
*/
|
||||
public int getLineNumber(int bcIndex) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean isFactoryMethod() {
|
||||
return isFactory;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getSignature()
|
||||
*/
|
||||
public String getSignature() {
|
||||
return getReference().getSignature();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getSelector()
|
||||
*/
|
||||
public Selector getSelector() {
|
||||
return getReference().getSelector();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getLocalVariableName(int, int)
|
||||
*/
|
||||
public String getLocalVariableName(int bcIndex, int localNumber) {
|
||||
// no information is available
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#hasLocalVariableTable()
|
||||
*/
|
||||
public boolean hasLocalVariableTable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.ibm.wala.classLoader.IMethod#getStatements(com.ibm.wala.util.warnings.WarningSet)
|
||||
*/
|
||||
public SSAInstruction[] getStatements(WarningSet warnings) {
|
||||
return getStatements(SSAOptions.defaultOptions(), warnings);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.classLoader.IMethod#getReturnType()
|
||||
*/
|
||||
public TypeReference getReturnType() {
|
||||
return getReference().getReturnType();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
This package provides functionality related to class loading and
|
||||
management of loaded classes.
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -0,0 +1,71 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2002 - 2006 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.client;
|
||||
|
||||
import com.ibm.wala.util.Stopwatch;
|
||||
|
||||
/**
|
||||
*
|
||||
* An object to track performance of an analysis engine
|
||||
*
|
||||
* @author sfink
|
||||
*/
|
||||
public abstract class AbstractEngineStopwatch implements EngineStopwatch {
|
||||
|
||||
/**
|
||||
* @return the number of distinct categories timed by this object
|
||||
*/
|
||||
protected abstract int getNumberOfCategories();
|
||||
|
||||
/**
|
||||
* @return an array of Strings that represent names of the categories tracked
|
||||
*/
|
||||
protected abstract String[] getCategoryNames();
|
||||
|
||||
protected final Stopwatch[] stopwatch;
|
||||
|
||||
protected AbstractEngineStopwatch() {
|
||||
stopwatch = new Stopwatch[getNumberOfCategories()];
|
||||
for (int i = 0; i < getNumberOfCategories(); i++) {
|
||||
stopwatch[i] = new Stopwatch(getCategoryNames()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public final String report() {
|
||||
StringBuffer result = new StringBuffer();
|
||||
long total = 0;
|
||||
for (int i = 0; i < getNumberOfCategories(); i++) {
|
||||
total += stopwatch[i].getElapsedMillis();
|
||||
result.append(getCategoryNames()[i] + ": " + stopwatch[i].getElapsedMillis() + "\n");
|
||||
}
|
||||
result.append("Total : " + total + "\n");
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void start(byte category) {
|
||||
stopwatch[category].start();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void stop(byte category) {
|
||||
stopwatch[category].stop();
|
||||
}
|
||||
|
||||
public Stopwatch getTimer(byte category) {
|
||||
return stopwatch[category];
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue