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:
sjfink 2006-11-22 17:38:46 +00:00
commit df97f42b7e
1316 changed files with 201901 additions and 0 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -0,0 +1,3 @@
#Mon Oct 02 08:58:11 EDT 2006
eclipse.preferences.version=1
internal.default.compliance=default

View File

@ -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

View File

@ -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/

202
com.ibm.wala.core/build.xml Normal file
View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -0,0 +1,3 @@
#Mon Oct 02 08:58:11 EDT 2006
eclipse.preferences.version=1
internal.default.compliance=default

View File

@ -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

View File

@ -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/

View File

@ -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>

View File

@ -0,0 +1 @@
wala.properties

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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="&lt;init&gt;" 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="&lt;init&gt;"
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>

View File

@ -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

View File

@ -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/*;?**/*]

View File

@ -0,0 +1,6 @@
PLUGINNAME=core WALA analysis engine
VENDORNAME=IBMproviderName = www.example.org
pluginName = PatternSet Model
# ====================================================================
providerName = www.example.org

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,5 @@
<HTML>
<BODY>
This package defines utilities to help navigate pointer analysis results.
</BODY>
</HTML>

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,5 @@
<HTML>
<BODY>
This package provides functions to deal with reflection.
</BODY>
</HTML>

View File

@ -0,0 +1,6 @@
<HTML>
<BODY>
This package provides a layer to perform abstract interpretation over
the JVM stack machine.
</BODY>
</HTML>

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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";
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,5 @@
<HTML>
<BODY>
This package provides intraprocedural type inference over the SSA form.
</BODY>
</HTML>

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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
}

View File

@ -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;
}
}

View File

@ -0,0 +1,5 @@
<HTML>
<BODY>
This package supports a control-dependence graph.
</BODY>
</HTML>

View File

@ -0,0 +1,5 @@
<HTML>
<BODY>
This package provides control-flow graph utilities.
</BODY>
</HTML>

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View 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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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());
}
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View 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();
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View 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();
}

View File

@ -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();
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
};
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -0,0 +1,6 @@
<HTML>
<BODY>
This package provides functionality related to class loading and
management of loaded classes.
</BODY>
</HTML>

View File

@ -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