private static void addEdgesForNode( SDG sdg, PDGNode node, Map<PDGNode, SDGNode> pdg2sdg, SDGBuilder b) { PDG pdg = b.getPDGforId(node.getPdgId()); SDGNode from = pdg2sdg.get(node); if (!pdg.containsVertex(node)) { throw new IllegalStateException(); } for (PDGEdge edge : pdg.outgoingEdgesOf(node)) { SDGNode to = pdg2sdg.get(edge.to); SDGEdge sdgEdge = createEdge(from, to, edge.kind, edge.getLabel()); sdg.addEdge(from, to, sdgEdge); } }
private void run(IProgressMonitor progress) throws CancelException { final Map<PDGNode, PDGNode[]> entry2out = new HashMap<PDGNode, PDGNode[]>(); // add out nodes for each non-primitive parameter for (final PDG pdg : sdg.getAllPDGs()) { // primitive types nodes are null final PDGNode[] formOuts = new PDGNode[pdg.params.length]; for (int i = 0; i < pdg.params.length; i++) { final PDGNode formIn = pdg.params[i]; final TypeReference type = pdg.getParamType(i); if (createOutputParamFor(type)) { final PDGNode formOut = pdg.addOutputFieldChildTo( pdg.entry, formIn.getLabel(), formIn.getBytecodeName(), formIn.getBytecodeIndex(), formIn.getTypeRef()); formOuts[i] = formOut; } } entry2out.put(pdg.entry, formOuts); for (final PDGNode call : pdg.getCalls()) { final PDGNode[] actIns = pdg.getParamIn(call); final PDGNode[] actOuts = new PDGNode[actIns.length]; for (int i = 0; i < actIns.length; i++) { final PDGNode actIn = actIns[i]; final TypeReference type = pdg.getParamType(call, i); if (createOutputParamFor(type)) { final PDGNode actOut = pdg.addOutputFieldChildTo( call, actIn.getLabel(), actIn.getBytecodeName(), actIn.getBytecodeIndex(), actIn.getTypeRef()); actOuts[i] = actOut; } } entry2out.put(call, actOuts); } } // connect form-outs of called procedures with act-outs for (final PDG pdg : sdg.getAllPDGs()) { for (final PDGNode call : pdg.getCalls()) { final PDGNode[] actOuts = entry2out.get(call); assert actOuts != null; for (final PDGEdge out : pdg.outgoingEdgesOf(call)) { if (out.kind == PDGEdge.Kind.CALL_STATIC || out.kind == PDGEdge.Kind.CALL_VIRTUAL) { final PDGNode calleeEntry = out.to; final PDGNode[] formOuts = entry2out.get(calleeEntry); final PDG callee = sdg.getPDGforId(calleeEntry.getPdgId()); assert formOuts != null; assert actOuts.length == formOuts.length; for (int i = 0; i < actOuts.length; i++) { final PDGNode actOut = actOuts[i]; if (actOut != null) { // primitive type (and immutable type) params have no act out callee.addVertex(actOut); final PDGNode formOut = formOuts[i]; if (formOut != null) { callee.addEdge(formOut, actOut, PDGEdge.Kind.PARAMETER_OUT); } } } } } } } // collect reachable points-to elements for reachable fields for each parameter for (final PDG pdg : sdg.getAllPDGs()) { final Map<PDGNode, OrdinalSet<InstanceKey>> node2ptsMod = new HashMap<PDGNode, OrdinalSet<InstanceKey>>(); final Map<PDGNode, OrdinalSet<InstanceKey>> node2ptsRef = new HashMap<PDGNode, OrdinalSet<InstanceKey>>(); final IR ir = pdg.cgNode.getIR(); if (ir == null) { continue; } for (int i = 0; i < pdg.params.length; i++) { if (!pdg.getParamType(i).isPrimitiveType()) { final PDGNode formIn = pdg.params[i]; final int ssaVar = ir.getParameter(i); if (ssaVar >= 0) { final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar); node2ptsMod.put(formIn, ptsSet); } } } final PDGNode[] formOuts = entry2out.get(pdg.entry); for (int i = 0; i < formOuts.length; i++) { final PDGNode formOut = formOuts[i]; if (formOut != null) { final PDGNode formIn = pdg.params[i]; final OrdinalSet<InstanceKey> ptsSet = node2ptsMod.get(formIn); node2ptsRef.put(formOut, ptsSet); } } final TypeReference retType = pdg.getMethod().getReturnType(); if (retType != TypeReference.Void && !retType.isPrimitiveType()) { for (final PDGNode retNode : pdg.getReturns()) { final SSAReturnInstruction ret = (SSAReturnInstruction) pdg.getInstruction(retNode); final int ssaVar = ret.getResult(); final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar); node2ptsRef.put(retNode, ptsSet); } } for (final PDGNode call : pdg.getCalls()) { final PDGNode[] actIns = pdg.getParamIn(call); final SSAAbstractInvokeInstruction invk = (SSAAbstractInvokeInstruction) pdg.getInstruction(call); for (int i = 0; i < actIns.length; i++) { if (!pdg.getParamType(call, i).isPrimitiveType()) { final PDGNode actIn = actIns[i]; final int ssaVar = invk.getUse(i); if (ssaVar >= 0) { final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar); node2ptsRef.put(actIn, ptsSet); } } } final PDGNode actOuts[] = entry2out.get(call); for (int i = 0; i < actIns.length; i++) { final PDGNode actOut = actOuts[i]; if (actOut != null) { final PDGNode actIn = actIns[i]; final OrdinalSet<InstanceKey> ptsSet = node2ptsRef.get(actIn); node2ptsMod.put(actOut, ptsSet); } } final TypeReference callRetType = invk.getDeclaredTarget().getReturnType(); if (callRetType != TypeReference.Void && !callRetType.isPrimitiveType()) { final int ssaVar = invk.getReturnValue(0); final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar); final PDGNode retNode = pdg.getReturnOut(call); node2ptsMod.put(retNode, ptsSet); } } // create mod/ref sets for get & set instructions for (final PDGField read : pdg.getFieldReads()) { if (!read.field.isStatic()) { if (read.field.isArray()) { final SSAArrayLoadInstruction ali = (SSAArrayLoadInstruction) pdg.getInstruction(read.node); final int ssaVarBase = ali.getArrayRef(); if (ssaVarBase >= 0) { final OrdinalSet<InstanceKey> ptsSet = pointsToArrayField(pdg.cgNode, ssaVarBase); node2ptsRef.put(read.accfield, ptsSet); } } else { final SSAGetInstruction get = (SSAGetInstruction) pdg.getInstruction(read.node); final int ssaVarBase = get.getRef(); if (ssaVarBase >= 0) { final IField field = sdg.getClassHierarchy().resolveField(get.getDeclaredField()); final OrdinalSet<InstanceKey> ptsSet = pointsToObjectField(pdg.cgNode, ssaVarBase, field); node2ptsRef.put(read.accfield, ptsSet); } } // final SSAInstruction get = pdg.getInstruction(read.node); // final int ssaVar = get.getDef(); // if (ssaVar >= 0) { // final OrdinalSet<InstanceKey> ptsSet = findReachableInstances(pdg.cgNode, ssaVar); // node2ptsRef.put(read.accfield, ptsSet); // } } } for (final PDGField write : pdg.getFieldWrites()) { if (!write.field.isStatic()) { if (write.field.isArray()) { final SSAArrayStoreInstruction asi = (SSAArrayStoreInstruction) pdg.getInstruction(write.node); final int ssaVarBase = asi.getArrayRef(); if (ssaVarBase >= 0) { final OrdinalSet<InstanceKey> ptsSet = pointsToArrayField(pdg.cgNode, ssaVarBase); node2ptsMod.put(write.accfield, ptsSet); } } else { final SSAPutInstruction put = (SSAPutInstruction) pdg.getInstruction(write.node); final int ssaVarBase = put.getRef(); if (ssaVarBase >= 0) { final IField field = sdg.getClassHierarchy().resolveField(put.getDeclaredField()); final OrdinalSet<InstanceKey> ptsSet = pointsToObjectField(pdg.cgNode, ssaVarBase, field); node2ptsMod.put(write.accfield, ptsSet); } } } } // add data flow for each pdg FlatHeapParamsDataFlow.compute( pdg, node2ptsMod, node2ptsRef, (sdg.cfg.accessPath ? PDGEdge.Kind.DATA_ALIAS : PDGEdge.Kind.DATA_HEAP), progress); } }