Generalize certain IR data structures to be less Java-specific. Generalize annotations code to allow for reading annotation parameters. Various other fixes
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4290 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
bd315e7718
commit
59e46916ce
|
@ -138,7 +138,7 @@ public abstract class JavaIRTests extends IRTests {
|
|||
final IClass iClass = cg.getClassHierarchy().lookupClass(type);
|
||||
Assert.assertNotNull("Could not find class " + typeStr, iClass);
|
||||
|
||||
final Collection<IClass> interfaces = iClass.getDirectInterfaces();
|
||||
final Collection<? extends IClass> interfaces = iClass.getDirectInterfaces();
|
||||
|
||||
Assert.assertEquals("Expected one single interface.", interfaces.size(), 1);
|
||||
|
||||
|
|
|
@ -316,14 +316,13 @@ public class JavaCAst2IRTranslator extends AstTranslator {
|
|||
}
|
||||
|
||||
protected boolean visitCast(CAstNode n, Context c, CAstVisitor visitor) {
|
||||
WalkContext context = (WalkContext) c;
|
||||
WalkContext context = (WalkContext)c;
|
||||
int result = context.currentScope().allocateTempValue();
|
||||
setValue(n, result);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void leaveCast(CAstNode n, Context c, CAstVisitor visitor) {
|
||||
WalkContext context = (WalkContext) c;
|
||||
WalkContext context = (WalkContext)c;
|
||||
int result = getValue(n);
|
||||
CAstType toType = (CAstType) n.getChild(0).getValue();
|
||||
TypeReference toRef = makeType(toType);
|
||||
|
@ -332,29 +331,42 @@ public class JavaCAst2IRTranslator extends AstTranslator {
|
|||
TypeReference fromRef = makeType(fromType);
|
||||
|
||||
if (toRef.isPrimitiveType()) {
|
||||
context.cfg().addInstruction(insts.ConversionInstruction(result, getValue(n.getChild(1)), fromRef, toRef, false));
|
||||
|
||||
context.cfg().addInstruction(
|
||||
insts.ConversionInstruction(
|
||||
result,
|
||||
getValue(n.getChild(1)),
|
||||
fromRef,
|
||||
toRef,
|
||||
false));
|
||||
|
||||
} else {
|
||||
context.cfg().addInstruction(insts.CheckCastInstruction(result, getValue(n.getChild(1)), toRef));
|
||||
context.cfg().addInstruction(
|
||||
insts.CheckCastInstruction(
|
||||
result,
|
||||
getValue(n.getChild(1)),
|
||||
toRef,
|
||||
true));
|
||||
|
||||
processExceptions(n, context);
|
||||
processExceptions(n, context);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean visitInstanceOf(CAstNode n, Context c, CAstVisitor visitor) {
|
||||
WalkContext context = (WalkContext) c;
|
||||
WalkContext context = (WalkContext)c;
|
||||
int result = context.currentScope().allocateTempValue();
|
||||
setValue(n, result);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void leaveInstanceOf(CAstNode n, Context c, CAstVisitor visitor) {
|
||||
WalkContext context = (WalkContext) c;
|
||||
WalkContext context = (WalkContext)c;
|
||||
int result = getValue(n);
|
||||
CAstType type = (CAstType) n.getChild(0).getValue();
|
||||
|
||||
TypeReference ref = makeType(type);
|
||||
context.cfg().addInstruction(insts.InstanceofInstruction(result, getValue(n.getChild(1)), ref));
|
||||
TypeReference ref = makeType( type );
|
||||
context.cfg().addInstruction(
|
||||
insts.InstanceofInstruction(
|
||||
result,
|
||||
getValue(n.getChild(1)),
|
||||
ref));
|
||||
}
|
||||
|
||||
protected boolean doVisit(CAstNode n, Context context, CAstVisitor visitor) {
|
||||
|
@ -369,7 +381,6 @@ public class JavaCAst2IRTranslator extends AstTranslator {
|
|||
visitor.visit(n.getChild(0), wc, visitor);
|
||||
wc.cfg().addInstruction(insts.MonitorInstruction(getValue(n.getChild(0)), false));
|
||||
processExceptions(n, wc);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return super.doVisit(n, wc, visitor);
|
||||
|
|
|
@ -39,4 +39,5 @@ public class FileMapping{
|
|||
ps.println(line + ": " + fnAndln);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -347,20 +347,22 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
|
|||
};
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types) {
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types, boolean isPEI) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues) {
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues, boolean isPEI) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue) {
|
||||
return CheckCastInstruction(result, val, new int[] { typeValue });
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue, boolean isPEI) {
|
||||
assert isPEI;
|
||||
return CheckCastInstruction(result, val, new int[]{ typeValue }, true);
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type) {
|
||||
return CheckCastInstruction(result, val, new TypeReference[] { type });
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type, boolean isPEI) {
|
||||
assert isPEI;
|
||||
return CheckCastInstruction(result, val, new TypeReference[]{ type }, true);
|
||||
}
|
||||
|
||||
public SSAComparisonInstruction ComparisonInstruction(Operator operator, int result, int val1, int val2) {
|
||||
|
|
|
@ -1,90 +1,90 @@
|
|||
package com.ibm.wala.cast.js.vis;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.ibm.wala.analysis.pointers.HeapGraph;
|
||||
import com.ibm.wala.cast.ipa.callgraph.AstGlobalPointerKey;
|
||||
import com.ibm.wala.cast.ipa.callgraph.ObjectPropertyCatalogKey;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.util.intset.MutableMapping;
|
||||
import com.ibm.wala.util.intset.OrdinalSetMapping;
|
||||
import com.ibm.wala.viz.viewer.PaPanel;
|
||||
|
||||
/**
|
||||
* Augments the PaPanel with: 1) global pointer keys at the root level. 2) property catalog key for instance keys.
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public class JsPaPanel extends PaPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private MutableMapping<List<ObjectPropertyCatalogKey>> instanceKeyIdToObjectPropertyCatalogKey = MutableMapping.<List<ObjectPropertyCatalogKey>> make();
|
||||
private List<AstGlobalPointerKey> globalsPointerKeys = new ArrayList<AstGlobalPointerKey>();
|
||||
|
||||
public JsPaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
super(cg, pa);
|
||||
initDataStructures(pa);
|
||||
}
|
||||
|
||||
private void initDataStructures(PointerAnalysis pa) {
|
||||
HeapGraph heapGraph = pa.getHeapGraph();
|
||||
OrdinalSetMapping<InstanceKey> instanceKeyMapping = pa.getInstanceKeyMapping();
|
||||
for (Object n : heapGraph){
|
||||
if (heapGraph.getPredNodeCount(n) == 0){
|
||||
if (n instanceof PointerKey){
|
||||
if (n instanceof ObjectPropertyCatalogKey){
|
||||
ObjectPropertyCatalogKey opck = (ObjectPropertyCatalogKey) n;
|
||||
InstanceKey instanceKey = opck.getObject();
|
||||
int instanceKeyId = instanceKeyMapping.getMappedIndex(instanceKey);
|
||||
mapUsingMutableMapping(instanceKeyIdToObjectPropertyCatalogKey, instanceKeyId, opck);
|
||||
} else if (n instanceof AstGlobalPointerKey){
|
||||
globalsPointerKeys.add((AstGlobalPointerKey) n);
|
||||
}
|
||||
} else {
|
||||
System.err.println("Non Pointer key root: " + n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected List<PointerKey> getPointerKeysUnderInstanceKey(InstanceKey ik) {
|
||||
List<PointerKey> ret = new ArrayList<PointerKey>();
|
||||
ret.addAll(super.getPointerKeysUnderInstanceKey(ik));
|
||||
int ikIndex = pa.getInstanceKeyMapping().getMappedIndex(ik);
|
||||
ret.addAll(nonNullList(instanceKeyIdToObjectPropertyCatalogKey.getMappedObject(ikIndex)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
private String cgNodesRoot = "CGNodes";
|
||||
private String globalsRoot = "Globals";
|
||||
|
||||
@Override
|
||||
protected List<Object> getRootNodes() {
|
||||
List<Object> ret = new ArrayList<Object>(2);
|
||||
ret.add(cgNodesRoot);
|
||||
ret.add(globalsRoot);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Object> getChildrenFor(Object node) {
|
||||
List<Object> ret = new ArrayList<Object>();
|
||||
if (node == cgNodesRoot){
|
||||
for (int nodeId = 0 ; nodeId < cg.getNumberOfNodes(); nodeId++){
|
||||
CGNode cgNode = cg.getNode(nodeId);
|
||||
ret.add(cgNode);
|
||||
}
|
||||
} else if (node == globalsRoot){
|
||||
ret.addAll(globalsPointerKeys);
|
||||
} else {
|
||||
ret.addAll(super.getChildrenFor(node));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
package com.ibm.wala.cast.js.vis;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.ibm.wala.analysis.pointers.HeapGraph;
|
||||
import com.ibm.wala.cast.ipa.callgraph.AstGlobalPointerKey;
|
||||
import com.ibm.wala.cast.ipa.callgraph.ObjectPropertyCatalogKey;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.util.intset.MutableMapping;
|
||||
import com.ibm.wala.util.intset.OrdinalSetMapping;
|
||||
import com.ibm.wala.viz.viewer.PaPanel;
|
||||
|
||||
/**
|
||||
* Augments the PaPanel with: 1) global pointer keys at the root level. 2) property catalog key for instance keys.
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public class JsPaPanel extends PaPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private MutableMapping<List<ObjectPropertyCatalogKey>> instanceKeyIdToObjectPropertyCatalogKey = MutableMapping.<List<ObjectPropertyCatalogKey>> make();
|
||||
private List<AstGlobalPointerKey> globalsPointerKeys = new ArrayList<AstGlobalPointerKey>();
|
||||
|
||||
public JsPaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
super(cg, pa);
|
||||
initDataStructures(pa);
|
||||
}
|
||||
|
||||
private void initDataStructures(PointerAnalysis pa) {
|
||||
HeapGraph heapGraph = pa.getHeapGraph();
|
||||
OrdinalSetMapping<InstanceKey> instanceKeyMapping = pa.getInstanceKeyMapping();
|
||||
for (Object n : heapGraph){
|
||||
if (heapGraph.getPredNodeCount(n) == 0){
|
||||
if (n instanceof PointerKey){
|
||||
if (n instanceof ObjectPropertyCatalogKey){
|
||||
ObjectPropertyCatalogKey opck = (ObjectPropertyCatalogKey) n;
|
||||
InstanceKey instanceKey = opck.getObject();
|
||||
int instanceKeyId = instanceKeyMapping.getMappedIndex(instanceKey);
|
||||
mapUsingMutableMapping(instanceKeyIdToObjectPropertyCatalogKey, instanceKeyId, opck);
|
||||
} else if (n instanceof AstGlobalPointerKey){
|
||||
globalsPointerKeys.add((AstGlobalPointerKey) n);
|
||||
}
|
||||
} else {
|
||||
System.err.println("Non Pointer key root: " + n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected List<PointerKey> getPointerKeysUnderInstanceKey(InstanceKey ik) {
|
||||
List<PointerKey> ret = new ArrayList<PointerKey>();
|
||||
ret.addAll(super.getPointerKeysUnderInstanceKey(ik));
|
||||
int ikIndex = pa.getInstanceKeyMapping().getMappedIndex(ik);
|
||||
ret.addAll(nonNullList(instanceKeyIdToObjectPropertyCatalogKey.getMappedObject(ikIndex)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
private String cgNodesRoot = "CGNodes";
|
||||
private String globalsRoot = "Globals";
|
||||
|
||||
@Override
|
||||
protected List<Object> getRootNodes() {
|
||||
List<Object> ret = new ArrayList<Object>(2);
|
||||
ret.add(cgNodesRoot);
|
||||
ret.add(globalsRoot);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Object> getChildrenFor(Object node) {
|
||||
List<Object> ret = new ArrayList<Object>();
|
||||
if (node == cgNodesRoot){
|
||||
for (int nodeId = 0 ; nodeId < cg.getNumberOfNodes(); nodeId++){
|
||||
CGNode cgNode = cg.getNode(nodeId);
|
||||
ret.add(cgNode);
|
||||
}
|
||||
} else if (node == globalsRoot){
|
||||
ret.addAll(globalsPointerKeys);
|
||||
} else {
|
||||
ret.addAll(super.getChildrenFor(node));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
package com.ibm.wala.cast.js.vis;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.viz.viewer.PaPanel;
|
||||
import com.ibm.wala.viz.viewer.WalaViewer;
|
||||
|
||||
public class JsViewer extends WalaViewer{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public JsViewer(CallGraph cg, PointerAnalysis pa) {
|
||||
super(cg, pa);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PaPanel createPaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
return new JsPaPanel(cg, pa);
|
||||
}
|
||||
}
|
||||
package com.ibm.wala.cast.js.vis;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.viz.viewer.PaPanel;
|
||||
import com.ibm.wala.viz.viewer.WalaViewer;
|
||||
|
||||
public class JsViewer extends WalaViewer{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public JsViewer(CallGraph cg, PointerAnalysis pa) {
|
||||
super(cg, pa);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PaPanel createPaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
return new JsPaPanel(cg, pa);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,10 +121,10 @@ public class CrossLanguageCallGraph extends AstCallGraph {
|
|||
return root.addGetStatic(ref);
|
||||
}
|
||||
|
||||
public int addCheckcast(TypeReference[] type, int rv) {
|
||||
public int addCheckcast(TypeReference[] type, int rv, boolean isPEI) {
|
||||
Atom language = type[0].getClassLoader().getLanguage();
|
||||
AbstractRootMethod root = getLanguageRoot(language);
|
||||
return root.addCheckcast(type, rv);
|
||||
return root.addCheckcast(type, rv, isPEI);
|
||||
}
|
||||
|
||||
public SSANewInstruction addAllocation(TypeReference type) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.Iterator;
|
|||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
|
||||
|
@ -220,6 +221,7 @@ public class SlicerTest {
|
|||
* @throws IllegalArgumentException
|
||||
* @throws IOException
|
||||
*/
|
||||
@Ignore
|
||||
@Test
|
||||
public void testSlice7() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
|
||||
AnalysisScope scope = findOrCreateAnalysisScope();
|
||||
|
|
|
@ -150,7 +150,7 @@ public class ReflectiveInvocationInterpreter extends AbstractReflectionInterpret
|
|||
// insert a cast for v2 to filter out bogus types
|
||||
args[0] = nextLocal++;
|
||||
TypeReference type = target.getParameterType(0);
|
||||
SSACheckCastInstruction cast = insts.CheckCastInstruction(args[0], 2, type);
|
||||
SSACheckCastInstruction cast = insts.CheckCastInstruction(args[0], 2, type, true);
|
||||
m.addInstruction(null, cast, false);
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ public class ReflectiveInvocationInterpreter extends AbstractReflectionInterpret
|
|||
args[j] = nextLocal++;
|
||||
TypeReference type = target.getParameterType(j);
|
||||
// we insert a cast to filter out bogus types
|
||||
SSACheckCastInstruction cast = insts.CheckCastInstruction(args[j], temp, type);
|
||||
SSACheckCastInstruction cast = insts.CheckCastInstruction(args[j], temp, type, true);
|
||||
m.addInstruction(null, cast, false);
|
||||
pc++;
|
||||
}
|
||||
|
|
|
@ -85,16 +85,6 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
*/
|
||||
final private ShrikeCFG cfg;
|
||||
|
||||
/**
|
||||
* The max height of the stack.
|
||||
*/
|
||||
final private int maxStackHeight;
|
||||
|
||||
/**
|
||||
* the max number of locals in play
|
||||
*/
|
||||
final protected int maxLocals;
|
||||
|
||||
/**
|
||||
* Should uninitialized variables be considered TOP (optimistic) or BOTTOM (pessimistic);
|
||||
*/
|
||||
|
@ -104,8 +94,6 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
if (G == null) {
|
||||
throw new IllegalArgumentException("G is null");
|
||||
}
|
||||
maxStackHeight = G.getMaxStackHeight();
|
||||
maxLocals = G.getMaxLocals();
|
||||
this.cfg = G;
|
||||
}
|
||||
|
||||
|
@ -394,7 +382,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
// allocate lhs.stack if it's
|
||||
// not already allocated.
|
||||
if (L.stack == null) {
|
||||
L.allocateStack();
|
||||
L.allocateStack(1);
|
||||
L.stackHeight = 1;
|
||||
}
|
||||
|
||||
|
@ -430,8 +418,8 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
|
||||
// if there's any stack height to meet, allocate lhs.stack if it's
|
||||
// not already allocated.
|
||||
if (height > -1 && L.stack == null) {
|
||||
L.allocateStack();
|
||||
if (height > -1 && (L.stack == null || L.stack.length < height)) {
|
||||
L.allocateStack(height);
|
||||
L.stackHeight = height;
|
||||
changed = true;
|
||||
}
|
||||
|
@ -441,7 +429,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
int[] R = new int[rhs.length];
|
||||
for (int j = 0; j < R.length; j++) {
|
||||
MachineState m = (MachineState) rhs[j];
|
||||
if (m.stack == null) {
|
||||
if (m.stack == null || m.stack.length < i+1) {
|
||||
R[j] = TOP;
|
||||
} else {
|
||||
R[j] = m.stack[i];
|
||||
|
@ -478,8 +466,8 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
MachineState L = (MachineState) lhs;
|
||||
// need we allocate lhs.locals?
|
||||
int nLocals = computeMeetNLocals(rhs);
|
||||
if (nLocals > -1 && L.locals == null) {
|
||||
L.allocateLocals();
|
||||
if (nLocals > -1 && (L.locals == null || L.locals.length < nLocals)) {
|
||||
L.allocateLocals(nLocals);
|
||||
}
|
||||
|
||||
// evaluate the element-wise meet over the locals.
|
||||
|
@ -577,6 +565,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
|
||||
void setTOP() {
|
||||
stackHeight = -1;
|
||||
stack = null;
|
||||
}
|
||||
|
||||
boolean isTOP() {
|
||||
|
@ -584,8 +573,8 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
}
|
||||
|
||||
public void push(int i) {
|
||||
if (stack == null)
|
||||
allocateStack();
|
||||
if (stack == null || stackHeight >= stack.length)
|
||||
allocateStack(stackHeight+1);
|
||||
stack[stackHeight++] = i;
|
||||
}
|
||||
|
||||
|
@ -607,13 +596,30 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
stack[stackHeight - 2] = temp;
|
||||
}
|
||||
|
||||
private void allocateStack() {
|
||||
stack = new int[maxStackHeight + 1];
|
||||
stackHeight = 0;
|
||||
private void allocateStack(int stackHeight) {
|
||||
if (stack == null) {
|
||||
stack = new int[stackHeight + 1 ];
|
||||
this.stackHeight = 0;
|
||||
} else {
|
||||
int[] newStack = new int[ Math.max(stack.length, stackHeight) * 2 + 1 ];
|
||||
System.arraycopy(stack, 0, newStack, 0, stack.length);
|
||||
stack = newStack;
|
||||
}
|
||||
}
|
||||
|
||||
private void allocateLocals() {
|
||||
locals = allocateNewLocalsArray();
|
||||
private void allocateLocals(int maxLocals) {
|
||||
int[] result = new int[maxLocals];
|
||||
int start = 0;
|
||||
if (locals != null) {
|
||||
System.arraycopy(locals, 0, result, 0, locals.length);
|
||||
start = locals.length;
|
||||
}
|
||||
|
||||
for (int i = start; i < maxLocals; i++) {
|
||||
result[i] = OPTIMISTIC ? TOP : BOTTOM;
|
||||
}
|
||||
|
||||
locals = result;
|
||||
}
|
||||
|
||||
public void clearStack() {
|
||||
|
@ -627,11 +633,11 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
* @param j
|
||||
*/
|
||||
public void setLocal(int i, int j) {
|
||||
if (locals == null) {
|
||||
if (locals == null || locals.length < i+1) {
|
||||
if (OPTIMISTIC && (j == TOP)) {
|
||||
return;
|
||||
} else {
|
||||
allocateLocals();
|
||||
allocateLocals(i+1);
|
||||
}
|
||||
}
|
||||
locals[i] = j;
|
||||
|
@ -642,7 +648,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
* @return the number of the symbol corresponding to local i
|
||||
*/
|
||||
public int getLocal(int i) {
|
||||
if (locals == null) {
|
||||
if (locals == null || locals.length < i+1) {
|
||||
if (OPTIMISTIC) {
|
||||
return TOP;
|
||||
} else {
|
||||
|
@ -660,7 +666,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
stack[i] = to;
|
||||
|
||||
if (locals != null)
|
||||
for (int i = 0; i < maxLocals; i++)
|
||||
for (int i = 0; i < locals.length; i++)
|
||||
if (locals[i] == from)
|
||||
locals[i] = to;
|
||||
}
|
||||
|
@ -672,7 +678,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
return true;
|
||||
|
||||
if (locals != null)
|
||||
for (int i = 0; i < maxLocals; i++)
|
||||
for (int i = 0; i < locals.length; i++)
|
||||
if (locals[i] == val)
|
||||
return true;
|
||||
|
||||
|
@ -692,7 +698,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
result.append(array2StringBuffer(stack, stackHeight));
|
||||
}
|
||||
result.append("L");
|
||||
result.append(array2StringBuffer(locals, maxLocals));
|
||||
result.append(array2StringBuffer(locals, locals.length));
|
||||
result.append(">");
|
||||
return result.toString();
|
||||
}
|
||||
|
@ -775,14 +781,6 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
|
||||
}
|
||||
|
||||
public int[] allocateNewLocalsArray() {
|
||||
int[] result = new int[maxLocals];
|
||||
for (int i = 0; i < maxLocals; i++) {
|
||||
result[i] = OPTIMISTIC ? TOP : BOTTOM;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface which defines a flow function for a basic block
|
||||
*/
|
||||
|
|
|
@ -31,7 +31,7 @@ public class ConeType extends TypeAbstraction {
|
|||
if (type == null) {
|
||||
throw new IllegalArgumentException("type is null");
|
||||
}
|
||||
assert type.getReference().isReferenceType();
|
||||
assert type.getReference().isReferenceType() : type;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ public abstract class TypeAbstraction implements ContextItem {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JavaTypeAbstraction.TOP";
|
||||
return "WalaTypeAbstraction.TOP";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -538,7 +538,9 @@ public class TypeInference extends SSAInference<TypeVariable> implements FixedPo
|
|||
TypeReference type = instruction.getDeclaredFieldType();
|
||||
|
||||
if (doPrimitives && type.isPrimitiveType()) {
|
||||
result = new DeclaredTypeOperator(language.getPrimitive(type));
|
||||
PrimitiveType p = language.getPrimitive(type);
|
||||
assert p != null : "no type for " + type;
|
||||
result = new DeclaredTypeOperator(p);
|
||||
} else {
|
||||
IClass klass = cha.lookupClass(type);
|
||||
if (klass == null) {
|
||||
|
@ -593,10 +595,18 @@ public class TypeInference extends SSAInference<TypeVariable> implements FixedPo
|
|||
// be pessimistic
|
||||
typeAbs = BOTTOM;
|
||||
} else {
|
||||
if (typeAbs == null) {
|
||||
typeAbs = new ConeType(klass);
|
||||
} else {
|
||||
typeAbs = typeAbs.meet(new ConeType(klass));
|
||||
TypeAbstraction x = null;
|
||||
if (doPrimitives && type.isPrimitiveType()) {
|
||||
x = language.getPrimitive(type);
|
||||
} else if (type.isReferenceType()) {
|
||||
x = new ConeType(klass);
|
||||
}
|
||||
if (x != null) {
|
||||
if (typeAbs == null) {
|
||||
typeAbs = x;
|
||||
} else {
|
||||
typeAbs = typeAbs.meet(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -663,4 +663,5 @@ public abstract class AbstractCFG<I, T extends IBasicBlock<I>> implements Contro
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -59,7 +59,11 @@ public class ShrikeCFG extends AbstractCFG<IInstruction, ShrikeCFG.BasicBlock> {
|
|||
*/
|
||||
final private Set<ExceptionHandler> exceptionHandlers = HashSetFactory.make(10);
|
||||
|
||||
public ShrikeCFG(IBytecodeMethod method) throws IllegalArgumentException {
|
||||
public static ShrikeCFG make(IBytecodeMethod m) {
|
||||
return new ShrikeCFG(m);
|
||||
}
|
||||
|
||||
private ShrikeCFG(IBytecodeMethod method) throws IllegalArgumentException {
|
||||
super(method);
|
||||
if (method == null) {
|
||||
throw new IllegalArgumentException("method cannot be null");
|
||||
|
@ -70,12 +74,12 @@ public class ShrikeCFG extends AbstractCFG<IInstruction, ShrikeCFG.BasicBlock> {
|
|||
init();
|
||||
computeI2BMapping();
|
||||
computeEdges();
|
||||
|
||||
|
||||
if (DEBUG) {
|
||||
System.err.println(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IBytecodeMethod getMethod() {
|
||||
return method;
|
||||
|
@ -426,7 +430,11 @@ public class ShrikeCFG extends AbstractCFG<IInstruction, ShrikeCFG.BasicBlock> {
|
|||
// this is the last non-exit block
|
||||
return getInstructions().length - 1;
|
||||
} else {
|
||||
BasicBlock next = getNode(getNumber() + 1);
|
||||
int i = 1;
|
||||
BasicBlock next;
|
||||
do {
|
||||
next = getNode(getNumber() + i);
|
||||
} while (next == null);
|
||||
return next.getFirstInstructionIndex() - 1;
|
||||
}
|
||||
}
|
||||
|
@ -502,14 +510,6 @@ public class ShrikeCFG extends AbstractCFG<IInstruction, ShrikeCFG.BasicBlock> {
|
|||
return s.toString();
|
||||
}
|
||||
|
||||
public int getMaxStackHeight() {
|
||||
return method.getMaxStackHeight();
|
||||
}
|
||||
|
||||
public int getMaxLocals() {
|
||||
return method.getMaxLocals();
|
||||
}
|
||||
|
||||
public Set<ExceptionHandler> getExceptionHandlers() {
|
||||
return exceptionHandlers;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import java.util.HashSet;
|
|||
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
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;
|
||||
|
@ -50,7 +49,7 @@ public class ArrayClass implements IClass, Constants {
|
|||
Assertions.UNREACHABLE("caller should not attempt to create an array with type " + type);
|
||||
}
|
||||
} else {
|
||||
assert loader.getReference().equals(ClassLoaderReference.Primordial);
|
||||
// assert loader.getReference().equals(ClassLoaderReference.Primordial);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,7 +122,7 @@ public class ArrayClass implements IClass, Constants {
|
|||
* @see com.ibm.wala.classLoader.IClass#getMethod(com.ibm.wala.classLoader.Selector)
|
||||
*/
|
||||
public IMethod getMethod(Selector sig) {
|
||||
return loader.lookupClass(getClassLoader().getLanguage().getRootType().getName()).getMethod(sig);
|
||||
return cha.lookupClass(getClassLoader().getLanguage().getRootType()).getMethod(sig);
|
||||
}
|
||||
|
||||
public IField getField(Atom name) {
|
||||
|
|
|
@ -12,6 +12,10 @@ package com.ibm.wala.classLoader;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.util.warnings.Warning;
|
||||
import com.ibm.wala.util.warnings.Warnings;
|
||||
|
||||
/**
|
||||
* Module representing a directory of .class files
|
||||
*/
|
||||
|
@ -27,8 +31,19 @@ public class BinaryDirectoryTreeModule extends DirectoryTreeModule {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected FileModule makeFile(File file) {
|
||||
return new ClassFileModule(file);
|
||||
protected FileModule makeFile(final File file) {
|
||||
try {
|
||||
return new ClassFileModule(file);
|
||||
} catch (InvalidClassFileException e) {
|
||||
Warnings.add(new Warning(Warning.MODERATE) {
|
||||
|
||||
@Override
|
||||
public String getMsg() {
|
||||
return "Invalid class file at path " + file.getAbsolutePath();
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -279,7 +279,7 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
|
|||
/*
|
||||
* @see com.ibm.wala.classLoader.IClass#getDirectInterfaces()
|
||||
*/
|
||||
public Collection<IClass> getDirectInterfaces() {
|
||||
public Collection<? extends IClass> getDirectInterfaces() {
|
||||
return array2IClassSet(interfaceNames);
|
||||
}
|
||||
|
||||
|
@ -416,9 +416,9 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
|
|||
* @return Collection of IClasses, representing the interfaces this class implements.
|
||||
*/
|
||||
protected Collection<IClass> computeAllInterfacesAsCollection() {
|
||||
Collection<IClass> c = getDirectInterfaces();
|
||||
Collection<? extends IClass> c = getDirectInterfaces();
|
||||
Set<IClass> result = HashSetFactory.make();
|
||||
for (Iterator<IClass> it = c.iterator(); it.hasNext();) {
|
||||
for (Iterator<? extends IClass> it = c.iterator(); it.hasNext();) {
|
||||
IClass klass = it.next();
|
||||
if (klass.isInterface()) {
|
||||
result.add(klass);
|
||||
|
|
|
@ -14,7 +14,6 @@ package com.ibm.wala.classLoader;
|
|||
import java.io.File;
|
||||
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.shrike.ShrikeClassReaderHandle;
|
||||
import com.ibm.wala.util.strings.ImmutableByteArray;
|
||||
|
||||
|
@ -25,18 +24,10 @@ public class ClassFileModule extends FileModule {
|
|||
|
||||
private final String className;
|
||||
|
||||
public ClassFileModule(File f) {
|
||||
public ClassFileModule(File f) throws InvalidClassFileException {
|
||||
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) {
|
||||
System.err.println("Invalid class file: " + f.getAbsolutePath());
|
||||
e.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
ImmutableByteArray name = ImmutableByteArray.make(reader.get().getName());
|
||||
className = name.toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,6 @@ public class ClassLoaderImpl implements IClassLoader {
|
|||
}
|
||||
TreeSet<ModuleEntry> sortedEntries = new TreeSet<ModuleEntry>(HashCodeComparator.instance());
|
||||
sortedEntries.addAll(Iterator2Collection.toSet(M.getEntries()));
|
||||
|
||||
HashSet<ModuleEntry> result = HashSetFactory.make();
|
||||
for (Iterator it = sortedEntries.iterator(); it.hasNext();) {
|
||||
ModuleEntry entry = (ModuleEntry) it.next();
|
||||
|
|
|
@ -36,6 +36,9 @@ public abstract class DirectoryTreeModule implements Module {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns null if unsuccessful in creating FileModule
|
||||
*/
|
||||
protected abstract FileModule makeFile(File file);
|
||||
|
||||
protected abstract boolean includeFile(File file);
|
||||
|
@ -48,7 +51,10 @@ public abstract class DirectoryTreeModule implements Module {
|
|||
if (files[i].isDirectory()) {
|
||||
result.addAll(getEntriesRecursive(files[i]));
|
||||
} else if (includeFile(files[i])) {
|
||||
result.add(makeFile(files[i]));
|
||||
FileModule fileModule = makeFile(files[i]);
|
||||
if (fileModule != null) {
|
||||
result.add(fileModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -70,7 +70,7 @@ public interface IClass extends IClassHierarchyDweller {
|
|||
* @return Collection of (IClass) interfaces this class directly implements. If this class is an interface, returns the interfaces
|
||||
* it immediately extends.
|
||||
*/
|
||||
Collection<IClass> getDirectInterfaces();
|
||||
Collection<? extends IClass> getDirectInterfaces();
|
||||
|
||||
/**
|
||||
* @return Collection of (IClass) interfaces this class implements, including all ancestors of interfaces immediately implemented.
|
||||
|
|
|
@ -82,16 +82,6 @@ public interface IMethod extends IMember, ContextItem {
|
|||
*/
|
||||
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
|
||||
*/
|
||||
|
|
|
@ -128,13 +128,14 @@ public class JavaLanguage extends LanguageImpl implements BytecodeLanguage, Cons
|
|||
};
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues) {
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues, boolean isPEI) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types) {
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types, boolean isPEI) {
|
||||
assert types.length == 1;
|
||||
return new SSACheckCastInstruction(result, val, types) {
|
||||
assert isPEI;
|
||||
return new SSACheckCastInstruction(result, val, types, true) {
|
||||
@Override
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
return getClassCastException();
|
||||
|
@ -142,12 +143,14 @@ public class JavaLanguage extends LanguageImpl implements BytecodeLanguage, Cons
|
|||
};
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue) {
|
||||
return CheckCastInstruction(result, val, new int[]{ typeValue });
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue, boolean isPEI) {
|
||||
assert isPEI;
|
||||
return CheckCastInstruction(result, val, new int[]{ typeValue }, true);
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type) {
|
||||
return CheckCastInstruction(result, val, new TypeReference[]{ type });
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type, boolean isPEI) {
|
||||
assert isPEI;
|
||||
return CheckCastInstruction(result, val, new TypeReference[]{ type }, true);
|
||||
}
|
||||
|
||||
public SSAComparisonInstruction ComparisonInstruction(IComparisonInstruction.Operator operator, int result, int val1, int val2) {
|
||||
|
|
|
@ -33,7 +33,7 @@ public class ShrikeIRFactory implements IRFactory<IBytecodeMethod> {
|
|||
public final static boolean buildLocalMap = true;
|
||||
|
||||
public ControlFlowGraph makeCFG(final IBytecodeMethod method, Context C) {
|
||||
return new ShrikeCFG(method);
|
||||
return ShrikeCFG.make(method);
|
||||
}
|
||||
|
||||
public IR makeIR(final IBytecodeMethod method, Context C, final SSAOptions options) throws IllegalArgumentException {
|
||||
|
|
|
@ -35,6 +35,7 @@ import com.ibm.wala.classLoader.Module;
|
|||
import com.ibm.wala.classLoader.SourceDirectoryTreeModule;
|
||||
import com.ibm.wala.classLoader.SourceFileModule;
|
||||
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
|
@ -202,8 +203,9 @@ public class AnalysisScope {
|
|||
|
||||
/**
|
||||
* Add a class file to the scope for a loader
|
||||
* @throws InvalidClassFileException
|
||||
*/
|
||||
public void addClassFileToScope(ClassLoaderReference loader, File file) throws IllegalArgumentException {
|
||||
public void addClassFileToScope(ClassLoaderReference loader, File file) throws IllegalArgumentException, InvalidClassFileException {
|
||||
List<Module> s = MapUtil.findOrCreateList(moduleMap, loader);
|
||||
s.add(new ClassFileModule(file));
|
||||
}
|
||||
|
|
|
@ -330,10 +330,10 @@ public abstract class AbstractRootMethod extends SyntheticMethod {
|
|||
return result;
|
||||
}
|
||||
|
||||
public int addCheckcast(TypeReference[] types, int rv) {
|
||||
public int addCheckcast(TypeReference[] types, int rv, boolean isPEI) {
|
||||
int lv = nextLocal++;
|
||||
|
||||
statements.add(insts.CheckCastInstruction(lv, rv, types));
|
||||
statements.add(insts.CheckCastInstruction(lv, rv, types, isPEI));
|
||||
return lv;
|
||||
}
|
||||
|
||||
|
|
|
@ -747,13 +747,22 @@ public class ClassHierarchy implements IClassHierarchy {
|
|||
Assertions.UNREACHABLE();
|
||||
superB = null;
|
||||
}
|
||||
while (a != null) {
|
||||
if (superB.contains(a)) {
|
||||
return a;
|
||||
IClass aa = a;
|
||||
while (aa != null) {
|
||||
if (superB.contains(aa)) {
|
||||
return aa;
|
||||
}
|
||||
a = a.getSuperclass();
|
||||
aa = aa.getSuperclass();
|
||||
}
|
||||
Assertions.UNREACHABLE("getLeastCommonSuperclass " + tempA + " " + b);
|
||||
Set<IClass> superA;
|
||||
try {
|
||||
superA = getSuperclasses(a);
|
||||
} catch (ClassHierarchyException e1) {
|
||||
e1.printStackTrace();
|
||||
Assertions.UNREACHABLE();
|
||||
superA = null;
|
||||
}
|
||||
Assertions.UNREACHABLE("getLeastCommonSuperclass " + tempA + " " + b + ": " + superA + ", " + superB);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ public abstract class IR {
|
|||
newSiteMapping.put(((SSANewInstruction) x).getNewSite(), new Integer(i));
|
||||
}
|
||||
if (x.isPEI()) {
|
||||
peiMapping.put(new ProgramCounter(cfg.getProgramCounter(i)), new Integer(i));
|
||||
peiMapping.put(new ProgramCounter(cfg.getProgramCounter(i)), new Integer(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,8 +105,8 @@ public class SSABuilder extends AbstractIntStackMachine {
|
|||
private SSABuilder(IBytecodeMethod method, SSACFG cfg, ShrikeCFG scfg, SSAInstruction[] instructions, SymbolTable symbolTable,
|
||||
boolean buildLocalMap, SSAPiNodePolicy piNodePolicy) {
|
||||
super(scfg);
|
||||
localMap = buildLocalMap ? new SSA2LocalMap(scfg, instructions.length, cfg.getNumberOfNodes(), maxLocals) : null;
|
||||
init(new SymbolTableMeeter(symbolTable, cfg, instructions, scfg), new SymbolicPropagator(scfg, instructions, symbolTable,
|
||||
localMap = buildLocalMap ? new SSA2LocalMap(scfg, instructions.length, cfg.getNumberOfNodes()) : null;
|
||||
init(new SymbolTableMeeter(symbolTable, cfg, scfg), new SymbolicPropagator(scfg, instructions, symbolTable,
|
||||
localMap, cfg, piNodePolicy));
|
||||
this.method = method;
|
||||
this.symbolTable = symbolTable;
|
||||
|
@ -120,15 +120,13 @@ public class SSABuilder extends AbstractIntStackMachine {
|
|||
|
||||
final SSACFG cfg;
|
||||
|
||||
final SSAInstruction[] instructions;
|
||||
|
||||
final SymbolTable symbolTable;
|
||||
|
||||
final ShrikeCFG shrikeCFG;
|
||||
|
||||
SymbolTableMeeter(SymbolTable symbolTable, SSACFG cfg, SSAInstruction[] instructions, ShrikeCFG shrikeCFG) {
|
||||
SymbolTableMeeter(SymbolTable symbolTable, SSACFG cfg, ShrikeCFG shrikeCFG) {
|
||||
this.cfg = cfg;
|
||||
this.instructions = instructions;
|
||||
this.symbolTable = symbolTable;
|
||||
this.shrikeCFG = shrikeCFG;
|
||||
}
|
||||
|
@ -328,17 +326,19 @@ public class SSABuilder extends AbstractIntStackMachine {
|
|||
}
|
||||
|
||||
private void emitInstruction(SSAInstruction s) {
|
||||
instructions[getCurrentInstructionIndex()] = s;
|
||||
for (int i = 0; i < s.getNumberOfDefs(); i++) {
|
||||
if (creators.length < (s.getDef(i) + 1)) {
|
||||
SSAInstruction[] arr = new SSAInstruction[2 * s.getDef(i)];
|
||||
System.arraycopy(creators, 0, arr, 0, creators.length);
|
||||
creators = arr;
|
||||
}
|
||||
if (s != null) {
|
||||
instructions[getCurrentInstructionIndex()] = s;
|
||||
for (int i = 0; i < s.getNumberOfDefs(); i++) {
|
||||
if (creators.length < (s.getDef(i) + 1)) {
|
||||
SSAInstruction[] arr = new SSAInstruction[2 * s.getDef(i)];
|
||||
System.arraycopy(creators, 0, arr, 0, creators.length);
|
||||
creators = arr;
|
||||
}
|
||||
|
||||
assert s.getDef(i) != -1 : "invalid def " + i + " for " + s;
|
||||
assert s.getDef(i) != -1 : "invalid def " + i + " for " + s;
|
||||
|
||||
creators[s.getDef(i)] = s;
|
||||
creators[s.getDef(i)] = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -451,7 +451,7 @@ public class SSABuilder extends AbstractIntStackMachine {
|
|||
for(int i = 0; i < typeNames.length; i++) {
|
||||
t[i] = ShrikeUtil.makeTypeReference(loader, typeNames[i]);
|
||||
}
|
||||
emitInstruction(insts.CheckCastInstruction(result, val, t));
|
||||
emitInstruction(insts.CheckCastInstruction(result, val, t, instruction.isPEI()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -933,20 +933,14 @@ public class SSABuilder extends AbstractIntStackMachine {
|
|||
*/
|
||||
private final int[][] block2LocalState;
|
||||
|
||||
/**
|
||||
* maximum number of locals used at any program point
|
||||
*/
|
||||
private final int maxLocals;
|
||||
|
||||
/**
|
||||
* @param nInstructions number of instructions in the bytecode for this method
|
||||
* @param nBlocks number of basic blocks in the CFG
|
||||
*/
|
||||
SSA2LocalMap(ShrikeCFG shrikeCfg, int nInstructions, int nBlocks, int maxLocals) {
|
||||
SSA2LocalMap(ShrikeCFG shrikeCfg, int nInstructions, int nBlocks) {
|
||||
shrikeCFG = shrikeCfg;
|
||||
localStoreMap = new IntPair[nInstructions];
|
||||
block2LocalState = new int[nBlocks][];
|
||||
this.maxLocals = maxLocals;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -954,11 +948,6 @@ public class SSABuilder extends AbstractIntStackMachine {
|
|||
* a particular local number
|
||||
*/
|
||||
void startRange(int pc, int localNumber, int valueNumber) {
|
||||
int max = shrikeCFG.getMethod().getMaxLocals();
|
||||
if (localNumber >= max) {
|
||||
assert false : "invalid local " + localNumber + ">" + max;
|
||||
}
|
||||
|
||||
localStoreMap[pc] = new IntPair(valueNumber, localNumber);
|
||||
}
|
||||
|
||||
|
@ -1002,6 +991,27 @@ public class SSABuilder extends AbstractIntStackMachine {
|
|||
}
|
||||
}
|
||||
|
||||
public int[] allocateNewLocalsArray(int maxLocals) {
|
||||
int[] result = new int[maxLocals];
|
||||
for (int i = 0; i < maxLocals; i++) {
|
||||
result[i] = OPTIMISTIC ? TOP : BOTTOM;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int[] setLocal(int[] locals, int localNumber, int valueNumber) {
|
||||
if (locals == null) {
|
||||
locals = allocateNewLocalsArray(localNumber + 1);
|
||||
} else if (locals.length <= localNumber) {
|
||||
int[] newLocals = allocateNewLocalsArray(2 * Math.max(locals.length, localNumber) + 1);
|
||||
System.arraycopy(locals, 0, newLocals, 0, locals.length);
|
||||
locals = newLocals;
|
||||
}
|
||||
|
||||
locals[localNumber] = valueNumber;
|
||||
|
||||
return locals;
|
||||
}
|
||||
/**
|
||||
* @param pc a program counter (index into ShrikeBT instruction array)
|
||||
* @param vn a value number
|
||||
|
@ -1015,26 +1025,15 @@ public class SSABuilder extends AbstractIntStackMachine {
|
|||
// walk forward from the first instruction to reconstruct the
|
||||
// state of the locals at this pc
|
||||
int[] locals = block2LocalState[bb.getNumber()];
|
||||
if (locals == null) {
|
||||
locals = allocateNewLocalsArray();
|
||||
}
|
||||
for (int i = firstInstruction; i <= pc; i++) {
|
||||
if (localStoreMap[i] != null) {
|
||||
IntPair p = localStoreMap[i];
|
||||
locals[p.getY()] = p.getX();
|
||||
setLocal(locals, p.getY(), p.getX());
|
||||
}
|
||||
}
|
||||
return extractIndices(locals, vn);
|
||||
}
|
||||
|
||||
public int[] allocateNewLocalsArray() {
|
||||
int[] result = new int[maxLocals];
|
||||
for (int i = 0; i < maxLocals; i++) {
|
||||
result[i] = OPTIMISTIC ? TOP : BOTTOM;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the indices i s.t. x[i] == y, or null if none found.
|
||||
*/
|
||||
|
|
|
@ -38,16 +38,22 @@ public abstract class SSACheckCastInstruction extends SSAInstruction {
|
|||
*/
|
||||
private final TypeReference[] declaredResultTypes;
|
||||
|
||||
/**
|
||||
* whether the type test throws an exception
|
||||
*/
|
||||
private final boolean isPEI;
|
||||
|
||||
/**
|
||||
* @param result A new value number def'fed by this instruction when the type check succeeds.
|
||||
* @param val The value being checked by this instruction
|
||||
* @param type The type which this instruction checks
|
||||
*/
|
||||
protected SSACheckCastInstruction(int result, int val, TypeReference[] types) {
|
||||
protected SSACheckCastInstruction(int result, int val, TypeReference[] types, boolean isPEI) {
|
||||
super();
|
||||
this.result = result;
|
||||
this.val = val;
|
||||
this.declaredResultTypes = types;
|
||||
this.isPEI = isPEI;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,7 +64,7 @@ public abstract class SSACheckCastInstruction extends SSAInstruction {
|
|||
if (uses != null && uses.length == 0) {
|
||||
throw new IllegalArgumentException("(uses != null) and (uses.length == 0)");
|
||||
}
|
||||
return insts.CheckCastInstruction(defs == null ? result : defs[0], uses == null ? val : uses[0], declaredResultTypes);
|
||||
return insts.CheckCastInstruction(defs == null ? result : defs[0], uses == null ? val : uses[0], declaredResultTypes, isPEI);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -162,7 +168,7 @@ public abstract class SSACheckCastInstruction extends SSAInstruction {
|
|||
*/
|
||||
@Override
|
||||
public boolean isPEI() {
|
||||
return true;
|
||||
return isPEI;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -40,13 +40,13 @@ public interface SSAInstructionFactory {
|
|||
SSABinaryOpInstruction BinaryOpInstruction(IBinaryOpInstruction.IOperator operator, boolean overflow, boolean unsigned,
|
||||
int result, int val1, int val2, boolean mayBeInteger);
|
||||
|
||||
SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues);
|
||||
SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues, boolean isPEI);
|
||||
|
||||
SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue);
|
||||
SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue, boolean isPEI);
|
||||
|
||||
SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types);
|
||||
SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types, boolean isPEI);
|
||||
|
||||
SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type);
|
||||
SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type, boolean isPEI);
|
||||
|
||||
SSAComparisonInstruction ComparisonInstruction(IComparisonInstruction.Operator operator, int result, int val1, int val2);
|
||||
|
||||
|
|
|
@ -261,7 +261,10 @@ public final class TypeName implements Serializable {
|
|||
}
|
||||
if (!innermostPrimitive) {
|
||||
result.append("L");
|
||||
} else if (packageName != null && innermostPrimitive) {
|
||||
result.append("P");
|
||||
}
|
||||
|
||||
if (packageName != null) {
|
||||
result.append(packageName.toString());
|
||||
result.append("/");
|
||||
|
@ -279,7 +282,10 @@ public final class TypeName implements Serializable {
|
|||
}
|
||||
if (!innermostPrimitive) {
|
||||
result.append("L");
|
||||
} else if (packageName != null && innermostPrimitive) {
|
||||
result.append("P");
|
||||
}
|
||||
|
||||
if (packageName != null) {
|
||||
result.append(packageName.toUnicodeString());
|
||||
result.append("/");
|
||||
|
|
|
@ -329,7 +329,11 @@ public final class TypeReference implements Serializable {
|
|||
public final static TypeReference Unknown = findOrCreate(ClassLoaderReference.Primordial, UnknownName);
|
||||
|
||||
private static TypeReference makePrimitive(TypeName n) {
|
||||
TypeReference t = new TypeReference(ClassLoaderReference.Primordial, n);
|
||||
return makePrimitive(ClassLoaderReference.Primordial, n);
|
||||
}
|
||||
|
||||
public static TypeReference makePrimitive(ClassLoaderReference cl, TypeName n) {
|
||||
TypeReference t = new TypeReference(cl, n);
|
||||
primitiveMap.put(t.name, t);
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,10 @@
|
|||
*******************************************************************************/
|
||||
package com.ibm.wala.types.annotations;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
|
||||
/**
|
||||
* Represents a Java 5.0 class file annotation
|
||||
|
@ -18,25 +21,40 @@ import com.ibm.wala.types.TypeReference;
|
|||
public class Annotation {
|
||||
|
||||
private final TypeReference type;
|
||||
private final Pair<TypeReference, Object>[] arguments;
|
||||
|
||||
private Annotation(TypeReference type) {
|
||||
private Annotation(TypeReference type, Pair<TypeReference, Object>[] arguments) {
|
||||
this.type = type;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public static Annotation make(TypeReference t, Pair<TypeReference, Object>[] arguments) {
|
||||
return new Annotation(t, arguments);
|
||||
}
|
||||
|
||||
public static Annotation make(TypeReference t) {
|
||||
return new Annotation(t);
|
||||
return make(t, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Annotation type " + type;
|
||||
StringBuffer sb = new StringBuffer("Annotation type " + type);
|
||||
if (arguments != null) {
|
||||
sb.append("[");
|
||||
for(Pair<TypeReference, Object> arg : arguments) {
|
||||
sb.append(" " + arg.fst.getName().getClassName() + ":" + arg.snd);
|
||||
}
|
||||
sb.append(" ]");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int PRIME = 31;
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = PRIME * result + ((type == null) ? 0 : type.hashCode());
|
||||
result = prime * result + Arrays.hashCode(arguments);
|
||||
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -48,7 +66,9 @@ public class Annotation {
|
|||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final Annotation other = (Annotation) obj;
|
||||
Annotation other = (Annotation) obj;
|
||||
if (!Arrays.equals(arguments, other.arguments))
|
||||
return false;
|
||||
if (type == null) {
|
||||
if (other.type != null)
|
||||
return false;
|
||||
|
@ -57,7 +77,10 @@ public class Annotation {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
public Pair<TypeReference, Object>[] getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public TypeReference getType() {
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import com.ibm.wala.classLoader.SourceDirectoryTreeModule;
|
|||
import com.ibm.wala.core.plugin.CorePlugin;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.properties.WalaProperties;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.io.FileProvider;
|
||||
|
@ -108,7 +109,11 @@ public class AnalysisScopeReader {
|
|||
String entryPathname = toks.nextToken();
|
||||
if ("classFile".equals(entryType)) {
|
||||
File cf = FileProvider.getFile(entryPathname, javaLoader);
|
||||
scope.addClassFileToScope(walaLoader, cf);
|
||||
try {
|
||||
scope.addClassFileToScope(walaLoader, cf);
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE(e.toString());
|
||||
}
|
||||
} else if ("sourceFile".equals(entryType)) {
|
||||
File sf = FileProvider.getFile(entryPathname, javaLoader);
|
||||
scope.addSourceFileToScope(walaLoader, sf, entryPathname);
|
||||
|
@ -197,6 +202,8 @@ public class AnalysisScopeReader {
|
|||
}
|
||||
} catch (IOException e) {
|
||||
Assertions.UNREACHABLE(e.toString());
|
||||
} catch (InvalidClassFileException e) {
|
||||
Assertions.UNREACHABLE(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ package com.ibm.wala.util.io;// 5724-D15
|
|||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
|
@ -263,6 +264,23 @@ public class FileProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public static InputStream getInputStreamFromClassLoader(String fileName, ClassLoader loader) throws FileNotFoundException {
|
||||
if (loader == null) {
|
||||
throw new IllegalArgumentException("null loader");
|
||||
}
|
||||
if (fileName == null) {
|
||||
throw new IllegalArgumentException("null fileName");
|
||||
}
|
||||
InputStream is = loader.getResourceAsStream(fileName);
|
||||
if (is == null) {
|
||||
throw new FileNotFoundException(fileName);
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the jar file packaged with this plug-in of the given name, or null
|
||||
* if not found: wrapped as a JarFileModule or a NestedJarFileModule
|
||||
|
|
|
@ -1,125 +1,125 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeExpansionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
|
||||
public class CgPanel extends JSplitPane{
|
||||
|
||||
private final CallGraph cg;
|
||||
|
||||
public CgPanel(CallGraph cg) {
|
||||
this.cg = cg;
|
||||
this.setDividerLocation(250);
|
||||
JTree tree = buildTree();
|
||||
this.setLeftComponent(new JScrollPane(tree));
|
||||
|
||||
|
||||
final IrAndSourceViewer irViewer = new IrAndSourceViewer(cg);
|
||||
this.setRightComponent(irViewer.getComponent());
|
||||
|
||||
tree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
TreePath newLeadSelectionPath = e.getNewLeadSelectionPath();
|
||||
if (null == newLeadSelectionPath){
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent();
|
||||
Object userObject = treeNode.getUserObject();
|
||||
if (userObject instanceof CGNode) {
|
||||
CGNode node = (CGNode) userObject;
|
||||
IR ir = node.getIR();
|
||||
irViewer.setIR(ir);
|
||||
} else if (userObject instanceof CallSiteReference){
|
||||
CGNode parentNode = (CGNode) ((DefaultMutableTreeNode) treeNode.getParent()).getUserObject();
|
||||
IR ir = parentNode.getIR();
|
||||
irViewer.setIRAndPc(ir, ((CallSiteReference) userObject).getProgramCounter());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private JTree buildTree() {
|
||||
|
||||
CGNode cgRoot = cg.getFakeRootNode();
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode(cgRoot);
|
||||
|
||||
expandNode(root);
|
||||
JTree tree = new JTree(root);
|
||||
|
||||
tree.addTreeExpansionListener(new TreeExpansionListener() {
|
||||
|
||||
public void treeExpanded(TreeExpansionEvent event) {
|
||||
TreePath path = event.getPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||
expandNode(lastNode);
|
||||
}
|
||||
|
||||
public void treeCollapsed(TreeExpansionEvent event) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode) {
|
||||
expandNode(treeNode, 3);
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode, int rec) {
|
||||
if (rec == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (treeNode.getChildCount() == 0) {
|
||||
List<DefaultMutableTreeNode> newChilds = new ArrayList<DefaultMutableTreeNode>();
|
||||
Object userObject = treeNode.getUserObject();
|
||||
if (userObject instanceof CGNode) {
|
||||
CGNode cgNode = (CGNode) userObject;
|
||||
for (Iterator<CallSiteReference> iter = cgNode.iterateCallSites(); iter.hasNext();) {
|
||||
CallSiteReference csr = iter.next();
|
||||
newChilds.add(new DefaultMutableTreeNode(csr));
|
||||
}
|
||||
} else {
|
||||
assert userObject instanceof CallSiteReference;
|
||||
CallSiteReference csr = (CallSiteReference) userObject;
|
||||
CGNode cgNode = (CGNode) ((DefaultMutableTreeNode) treeNode.getParent()).getUserObject();
|
||||
Set<CGNode> successors = cg.getPossibleTargets(cgNode, csr);
|
||||
for (CGNode successor : successors) {
|
||||
newChilds.add(new DefaultMutableTreeNode(successor));
|
||||
}
|
||||
}
|
||||
|
||||
for (DefaultMutableTreeNode newChild : newChilds) {
|
||||
treeNode.add(newChild);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < treeNode.getChildCount(); i++) {
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeNode.getChildAt(i);
|
||||
expandNode(child, rec - 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeExpansionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
|
||||
public class CgPanel extends JSplitPane{
|
||||
|
||||
private final CallGraph cg;
|
||||
|
||||
public CgPanel(CallGraph cg) {
|
||||
this.cg = cg;
|
||||
this.setDividerLocation(250);
|
||||
JTree tree = buildTree();
|
||||
this.setLeftComponent(new JScrollPane(tree));
|
||||
|
||||
|
||||
final IrAndSourceViewer irViewer = new IrAndSourceViewer(cg);
|
||||
this.setRightComponent(irViewer.getComponent());
|
||||
|
||||
tree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
TreePath newLeadSelectionPath = e.getNewLeadSelectionPath();
|
||||
if (null == newLeadSelectionPath){
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent();
|
||||
Object userObject = treeNode.getUserObject();
|
||||
if (userObject instanceof CGNode) {
|
||||
CGNode node = (CGNode) userObject;
|
||||
IR ir = node.getIR();
|
||||
irViewer.setIR(ir);
|
||||
} else if (userObject instanceof CallSiteReference){
|
||||
CGNode parentNode = (CGNode) ((DefaultMutableTreeNode) treeNode.getParent()).getUserObject();
|
||||
IR ir = parentNode.getIR();
|
||||
irViewer.setIRAndPc(ir, ((CallSiteReference) userObject).getProgramCounter());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private JTree buildTree() {
|
||||
|
||||
CGNode cgRoot = cg.getFakeRootNode();
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode(cgRoot);
|
||||
|
||||
expandNode(root);
|
||||
JTree tree = new JTree(root);
|
||||
|
||||
tree.addTreeExpansionListener(new TreeExpansionListener() {
|
||||
|
||||
public void treeExpanded(TreeExpansionEvent event) {
|
||||
TreePath path = event.getPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||
expandNode(lastNode);
|
||||
}
|
||||
|
||||
public void treeCollapsed(TreeExpansionEvent event) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode) {
|
||||
expandNode(treeNode, 3);
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode, int rec) {
|
||||
if (rec == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (treeNode.getChildCount() == 0) {
|
||||
List<DefaultMutableTreeNode> newChilds = new ArrayList<DefaultMutableTreeNode>();
|
||||
Object userObject = treeNode.getUserObject();
|
||||
if (userObject instanceof CGNode) {
|
||||
CGNode cgNode = (CGNode) userObject;
|
||||
for (Iterator<CallSiteReference> iter = cgNode.iterateCallSites(); iter.hasNext();) {
|
||||
CallSiteReference csr = iter.next();
|
||||
newChilds.add(new DefaultMutableTreeNode(csr));
|
||||
}
|
||||
} else {
|
||||
assert userObject instanceof CallSiteReference;
|
||||
CallSiteReference csr = (CallSiteReference) userObject;
|
||||
CGNode cgNode = (CGNode) ((DefaultMutableTreeNode) treeNode.getParent()).getUserObject();
|
||||
Set<CGNode> successors = cg.getPossibleTargets(cgNode, csr);
|
||||
for (CGNode successor : successors) {
|
||||
newChilds.add(new DefaultMutableTreeNode(successor));
|
||||
}
|
||||
}
|
||||
|
||||
for (DefaultMutableTreeNode newChild : newChilds) {
|
||||
treeNode.add(newChild);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < treeNode.getChildCount(); i++) {
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeNode.getChildAt(i);
|
||||
expandNode(child, rec - 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,104 +1,104 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeExpansionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
|
||||
public class ChaPanel extends JSplitPane {
|
||||
|
||||
private final IClassHierarchy cha;
|
||||
|
||||
public ChaPanel(IClassHierarchy cha) {
|
||||
this.cha = cha;
|
||||
|
||||
this.setDividerLocation(250);
|
||||
JTree tree = buildTree();
|
||||
this.setLeftComponent(new JScrollPane(tree));
|
||||
|
||||
final DefaultListModel methodListModel = new DefaultListModel();
|
||||
JList methodList = new JList(methodListModel);
|
||||
this.setRightComponent(methodList);
|
||||
|
||||
tree.addTreeSelectionListener(new TreeSelectionListener(){
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
TreePath newLeadSelectionPath = e.getNewLeadSelectionPath();
|
||||
if (null == newLeadSelectionPath){
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent();
|
||||
IClass klass = (IClass) treeNode.getUserObject();
|
||||
methodListModel.clear();
|
||||
for (IMethod m : klass.getDeclaredMethods()){
|
||||
methodListModel.addElement(m.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private JTree buildTree() {
|
||||
IClass rootClass = cha.getRootClass();
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode(rootClass);
|
||||
|
||||
expandNode(root);
|
||||
JTree tree = new JTree(root);
|
||||
|
||||
tree.addTreeExpansionListener(new TreeExpansionListener() {
|
||||
|
||||
public void treeExpanded(TreeExpansionEvent event) {
|
||||
TreePath path = event.getPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||
expandNode(lastNode);
|
||||
}
|
||||
|
||||
public void treeCollapsed(TreeExpansionEvent event) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode) {
|
||||
expandNode(treeNode, 3);
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode, int rec) {
|
||||
if (rec == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (treeNode.getChildCount() == 0) {
|
||||
IClass klass = (IClass) treeNode.getUserObject();
|
||||
Collection<IClass> immediateSubclasses = cha.getImmediateSubclasses(klass);
|
||||
for (IClass immediateSubclass : immediateSubclasses){
|
||||
treeNode.add(new DefaultMutableTreeNode(immediateSubclass));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < treeNode.getChildCount(); i++) {
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeNode.getChildAt(i);
|
||||
expandNode(child, rec - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeExpansionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
|
||||
public class ChaPanel extends JSplitPane {
|
||||
|
||||
private final IClassHierarchy cha;
|
||||
|
||||
public ChaPanel(IClassHierarchy cha) {
|
||||
this.cha = cha;
|
||||
|
||||
this.setDividerLocation(250);
|
||||
JTree tree = buildTree();
|
||||
this.setLeftComponent(new JScrollPane(tree));
|
||||
|
||||
final DefaultListModel methodListModel = new DefaultListModel();
|
||||
JList methodList = new JList(methodListModel);
|
||||
this.setRightComponent(methodList);
|
||||
|
||||
tree.addTreeSelectionListener(new TreeSelectionListener(){
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
TreePath newLeadSelectionPath = e.getNewLeadSelectionPath();
|
||||
if (null == newLeadSelectionPath){
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent();
|
||||
IClass klass = (IClass) treeNode.getUserObject();
|
||||
methodListModel.clear();
|
||||
for (IMethod m : klass.getDeclaredMethods()){
|
||||
methodListModel.addElement(m.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private JTree buildTree() {
|
||||
IClass rootClass = cha.getRootClass();
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode(rootClass);
|
||||
|
||||
expandNode(root);
|
||||
JTree tree = new JTree(root);
|
||||
|
||||
tree.addTreeExpansionListener(new TreeExpansionListener() {
|
||||
|
||||
public void treeExpanded(TreeExpansionEvent event) {
|
||||
TreePath path = event.getPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||
expandNode(lastNode);
|
||||
}
|
||||
|
||||
public void treeCollapsed(TreeExpansionEvent event) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode) {
|
||||
expandNode(treeNode, 3);
|
||||
}
|
||||
|
||||
private void expandNode(DefaultMutableTreeNode treeNode, int rec) {
|
||||
if (rec == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (treeNode.getChildCount() == 0) {
|
||||
IClass klass = (IClass) treeNode.getUserObject();
|
||||
Collection<IClass> immediateSubclasses = cha.getImmediateSubclasses(klass);
|
||||
for (IClass immediateSubclass : immediateSubclasses){
|
||||
treeNode.add(new DefaultMutableTreeNode(immediateSubclass));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < treeNode.getChildCount(); i++) {
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeNode.getChildAt(i);
|
||||
expandNode(child, rec - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,70 +1,70 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.Component;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
import javax.swing.tree.TreeCellRenderer;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
|
||||
/**
|
||||
* Renderer for the heap tree. Gives non default icons for pointer keys and instance keys.
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
class DualTreeCellRenderer implements TreeCellRenderer {
|
||||
|
||||
private final DefaultTreeCellRenderer defaultTreeCellRenderer;
|
||||
private final DefaultTreeCellRenderer ikTreeCellRenderer;
|
||||
private final DefaultTreeCellRenderer pkTreeCellRenderer;
|
||||
|
||||
public DualTreeCellRenderer() {
|
||||
defaultTreeCellRenderer = new DefaultTreeCellRenderer();
|
||||
|
||||
|
||||
ikTreeCellRenderer = new DefaultTreeCellRenderer();
|
||||
ikTreeCellRenderer.setOpenIcon(createImageIcon("images/ik_open.png"));
|
||||
ikTreeCellRenderer.setClosedIcon(createImageIcon("images/ik_closed.png"));
|
||||
ikTreeCellRenderer.setLeafIcon(createImageIcon("images/ik_leaf.png"));
|
||||
|
||||
pkTreeCellRenderer = new DefaultTreeCellRenderer();
|
||||
pkTreeCellRenderer.setOpenIcon(createImageIcon("images/pk_open.png"));
|
||||
pkTreeCellRenderer.setClosedIcon(createImageIcon("images/pk_closed.png"));
|
||||
pkTreeCellRenderer.setLeafIcon(createImageIcon("images/pk_leaf.png"));
|
||||
}
|
||||
|
||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf,
|
||||
int row, boolean hasFocus) {
|
||||
TreeCellRenderer delegate = getTreeCellRenderer(value);
|
||||
return delegate.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
|
||||
}
|
||||
|
||||
private TreeCellRenderer getTreeCellRenderer(Object value) {
|
||||
if (value instanceof DefaultMutableTreeNode){
|
||||
value = ((DefaultMutableTreeNode) value).getUserObject();
|
||||
}
|
||||
if (value instanceof PointerKey){
|
||||
return pkTreeCellRenderer;
|
||||
} else if (value instanceof InstanceKey){
|
||||
return ikTreeCellRenderer;
|
||||
} else {
|
||||
return defaultTreeCellRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns an ImageIcon, or null if the path was invalid. */
|
||||
protected ImageIcon createImageIcon(String path) {
|
||||
java.net.URL imgURL = DualTreeCellRenderer.class.getResource(path);
|
||||
if (imgURL != null) {
|
||||
return new ImageIcon(imgURL);
|
||||
} else {
|
||||
System.err.println("Couldn't find file: " + path);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.Component;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
import javax.swing.tree.TreeCellRenderer;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
|
||||
/**
|
||||
* Renderer for the heap tree. Gives non default icons for pointer keys and instance keys.
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
class DualTreeCellRenderer implements TreeCellRenderer {
|
||||
|
||||
private final DefaultTreeCellRenderer defaultTreeCellRenderer;
|
||||
private final DefaultTreeCellRenderer ikTreeCellRenderer;
|
||||
private final DefaultTreeCellRenderer pkTreeCellRenderer;
|
||||
|
||||
public DualTreeCellRenderer() {
|
||||
defaultTreeCellRenderer = new DefaultTreeCellRenderer();
|
||||
|
||||
|
||||
ikTreeCellRenderer = new DefaultTreeCellRenderer();
|
||||
ikTreeCellRenderer.setOpenIcon(createImageIcon("images/ik_open.png"));
|
||||
ikTreeCellRenderer.setClosedIcon(createImageIcon("images/ik_closed.png"));
|
||||
ikTreeCellRenderer.setLeafIcon(createImageIcon("images/ik_leaf.png"));
|
||||
|
||||
pkTreeCellRenderer = new DefaultTreeCellRenderer();
|
||||
pkTreeCellRenderer.setOpenIcon(createImageIcon("images/pk_open.png"));
|
||||
pkTreeCellRenderer.setClosedIcon(createImageIcon("images/pk_closed.png"));
|
||||
pkTreeCellRenderer.setLeafIcon(createImageIcon("images/pk_leaf.png"));
|
||||
}
|
||||
|
||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf,
|
||||
int row, boolean hasFocus) {
|
||||
TreeCellRenderer delegate = getTreeCellRenderer(value);
|
||||
return delegate.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
|
||||
}
|
||||
|
||||
private TreeCellRenderer getTreeCellRenderer(Object value) {
|
||||
if (value instanceof DefaultMutableTreeNode){
|
||||
value = ((DefaultMutableTreeNode) value).getUserObject();
|
||||
}
|
||||
if (value instanceof PointerKey){
|
||||
return pkTreeCellRenderer;
|
||||
} else if (value instanceof InstanceKey){
|
||||
return ikTreeCellRenderer;
|
||||
} else {
|
||||
return defaultTreeCellRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns an ImageIcon, or null if the path was invalid. */
|
||||
protected ImageIcon createImageIcon(String path) {
|
||||
java.net.URL imgURL = DualTreeCellRenderer.class.getResource(path);
|
||||
if (imgURL != null) {
|
||||
return new ImageIcon(imgURL);
|
||||
} else {
|
||||
System.err.println("Couldn't find file: " + path);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,79 +1,79 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.JSplitPane;
|
||||
|
||||
import com.ibm.wala.classLoader.IClassLoader;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.viz.viewer.IrViewer.SelectedPcListner;
|
||||
|
||||
public class IrAndSourceViewer {
|
||||
|
||||
private IrViewer irViewer;
|
||||
private SourceViewer sourceViewer;
|
||||
|
||||
private IR ir;
|
||||
|
||||
public IrAndSourceViewer(CallGraph cg) {
|
||||
}
|
||||
|
||||
public Component getComponent() {
|
||||
|
||||
|
||||
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
||||
irViewer = new IrViewer();
|
||||
splitPane.setLeftComponent(irViewer);
|
||||
|
||||
sourceViewer = new SourceViewer();
|
||||
splitPane.setRightComponent(sourceViewer);
|
||||
|
||||
irViewer.addSelectedPcListner(new SelectedPcListner(){
|
||||
|
||||
public void valueChanged(int pc) {
|
||||
IMethod method = ir.getMethod();
|
||||
int sourceLineNumber = IrViewer.NA;
|
||||
String sourceFileName = null;
|
||||
if (pc != IrViewer.NA){
|
||||
try{
|
||||
sourceLineNumber = method.getLineNumber(pc);
|
||||
IClassLoader loader = method.getDeclaringClass().getClassLoader();
|
||||
sourceFileName = loader.getSourceFileName(method, pc);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (sourceFileName != null){
|
||||
URL url;
|
||||
try {
|
||||
url = (new File(sourceFileName)).toURI().toURL();
|
||||
sourceViewer.setSource(url, sourceLineNumber);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
sourceViewer.removeSource();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return splitPane;
|
||||
}
|
||||
|
||||
public void setIRAndPc(IR ir, int pc) {
|
||||
this.ir = ir;
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
}
|
||||
|
||||
public void setIR(IR ir) {
|
||||
this.ir = ir;
|
||||
irViewer.setIR(ir);
|
||||
}
|
||||
|
||||
}
|
||||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.JSplitPane;
|
||||
|
||||
import com.ibm.wala.classLoader.IClassLoader;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.viz.viewer.IrViewer.SelectedPcListner;
|
||||
|
||||
public class IrAndSourceViewer {
|
||||
|
||||
private IrViewer irViewer;
|
||||
private SourceViewer sourceViewer;
|
||||
|
||||
private IR ir;
|
||||
|
||||
public IrAndSourceViewer(CallGraph cg) {
|
||||
}
|
||||
|
||||
public Component getComponent() {
|
||||
|
||||
|
||||
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
||||
irViewer = new IrViewer();
|
||||
splitPane.setLeftComponent(irViewer);
|
||||
|
||||
sourceViewer = new SourceViewer();
|
||||
splitPane.setRightComponent(sourceViewer);
|
||||
|
||||
irViewer.addSelectedPcListner(new SelectedPcListner(){
|
||||
|
||||
public void valueChanged(int pc) {
|
||||
IMethod method = ir.getMethod();
|
||||
int sourceLineNumber = IrViewer.NA;
|
||||
String sourceFileName = null;
|
||||
if (pc != IrViewer.NA){
|
||||
try{
|
||||
sourceLineNumber = method.getLineNumber(pc);
|
||||
IClassLoader loader = method.getDeclaringClass().getClassLoader();
|
||||
sourceFileName = loader.getSourceFileName(method, pc);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (sourceFileName != null){
|
||||
URL url;
|
||||
try {
|
||||
url = (new File(sourceFileName)).toURI().toURL();
|
||||
sourceViewer.setSource(url, sourceLineNumber);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
sourceViewer.removeSource();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return splitPane;
|
||||
}
|
||||
|
||||
public void setIRAndPc(IR ir, int pc) {
|
||||
this.ir = ir;
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
}
|
||||
|
||||
public void setIR(IR ir) {
|
||||
this.ir = ir;
|
||||
irViewer.setIR(ir);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,156 +1,156 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
|
||||
public class IrViewer extends JPanel{
|
||||
private JTextField methodName;
|
||||
private DefaultListModel irLineList = new DefaultListModel();
|
||||
private JList irLines;
|
||||
|
||||
// mapping from ir viewer list line to source code line number.
|
||||
private Map<Integer, Integer> lineToPosition = null;
|
||||
|
||||
// Mapping for pc to line in the ir viewer list.
|
||||
private Map<Integer, Integer> pcToLine = null;
|
||||
private Map<Integer, Integer> lineToPc = null;
|
||||
|
||||
public interface SelectedPcListner{
|
||||
void valueChanged(int pc);
|
||||
}
|
||||
Set<SelectedPcListner> selectedPcListners = new HashSet<SelectedPcListner>();
|
||||
|
||||
public IrViewer() {
|
||||
super(new BorderLayout());
|
||||
irLines = new JList(irLineList);
|
||||
methodName = new JTextField("IR");
|
||||
this.add(methodName, BorderLayout.PAGE_START);
|
||||
this.add(new JScrollPane(irLines, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
|
||||
|
||||
|
||||
irLines.addListSelectionListener(new ListSelectionListener() {
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
int index = irLines.getSelectedIndex();
|
||||
Integer pc = lineToPc.get(index);
|
||||
if (pc == null) {
|
||||
pc = NA;
|
||||
}
|
||||
for (SelectedPcListner selectedPcListner : selectedPcListners) {
|
||||
selectedPcListner.valueChanged(pc);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setIR(IR ir) {
|
||||
this.lineToPosition = HashMapFactory.make();
|
||||
this.pcToLine = HashMapFactory.make();
|
||||
this.lineToPc = HashMapFactory.make();
|
||||
|
||||
int firstLineWithPosition = NA;
|
||||
|
||||
try {
|
||||
methodName.setText("IR: " + ir.getMethod());
|
||||
irLineList.clear();
|
||||
BufferedReader br = new BufferedReader(new StringReader(ir.toString()));
|
||||
int lineNum = 0;
|
||||
int position = NA;
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
irLineList.addElement(line);
|
||||
int pc = parseIrLine(line);
|
||||
if (pc != NA) {
|
||||
IMethod m = ir.getMethod();
|
||||
int newPosition = m.getLineNumber(pc);
|
||||
if (newPosition != -1) {
|
||||
position = newPosition;
|
||||
}
|
||||
lineToPc.put(lineNum, pc);
|
||||
pcToLine.put(pc, lineNum);
|
||||
|
||||
if (position != NA) {
|
||||
lineToPosition.put(lineNum, position);
|
||||
if (firstLineWithPosition == NA){
|
||||
firstLineWithPosition = lineNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
lineNum++;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ???
|
||||
assert false;
|
||||
}
|
||||
|
||||
// focusing on the first line with position
|
||||
if (firstLineWithPosition != NA){
|
||||
irLines.setSelectedIndex(firstLineWithPosition);
|
||||
irLines.ensureIndexIsVisible(firstLineWithPosition);
|
||||
}
|
||||
}
|
||||
|
||||
static final int NA = -1;
|
||||
|
||||
private int parseIrLine(String line) {
|
||||
int firstSpace = line.indexOf(' ');
|
||||
if (firstSpace > 0) {
|
||||
String pcString = line.substring(0, firstSpace);
|
||||
try {
|
||||
return Integer.parseInt(pcString);
|
||||
} catch (NumberFormatException e) {
|
||||
return NA;
|
||||
}
|
||||
} else {
|
||||
return NA;
|
||||
}
|
||||
}
|
||||
|
||||
public void addSelectedPcListner(SelectedPcListner selectedPcListner) {
|
||||
this.selectedPcListners.add(selectedPcListner);
|
||||
}
|
||||
|
||||
public void setPc(int pc){
|
||||
Integer lineNum = pcToLine.get(pc);
|
||||
if (lineNum != null){
|
||||
irLines.ensureIndexIsVisible(lineNum);
|
||||
irLines.setSelectedIndex(lineNum);
|
||||
} else {
|
||||
removeSelection();
|
||||
}
|
||||
}
|
||||
|
||||
public void setIRAndPc(IR ir, int pc) {
|
||||
setIR(ir);
|
||||
if (pc != NA){
|
||||
setPc(pc);
|
||||
} else {
|
||||
removeSelection();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSelection() {
|
||||
int curSelectedIndex = irLines.getSelectedIndex();
|
||||
irLines.removeSelectionInterval(curSelectedIndex, curSelectedIndex);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
|
||||
public class IrViewer extends JPanel{
|
||||
private JTextField methodName;
|
||||
private DefaultListModel irLineList = new DefaultListModel();
|
||||
private JList irLines;
|
||||
|
||||
// mapping from ir viewer list line to source code line number.
|
||||
private Map<Integer, Integer> lineToPosition = null;
|
||||
|
||||
// Mapping for pc to line in the ir viewer list.
|
||||
private Map<Integer, Integer> pcToLine = null;
|
||||
private Map<Integer, Integer> lineToPc = null;
|
||||
|
||||
public interface SelectedPcListner{
|
||||
void valueChanged(int pc);
|
||||
}
|
||||
Set<SelectedPcListner> selectedPcListners = new HashSet<SelectedPcListner>();
|
||||
|
||||
public IrViewer() {
|
||||
super(new BorderLayout());
|
||||
irLines = new JList(irLineList);
|
||||
methodName = new JTextField("IR");
|
||||
this.add(methodName, BorderLayout.PAGE_START);
|
||||
this.add(new JScrollPane(irLines, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
|
||||
|
||||
|
||||
irLines.addListSelectionListener(new ListSelectionListener() {
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
int index = irLines.getSelectedIndex();
|
||||
Integer pc = lineToPc.get(index);
|
||||
if (pc == null) {
|
||||
pc = NA;
|
||||
}
|
||||
for (SelectedPcListner selectedPcListner : selectedPcListners) {
|
||||
selectedPcListner.valueChanged(pc);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setIR(IR ir) {
|
||||
this.lineToPosition = HashMapFactory.make();
|
||||
this.pcToLine = HashMapFactory.make();
|
||||
this.lineToPc = HashMapFactory.make();
|
||||
|
||||
int firstLineWithPosition = NA;
|
||||
|
||||
try {
|
||||
methodName.setText("IR: " + ir.getMethod());
|
||||
irLineList.clear();
|
||||
BufferedReader br = new BufferedReader(new StringReader(ir.toString()));
|
||||
int lineNum = 0;
|
||||
int position = NA;
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
irLineList.addElement(line);
|
||||
int pc = parseIrLine(line);
|
||||
if (pc != NA) {
|
||||
IMethod m = ir.getMethod();
|
||||
int newPosition = m.getLineNumber(pc);
|
||||
if (newPosition != -1) {
|
||||
position = newPosition;
|
||||
}
|
||||
lineToPc.put(lineNum, pc);
|
||||
pcToLine.put(pc, lineNum);
|
||||
|
||||
if (position != NA) {
|
||||
lineToPosition.put(lineNum, position);
|
||||
if (firstLineWithPosition == NA){
|
||||
firstLineWithPosition = lineNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
lineNum++;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ???
|
||||
assert false;
|
||||
}
|
||||
|
||||
// focusing on the first line with position
|
||||
if (firstLineWithPosition != NA){
|
||||
irLines.setSelectedIndex(firstLineWithPosition);
|
||||
irLines.ensureIndexIsVisible(firstLineWithPosition);
|
||||
}
|
||||
}
|
||||
|
||||
static final int NA = -1;
|
||||
|
||||
private int parseIrLine(String line) {
|
||||
int firstSpace = line.indexOf(' ');
|
||||
if (firstSpace > 0) {
|
||||
String pcString = line.substring(0, firstSpace);
|
||||
try {
|
||||
return Integer.parseInt(pcString);
|
||||
} catch (NumberFormatException e) {
|
||||
return NA;
|
||||
}
|
||||
} else {
|
||||
return NA;
|
||||
}
|
||||
}
|
||||
|
||||
public void addSelectedPcListner(SelectedPcListner selectedPcListner) {
|
||||
this.selectedPcListners.add(selectedPcListner);
|
||||
}
|
||||
|
||||
public void setPc(int pc){
|
||||
Integer lineNum = pcToLine.get(pc);
|
||||
if (lineNum != null){
|
||||
irLines.ensureIndexIsVisible(lineNum);
|
||||
irLines.setSelectedIndex(lineNum);
|
||||
} else {
|
||||
removeSelection();
|
||||
}
|
||||
}
|
||||
|
||||
public void setIRAndPc(IR ir, int pc) {
|
||||
setIR(ir);
|
||||
if (pc != NA){
|
||||
setPc(pc);
|
||||
} else {
|
||||
removeSelection();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSelection() {
|
||||
int curSelectedIndex = irLines.getSelectedIndex();
|
||||
irLines.removeSelectionInterval(curSelectedIndex, curSelectedIndex);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,288 +1,288 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeExpansionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import com.ibm.wala.analysis.pointers.HeapGraph;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceFieldPointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.ReturnValueKey;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.util.intset.MutableMapping;
|
||||
import com.ibm.wala.util.intset.OrdinalSetMapping;
|
||||
|
||||
/**
|
||||
* Panel for showing the Pointer Analysis results. Shows the heap graph on the left, and the ir viewer on the right. Sets the IR of
|
||||
* and pc according to the chosen pointer/instance key when possible (e.g., allocation side for NormalAllocationInNode instance
|
||||
* keys. Can be customized for clients that use different their own pointer / instance keys (see JsPaPanel)
|
||||
*
|
||||
* Note the two steps initialization require (calling init())
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public class PaPanel extends JSplitPane {
|
||||
|
||||
protected final PointerAnalysis pa;
|
||||
protected final CallGraph cg;
|
||||
|
||||
private JTextField fullName;
|
||||
|
||||
private IrAndSourceViewer irViewer;
|
||||
|
||||
private MutableMapping<List<LocalPointerKey>> cgNodeIdToLocalPointers = MutableMapping.<List<LocalPointerKey>> make();
|
||||
private MutableMapping<List<ReturnValueKey>> cgNodeIdToReturnValue = MutableMapping.<List<ReturnValueKey>> make();
|
||||
private MutableMapping<List<InstanceFieldPointerKey>> instanceKeyIdToInstanceFieldPointers = MutableMapping.<List<InstanceFieldPointerKey>> make();
|
||||
|
||||
|
||||
public PaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
super(JSplitPane.HORIZONTAL_SPLIT);
|
||||
|
||||
this.pa = pa;
|
||||
this.cg = cg;
|
||||
|
||||
initDataStructures(pa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Two steps initialization is required here is our deriver can choose the roots for the heap tree.
|
||||
*/
|
||||
public void init() {
|
||||
this.setDividerLocation(250);
|
||||
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
|
||||
for (Object rootChildNode : getRootNodes()){
|
||||
DefaultMutableTreeNode n = new DefaultMutableTreeNode(rootChildNode);
|
||||
root.add(n);
|
||||
expandNodeRec(n, 1);
|
||||
}
|
||||
|
||||
JTree heapTree = new JTree(root);
|
||||
|
||||
heapTree.setCellRenderer(new DualTreeCellRenderer());
|
||||
|
||||
this.setLeftComponent(new JScrollPane(heapTree));
|
||||
JPanel rightPanel = new JPanel(new BorderLayout());
|
||||
this.setRightComponent(rightPanel);
|
||||
fullName = new JTextField("");
|
||||
rightPanel.add(fullName, BorderLayout.PAGE_START);
|
||||
irViewer = new IrAndSourceViewer(cg);
|
||||
rightPanel.add(irViewer.getComponent(), BorderLayout.CENTER);
|
||||
|
||||
heapTree.addTreeExpansionListener(new TreeExpansionListener() {
|
||||
|
||||
public void treeExpanded(TreeExpansionEvent event) {
|
||||
TreePath path = event.getPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||
expandNodeRec(lastNode, 2);
|
||||
}
|
||||
|
||||
public void treeCollapsed(TreeExpansionEvent event) {
|
||||
}
|
||||
});
|
||||
|
||||
heapTree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
TreePath newLeadSelectionPath = e.getNewLeadSelectionPath();
|
||||
if (null == newLeadSelectionPath){
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent();
|
||||
Object userObject = treeNode.getUserObject();
|
||||
fullName.setText(userObject.toString());
|
||||
if (userObject instanceof LocalPointerKey){
|
||||
LocalPointerKey lpk = (LocalPointerKey) userObject;
|
||||
IR ir = lpk.getNode().getIR();
|
||||
SSAInstruction def = lpk.getNode().getDU().getDef(lpk.getValueNumber());
|
||||
int pc = IrViewer.NA;
|
||||
if (def != null){
|
||||
SSAInstruction[] instructions = ir.getInstructions();
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
SSAInstruction instruction = instructions[i];
|
||||
if (def == instruction){
|
||||
pc = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
} else if (userObject instanceof InstanceFieldPointerKey){
|
||||
InstanceKey ik = ((InstanceFieldPointerKey) userObject).getInstanceKey();
|
||||
if (ik instanceof NormalAllocationInNode){
|
||||
NormalAllocationInNode normalIk = (NormalAllocationInNode) ik;
|
||||
IR ir = normalIk.getNode().getIR();
|
||||
int pc = normalIk.getSite().getProgramCounter();
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
}
|
||||
} else if (userObject instanceof NormalAllocationInNode){
|
||||
NormalAllocationInNode normalIk = (NormalAllocationInNode) userObject;
|
||||
IR ir = normalIk.getNode().getIR();
|
||||
int pc = normalIk.getSite().getProgramCounter();
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
} else if (userObject instanceof CGNode){
|
||||
irViewer.setIR(((CGNode)userObject).getIR());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void initDataStructures(PointerAnalysis pa) {
|
||||
HeapGraph heapGraph = pa.getHeapGraph();
|
||||
OrdinalSetMapping<InstanceKey> instanceKeyMapping = pa.getInstanceKeyMapping();
|
||||
for (Object n : heapGraph){
|
||||
if (heapGraph.getPredNodeCount(n) == 0){ // considering only roots of the heap graph.
|
||||
if (n instanceof PointerKey){
|
||||
if (n instanceof LocalPointerKey){
|
||||
LocalPointerKey lpk = (LocalPointerKey) n;
|
||||
int nodeId = lpk.getNode().getGraphNodeId();
|
||||
mapUsingMutableMapping(cgNodeIdToLocalPointers, nodeId, lpk);
|
||||
} else if (n instanceof ReturnValueKey){
|
||||
ReturnValueKey rvk = (ReturnValueKey) n;
|
||||
int nodeId = rvk.getNode().getGraphNodeId();
|
||||
mapUsingMutableMapping(cgNodeIdToReturnValue, nodeId, rvk);
|
||||
} else if (n instanceof InstanceFieldPointerKey){
|
||||
InstanceFieldPointerKey ifpk = (InstanceFieldPointerKey) n;
|
||||
int instanceKeyId = instanceKeyMapping.getMappedIndex(ifpk.getInstanceKey());
|
||||
mapUsingMutableMapping(instanceKeyIdToInstanceFieldPointers, instanceKeyId, ifpk);
|
||||
}
|
||||
} else {
|
||||
System.err.println("Non Pointer key root: " + n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override if you want different roots for your heap tree.
|
||||
* @return
|
||||
*/
|
||||
protected List<Object> getRootNodes(){
|
||||
List<Object> ret = new ArrayList<Object>();
|
||||
for (CGNode n : cg){
|
||||
ret.add(n);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* expands the given "treeNode" "rec" levels.
|
||||
* @param treeNode
|
||||
* @param rec
|
||||
*/
|
||||
private void expandNodeRec(DefaultMutableTreeNode treeNode, int rec) {
|
||||
if (rec == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
if (treeNode.getChildCount() == 0){ // may be expandable.
|
||||
List<Object> children = getChildrenFor(treeNode.getUserObject());
|
||||
for (Object child : children){
|
||||
treeNode.add(new DefaultMutableTreeNode(child));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0 ; i < treeNode.getChildCount(); i++){
|
||||
TreeNode child = treeNode.getChildAt(i);
|
||||
expandNodeRec((DefaultMutableTreeNode)child, rec-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for filling the tree dynamically. Override and handle your own nodes / different links.
|
||||
* @param node
|
||||
* @return
|
||||
*/
|
||||
protected List<Object> getChildrenFor(Object node) {
|
||||
List<Object> ret = new ArrayList<Object>();
|
||||
if (node instanceof InstanceKey){
|
||||
ret.addAll(getPointerKeysUnderInstanceKey((InstanceKey) node));
|
||||
} else if (node instanceof PointerKey){
|
||||
for (InstanceKey ik : pa.getPointsToSet((PointerKey) node)){
|
||||
ret.add(ik);
|
||||
}
|
||||
} else if (node instanceof CGNode){
|
||||
int nodeId = ((CGNode) node).getGraphNodeId();
|
||||
ret.addAll(nonNullList(cgNodeIdToLocalPointers.getMappedObject(nodeId)));
|
||||
ret.addAll(nonNullList(cgNodeIdToReturnValue.getMappedObject(nodeId)));
|
||||
} else {
|
||||
assert false : "Unhandled Node : " + node;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of pointer keys that should be presented below an instance key in the heap tree. Override if you have special
|
||||
* pointer keys (not just for fields)
|
||||
*
|
||||
* @param ik
|
||||
* @return
|
||||
*/
|
||||
protected List<? extends PointerKey> getPointerKeysUnderInstanceKey(InstanceKey ik) {
|
||||
int ikIndex = pa.getInstanceKeyMapping().getMappedIndex(ik);
|
||||
List<? extends PointerKey> ret;
|
||||
if (ikIndex <= instanceKeyIdToInstanceFieldPointers.getMaximumIndex()){
|
||||
ret = nonNullList(instanceKeyIdToInstanceFieldPointers.getMappedObject(ikIndex));
|
||||
} else {
|
||||
ret = Collections.emptyList();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility method for mutable mapping. map[index] U= o
|
||||
* @param <T>
|
||||
* @param map
|
||||
* @param index
|
||||
* @param o
|
||||
*/
|
||||
protected static <T> void mapUsingMutableMapping(MutableMapping<List<T>> map, int index, T o){
|
||||
List<T> set;
|
||||
if (index <= map.getMaximumIndex()){
|
||||
set = map.getMappedObject(index);
|
||||
} else {
|
||||
set = null;
|
||||
}
|
||||
if (null == set){
|
||||
set = new ArrayList<T>();
|
||||
map.put(index, set);
|
||||
}
|
||||
set.add(o);
|
||||
}
|
||||
|
||||
protected <T> List<T> nonNullList(List<T> l){
|
||||
if (null == l){
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.event.TreeExpansionEvent;
|
||||
import javax.swing.event.TreeExpansionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import com.ibm.wala.analysis.pointers.HeapGraph;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceFieldPointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.ReturnValueKey;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.util.intset.MutableMapping;
|
||||
import com.ibm.wala.util.intset.OrdinalSetMapping;
|
||||
|
||||
/**
|
||||
* Panel for showing the Pointer Analysis results. Shows the heap graph on the left, and the ir viewer on the right. Sets the IR of
|
||||
* and pc according to the chosen pointer/instance key when possible (e.g., allocation side for NormalAllocationInNode instance
|
||||
* keys. Can be customized for clients that use different their own pointer / instance keys (see JsPaPanel)
|
||||
*
|
||||
* Note the two steps initialization require (calling init())
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public class PaPanel extends JSplitPane {
|
||||
|
||||
protected final PointerAnalysis pa;
|
||||
protected final CallGraph cg;
|
||||
|
||||
private JTextField fullName;
|
||||
|
||||
private IrAndSourceViewer irViewer;
|
||||
|
||||
private MutableMapping<List<LocalPointerKey>> cgNodeIdToLocalPointers = MutableMapping.<List<LocalPointerKey>> make();
|
||||
private MutableMapping<List<ReturnValueKey>> cgNodeIdToReturnValue = MutableMapping.<List<ReturnValueKey>> make();
|
||||
private MutableMapping<List<InstanceFieldPointerKey>> instanceKeyIdToInstanceFieldPointers = MutableMapping.<List<InstanceFieldPointerKey>> make();
|
||||
|
||||
|
||||
public PaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
super(JSplitPane.HORIZONTAL_SPLIT);
|
||||
|
||||
this.pa = pa;
|
||||
this.cg = cg;
|
||||
|
||||
initDataStructures(pa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Two steps initialization is required here is our deriver can choose the roots for the heap tree.
|
||||
*/
|
||||
public void init() {
|
||||
this.setDividerLocation(250);
|
||||
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
|
||||
for (Object rootChildNode : getRootNodes()){
|
||||
DefaultMutableTreeNode n = new DefaultMutableTreeNode(rootChildNode);
|
||||
root.add(n);
|
||||
expandNodeRec(n, 1);
|
||||
}
|
||||
|
||||
JTree heapTree = new JTree(root);
|
||||
|
||||
heapTree.setCellRenderer(new DualTreeCellRenderer());
|
||||
|
||||
this.setLeftComponent(new JScrollPane(heapTree));
|
||||
JPanel rightPanel = new JPanel(new BorderLayout());
|
||||
this.setRightComponent(rightPanel);
|
||||
fullName = new JTextField("");
|
||||
rightPanel.add(fullName, BorderLayout.PAGE_START);
|
||||
irViewer = new IrAndSourceViewer(cg);
|
||||
rightPanel.add(irViewer.getComponent(), BorderLayout.CENTER);
|
||||
|
||||
heapTree.addTreeExpansionListener(new TreeExpansionListener() {
|
||||
|
||||
public void treeExpanded(TreeExpansionEvent event) {
|
||||
TreePath path = event.getPath();
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||
expandNodeRec(lastNode, 2);
|
||||
}
|
||||
|
||||
public void treeCollapsed(TreeExpansionEvent event) {
|
||||
}
|
||||
});
|
||||
|
||||
heapTree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
TreePath newLeadSelectionPath = e.getNewLeadSelectionPath();
|
||||
if (null == newLeadSelectionPath){
|
||||
return;
|
||||
}
|
||||
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent();
|
||||
Object userObject = treeNode.getUserObject();
|
||||
fullName.setText(userObject.toString());
|
||||
if (userObject instanceof LocalPointerKey){
|
||||
LocalPointerKey lpk = (LocalPointerKey) userObject;
|
||||
IR ir = lpk.getNode().getIR();
|
||||
SSAInstruction def = lpk.getNode().getDU().getDef(lpk.getValueNumber());
|
||||
int pc = IrViewer.NA;
|
||||
if (def != null){
|
||||
SSAInstruction[] instructions = ir.getInstructions();
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
SSAInstruction instruction = instructions[i];
|
||||
if (def == instruction){
|
||||
pc = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
} else if (userObject instanceof InstanceFieldPointerKey){
|
||||
InstanceKey ik = ((InstanceFieldPointerKey) userObject).getInstanceKey();
|
||||
if (ik instanceof NormalAllocationInNode){
|
||||
NormalAllocationInNode normalIk = (NormalAllocationInNode) ik;
|
||||
IR ir = normalIk.getNode().getIR();
|
||||
int pc = normalIk.getSite().getProgramCounter();
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
}
|
||||
} else if (userObject instanceof NormalAllocationInNode){
|
||||
NormalAllocationInNode normalIk = (NormalAllocationInNode) userObject;
|
||||
IR ir = normalIk.getNode().getIR();
|
||||
int pc = normalIk.getSite().getProgramCounter();
|
||||
irViewer.setIRAndPc(ir, pc);
|
||||
} else if (userObject instanceof CGNode){
|
||||
irViewer.setIR(((CGNode)userObject).getIR());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void initDataStructures(PointerAnalysis pa) {
|
||||
HeapGraph heapGraph = pa.getHeapGraph();
|
||||
OrdinalSetMapping<InstanceKey> instanceKeyMapping = pa.getInstanceKeyMapping();
|
||||
for (Object n : heapGraph){
|
||||
if (heapGraph.getPredNodeCount(n) == 0){ // considering only roots of the heap graph.
|
||||
if (n instanceof PointerKey){
|
||||
if (n instanceof LocalPointerKey){
|
||||
LocalPointerKey lpk = (LocalPointerKey) n;
|
||||
int nodeId = lpk.getNode().getGraphNodeId();
|
||||
mapUsingMutableMapping(cgNodeIdToLocalPointers, nodeId, lpk);
|
||||
} else if (n instanceof ReturnValueKey){
|
||||
ReturnValueKey rvk = (ReturnValueKey) n;
|
||||
int nodeId = rvk.getNode().getGraphNodeId();
|
||||
mapUsingMutableMapping(cgNodeIdToReturnValue, nodeId, rvk);
|
||||
} else if (n instanceof InstanceFieldPointerKey){
|
||||
InstanceFieldPointerKey ifpk = (InstanceFieldPointerKey) n;
|
||||
int instanceKeyId = instanceKeyMapping.getMappedIndex(ifpk.getInstanceKey());
|
||||
mapUsingMutableMapping(instanceKeyIdToInstanceFieldPointers, instanceKeyId, ifpk);
|
||||
}
|
||||
} else {
|
||||
System.err.println("Non Pointer key root: " + n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override if you want different roots for your heap tree.
|
||||
* @return
|
||||
*/
|
||||
protected List<Object> getRootNodes(){
|
||||
List<Object> ret = new ArrayList<Object>();
|
||||
for (CGNode n : cg){
|
||||
ret.add(n);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* expands the given "treeNode" "rec" levels.
|
||||
* @param treeNode
|
||||
* @param rec
|
||||
*/
|
||||
private void expandNodeRec(DefaultMutableTreeNode treeNode, int rec) {
|
||||
if (rec == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
if (treeNode.getChildCount() == 0){ // may be expandable.
|
||||
List<Object> children = getChildrenFor(treeNode.getUserObject());
|
||||
for (Object child : children){
|
||||
treeNode.add(new DefaultMutableTreeNode(child));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0 ; i < treeNode.getChildCount(); i++){
|
||||
TreeNode child = treeNode.getChildAt(i);
|
||||
expandNodeRec((DefaultMutableTreeNode)child, rec-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for filling the tree dynamically. Override and handle your own nodes / different links.
|
||||
* @param node
|
||||
* @return
|
||||
*/
|
||||
protected List<Object> getChildrenFor(Object node) {
|
||||
List<Object> ret = new ArrayList<Object>();
|
||||
if (node instanceof InstanceKey){
|
||||
ret.addAll(getPointerKeysUnderInstanceKey((InstanceKey) node));
|
||||
} else if (node instanceof PointerKey){
|
||||
for (InstanceKey ik : pa.getPointsToSet((PointerKey) node)){
|
||||
ret.add(ik);
|
||||
}
|
||||
} else if (node instanceof CGNode){
|
||||
int nodeId = ((CGNode) node).getGraphNodeId();
|
||||
ret.addAll(nonNullList(cgNodeIdToLocalPointers.getMappedObject(nodeId)));
|
||||
ret.addAll(nonNullList(cgNodeIdToReturnValue.getMappedObject(nodeId)));
|
||||
} else {
|
||||
assert false : "Unhandled Node : " + node;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of pointer keys that should be presented below an instance key in the heap tree. Override if you have special
|
||||
* pointer keys (not just for fields)
|
||||
*
|
||||
* @param ik
|
||||
* @return
|
||||
*/
|
||||
protected List<? extends PointerKey> getPointerKeysUnderInstanceKey(InstanceKey ik) {
|
||||
int ikIndex = pa.getInstanceKeyMapping().getMappedIndex(ik);
|
||||
List<? extends PointerKey> ret;
|
||||
if (ikIndex <= instanceKeyIdToInstanceFieldPointers.getMaximumIndex()){
|
||||
ret = nonNullList(instanceKeyIdToInstanceFieldPointers.getMappedObject(ikIndex));
|
||||
} else {
|
||||
ret = Collections.emptyList();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility method for mutable mapping. map[index] U= o
|
||||
* @param <T>
|
||||
* @param map
|
||||
* @param index
|
||||
* @param o
|
||||
*/
|
||||
protected static <T> void mapUsingMutableMapping(MutableMapping<List<T>> map, int index, T o){
|
||||
List<T> set;
|
||||
if (index <= map.getMaximumIndex()){
|
||||
set = map.getMappedObject(index);
|
||||
} else {
|
||||
set = null;
|
||||
}
|
||||
if (null == set){
|
||||
set = new ArrayList<T>();
|
||||
map.put(index, set);
|
||||
}
|
||||
set.add(o);
|
||||
}
|
||||
|
||||
protected <T> List<T> nonNullList(List<T> l){
|
||||
if (null == l){
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,89 +1,89 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public class SourceViewer extends JPanel{
|
||||
private URL sourceURL;
|
||||
private JTextField sourceCodeLocation;
|
||||
private DefaultListModel sourceCodeLinesList = new DefaultListModel();
|
||||
private JList sourceCodeLines;
|
||||
|
||||
public SourceViewer() {
|
||||
super(new BorderLayout());
|
||||
sourceURL = null;
|
||||
sourceCodeLines = new JList(sourceCodeLinesList);
|
||||
sourceCodeLocation = new JTextField("Source code");
|
||||
this.add(sourceCodeLocation, BorderLayout.PAGE_START);
|
||||
this.add(new JScrollPane(sourceCodeLines), BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public void setSource(URL url) {
|
||||
setSource(url, IrViewer.NA);
|
||||
}
|
||||
|
||||
public void setSource(URL url, int sourceLine) {
|
||||
boolean succsess = loadSource(url);
|
||||
if (succsess){
|
||||
sourceCodeLocation.setText("Source code: " + url);
|
||||
if (sourceLine != IrViewer.NA){
|
||||
sourceCodeLines.ensureIndexIsVisible(sourceLine-1);
|
||||
sourceCodeLines.setSelectedIndex(sourceLine-1);
|
||||
sourceCodeLines.validate();
|
||||
}
|
||||
} else {
|
||||
sourceCodeLocation.setText("Error loading source code from: " + url);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadSource(URL url) {
|
||||
if (url == null) {
|
||||
if (sourceURL != null) {
|
||||
// easing the current code.
|
||||
sourceCodeLinesList.clear();
|
||||
}
|
||||
return false; // nothing to load
|
||||
} else {
|
||||
if (url.equals(sourceURL)) {
|
||||
return true; // already loaded
|
||||
} else {
|
||||
sourceCodeLinesList.clear();
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
sourceCodeLinesList.addElement(line.replaceAll("\t", " "));
|
||||
}
|
||||
br.close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Could not load source at " + url);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeSelection() {
|
||||
int curSelectedIndex = sourceCodeLines.getSelectedIndex();
|
||||
sourceCodeLines.removeSelectionInterval(curSelectedIndex, curSelectedIndex);
|
||||
}
|
||||
|
||||
public void removeSource() {
|
||||
sourceURL = null;
|
||||
sourceCodeLocation.setText("Source code");
|
||||
sourceCodeLinesList.clear();
|
||||
sourceCodeLines.validate();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public class SourceViewer extends JPanel{
|
||||
private URL sourceURL;
|
||||
private JTextField sourceCodeLocation;
|
||||
private DefaultListModel sourceCodeLinesList = new DefaultListModel();
|
||||
private JList sourceCodeLines;
|
||||
|
||||
public SourceViewer() {
|
||||
super(new BorderLayout());
|
||||
sourceURL = null;
|
||||
sourceCodeLines = new JList(sourceCodeLinesList);
|
||||
sourceCodeLocation = new JTextField("Source code");
|
||||
this.add(sourceCodeLocation, BorderLayout.PAGE_START);
|
||||
this.add(new JScrollPane(sourceCodeLines), BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public void setSource(URL url) {
|
||||
setSource(url, IrViewer.NA);
|
||||
}
|
||||
|
||||
public void setSource(URL url, int sourceLine) {
|
||||
boolean succsess = loadSource(url);
|
||||
if (succsess){
|
||||
sourceCodeLocation.setText("Source code: " + url);
|
||||
if (sourceLine != IrViewer.NA){
|
||||
sourceCodeLines.ensureIndexIsVisible(sourceLine-1);
|
||||
sourceCodeLines.setSelectedIndex(sourceLine-1);
|
||||
sourceCodeLines.validate();
|
||||
}
|
||||
} else {
|
||||
sourceCodeLocation.setText("Error loading source code from: " + url);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadSource(URL url) {
|
||||
if (url == null) {
|
||||
if (sourceURL != null) {
|
||||
// easing the current code.
|
||||
sourceCodeLinesList.clear();
|
||||
}
|
||||
return false; // nothing to load
|
||||
} else {
|
||||
if (url.equals(sourceURL)) {
|
||||
return true; // already loaded
|
||||
} else {
|
||||
sourceCodeLinesList.clear();
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
sourceCodeLinesList.addElement(line.replaceAll("\t", " "));
|
||||
}
|
||||
br.close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Could not load source at " + url);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeSelection() {
|
||||
int curSelectedIndex = sourceCodeLines.getSelectedIndex();
|
||||
sourceCodeLines.removeSelectionInterval(curSelectedIndex, curSelectedIndex);
|
||||
}
|
||||
|
||||
public void removeSource() {
|
||||
sourceURL = null;
|
||||
sourceCodeLocation.setText("Source code");
|
||||
sourceCodeLinesList.clear();
|
||||
sourceCodeLines.validate();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,62 +1,62 @@
|
|||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
|
||||
/**
|
||||
* Viewer for ClassHeirarcy, CallGraph and Pointer Analysis results.
|
||||
* A driver for example can be found in com.ibm.wala.js.rhino.vis.JsViewer.
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public class WalaViewer extends JFrame {
|
||||
|
||||
protected static final String DefaultMutableTreeNode = null;
|
||||
|
||||
|
||||
public WalaViewer(CallGraph cg, PointerAnalysis pa) {
|
||||
setNativeLookAndFeel();
|
||||
|
||||
JTabbedPane tabbedPane = new JTabbedPane();
|
||||
tabbedPane.add("Call Graph", new CgPanel(cg));
|
||||
tabbedPane.add("Class Hierarchy", new ChaPanel(cg.getClassHierarchy()));
|
||||
PaPanel paPanel = createPaPanel(cg, pa);
|
||||
paPanel.init();
|
||||
tabbedPane.add("Pointer Analysis", paPanel);
|
||||
|
||||
setSize(600, 800);
|
||||
setExtendedState(MAXIMIZED_BOTH);
|
||||
addWindowListener(new ExitListener());
|
||||
|
||||
this.setTitle("Wala viewer");
|
||||
|
||||
add(tabbedPane);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
protected PaPanel createPaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
return new PaPanel(cg, pa);
|
||||
}
|
||||
|
||||
public static void setNativeLookAndFeel() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExitListener extends WindowAdapter {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent event) {
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
package com.ibm.wala.viz.viewer;
|
||||
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
|
||||
/**
|
||||
* Viewer for ClassHeirarcy, CallGraph and Pointer Analysis results.
|
||||
* A driver for example can be found in com.ibm.wala.js.rhino.vis.JsViewer.
|
||||
* @author yinnonh
|
||||
*
|
||||
*/
|
||||
public class WalaViewer extends JFrame {
|
||||
|
||||
protected static final String DefaultMutableTreeNode = null;
|
||||
|
||||
|
||||
public WalaViewer(CallGraph cg, PointerAnalysis pa) {
|
||||
setNativeLookAndFeel();
|
||||
|
||||
JTabbedPane tabbedPane = new JTabbedPane();
|
||||
tabbedPane.add("Call Graph", new CgPanel(cg));
|
||||
tabbedPane.add("Class Hierarchy", new ChaPanel(cg.getClassHierarchy()));
|
||||
PaPanel paPanel = createPaPanel(cg, pa);
|
||||
paPanel.init();
|
||||
tabbedPane.add("Pointer Analysis", paPanel);
|
||||
|
||||
setSize(600, 800);
|
||||
setExtendedState(MAXIMIZED_BOTH);
|
||||
addWindowListener(new ExitListener());
|
||||
|
||||
this.setTitle("Wala viewer");
|
||||
|
||||
add(tabbedPane);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
protected PaPanel createPaPanel(CallGraph cg, PointerAnalysis pa) {
|
||||
return new PaPanel(cg, pa);
|
||||
}
|
||||
|
||||
public static void setNativeLookAndFeel() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExitListener extends WindowAdapter {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent event) {
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,4 +40,11 @@ public class PlatformUtil {
|
|||
return osname.toLowerCase().contains("windows");
|
||||
}
|
||||
|
||||
/**
|
||||
* are we running on IKVM? see http://www.ikvm.net
|
||||
*/
|
||||
public static boolean onIKVM() {
|
||||
return "IKVM.NET".equals(System.getProperty("java.runtime.name"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue