/* * @see com.ibm.wala.cfg.ControlFlowGraph#getProgramCounter(int) */ public int getProgramCounter(int index) { try { return method.getBytecodeIndex(index); } catch (InvalidClassFileException e) { e.printStackTrace(); Assertions.UNREACHABLE(); return -1; } }
public IInstruction[] getInstructions() { try { return method.getInstructions(); } catch (InvalidClassFileException e) { e.printStackTrace(); Assertions.UNREACHABLE(); return null; } }
/* * @see com.ibm.wala.classLoader.IClass#getDeclaredMethods() */ @Override public Collection<IMethod> getDeclaredMethods() { try { computeMethodMapIfNeeded(); } catch (InvalidClassFileException e) { e.printStackTrace(); Assertions.UNREACHABLE(); } return Collections.unmodifiableCollection(methodMap.values()); }
private ExceptionHandler[] getExceptionHandlers() { ExceptionHandler[][] handlers; try { handlers = method.getHandlers(); } catch (InvalidClassFileException e) { e.printStackTrace(); Assertions.UNREACHABLE(); handlers = null; } ExceptionHandler[] hs = handlers[getLastInstructionIndex()]; return hs; }
/* * @see com.ibm.wala.classLoader.IClass#getMethod(com.ibm.wala.types.Selector) */ @Override public IMethod getMethod(Selector selector) { try { computeMethodMapIfNeeded(); } catch (InvalidClassFileException e1) { e1.printStackTrace(); Assertions.UNREACHABLE(); } // my methods + cached parent stuff IMethod result = methodMap.get(selector); if (result != null) { return result; } if (inheritCache != null) { result = inheritCache.get(selector); if (result != null) { return result; } } // check parent, caching if found if (!selector.equals(MethodReference.clinitSelector) && !selector.equals(MethodReference.initSelector)) { IClass superclass = getSuperclass(); if (superclass != null) { IMethod inherit = superclass.getMethod(selector); if (inherit != null) { if (inheritCache == null) { inheritCache = new BimodalMap<Selector, IMethod>(5); } inheritCache.put(selector, inherit); return inherit; } } } // didn't find it yet. special logic for interfaces if (isInterface() || isAbstract()) { final Iterator<IClass> it = getAllImplementedInterfaces().iterator(); // try each superinterface while (it.hasNext()) { IClass k = it.next(); result = k.getMethod(selector); if (result != null) { return result; } } } return null; }
/** * Add any exceptional edges generated by the last instruction in a basic block. * * @param last the last instruction in a basic block. */ protected void addExceptionalEdges(IInstruction last) { IClassHierarchy cha = getMethod().getClassHierarchy(); if (last.isPEI()) { Collection<TypeReference> exceptionTypes = null; boolean goToAllHandlers = false; ExceptionHandler[] hs = getExceptionHandlers(); if (last instanceof ThrowInstruction) { // this class does not have the type information needed // to determine what the athrow throws. So, add an // edge to all reachable handlers. Better information can // be obtained later with SSA type propagation. // TODO: consider pruning to only the exception types that // this method either catches or allocates, since these are // the only types that can flow to an athrow. goToAllHandlers = true; } else { if (hs != null && hs.length > 0) { IClassLoader loader = getMethod().getDeclaringClass().getClassLoader(); BytecodeLanguage l = (BytecodeLanguage) loader.getLanguage(); exceptionTypes = l.getImplicitExceptionTypes(last); if (last instanceof IInvokeInstruction) { IInvokeInstruction call = (IInvokeInstruction) last; exceptionTypes = HashSetFactory.make(exceptionTypes); MethodReference target = MethodReference.findOrCreate( l, loader.getReference(), call.getClassType(), call.getMethodName(), call.getMethodSignature()); try { exceptionTypes.addAll(l.inferInvokeExceptions(target, cha)); } catch (InvalidClassFileException e) { e.printStackTrace(); Assertions.UNREACHABLE(); } } } } if (hs != null && hs.length > 0) { // found a handler for this PEI // create a mutable copy if (!goToAllHandlers) { exceptionTypes = HashSetFactory.make(exceptionTypes); } // this var gets set to false if goToAllHandlers is true but some enclosing exception // handler catches all // exceptions. in such a case, we need not add an exceptional edge to the method exit boolean needEdgeToExitForAllHandlers = true; for (int j = 0; j < hs.length; j++) { if (DEBUG) { System.err.println(" handler " + hs[j]); } BasicBlock b = getBlockForInstruction(hs[j].getHandler()); if (DEBUG) { System.err.println(" target " + b); } if (goToAllHandlers) { // add an edge to the catch block. if (DEBUG) { System.err.println(" gotoAllHandlers " + b); } addExceptionalEdgeTo(b); // if the handler catches all exceptions, we don't need to add an edge to the exit or // any other handlers if (hs[j].getCatchClass() == null) { needEdgeToExitForAllHandlers = false; break; } } else { TypeReference caughtException = null; if (hs[j].getCatchClass() != null) { ClassLoaderReference loader = ShrikeCFG.this.getMethod().getDeclaringClass().getReference().getClassLoader(); caughtException = ShrikeUtil.makeTypeReference(loader, hs[j].getCatchClass()); if (DEBUG) { System.err.println(" caughtException " + caughtException); } IClass caughtClass = cha.lookupClass(caughtException); if (caughtClass == null) { // conservatively add the edge, and raise a warning addExceptionalEdgeTo(b); Warnings.add(FailedExceptionResolutionWarning.create(caughtException)); // null out caughtException, to avoid attempting to process it caughtException = null; } } else { if (DEBUG) { System.err.println(" catchClass() == null"); } // hs[j].getCatchClass() == null. // this means that the handler catches all exceptions. // add the edge and null out all types if (!exceptionTypes.isEmpty()) { addExceptionalEdgeTo(b); exceptionTypes.clear(); caughtException = null; } } if (caughtException != null) { IClass caughtClass = cha.lookupClass(caughtException); // the set "caught" should be the set of exceptions that MUST // have been caught by the handlers in scope ArrayList<TypeReference> caught = new ArrayList<TypeReference>(exceptionTypes.size()); // check if we should add an edge to the catch block. for (TypeReference t : exceptionTypes) { if (t != null) { IClass klass = cha.lookupClass(t); if (klass == null) { Warnings.add(FailedExceptionResolutionWarning.create(caughtException)); // conservatively add an edge addExceptionalEdgeTo(b); } else { boolean subtype1 = cha.isSubclassOf(klass, caughtClass); if (subtype1 || cha.isSubclassOf(caughtClass, klass)) { // add the edge and null out the type from the array addExceptionalEdgeTo(b); if (subtype1) { caught.add(t); } } } } } exceptionTypes.removeAll(caught); } } } // if needed, add an edge to the exit block. if ((exceptionTypes == null && needEdgeToExitForAllHandlers) || (exceptionTypes != null && !exceptionTypes.isEmpty())) { BasicBlock exit = exit(); addExceptionalEdgeTo(exit); } } else { // found no handler for this PEI ... link to the exit block. BasicBlock exit = exit(); addExceptionalEdgeTo(exit); } } }
private void makeBasicBlocks() { ExceptionHandler[][] handlers; try { handlers = method.getHandlers(); } catch (InvalidClassFileException e) { e.printStackTrace(); Assertions.UNREACHABLE(); handlers = null; } boolean[] r = new boolean[getInstructions().length]; boolean[] catchers = new boolean[getInstructions().length]; // we initially start with both the entry and exit block. int blockCount = 2; // Compute r so r[i] == true iff instruction i begins a basic block. // While doing so count the number of blocks. r[0] = true; IInstruction[] instructions = getInstructions(); for (int i = 0; i < instructions.length; i++) { int[] targets = instructions[i].getBranchTargets(); // if there are any targets, then break the basic block here. // also break the basic block after a return if (targets.length > 0 || !instructions[i].isFallThrough()) { if (i + 1 < instructions.length && !r[i + 1]) { r[i + 1] = true; blockCount++; } } for (int j = 0; j < targets.length; j++) { if (!r[targets[j]]) { r[targets[j]] = true; blockCount++; } } if (instructions[i].isPEI()) { ExceptionHandler[] hs = handlers[i]; // break the basic block here. if (i + 1 < instructions.length && !r[i + 1]) { r[i + 1] = true; blockCount++; } if (hs != null && hs.length > 0) { for (int j = 0; j < hs.length; j++) { exceptionHandlers.add(hs[j]); if (!r[hs[j].getHandler()]) { // we have not discovered the catch block yet. // form a new basic block r[hs[j].getHandler()] = true; blockCount++; } catchers[hs[j].getHandler()] = true; } } } } BasicBlock entry = new BasicBlock(-1); addNode(entry); int j = 1; for (int i = 0; i < r.length; i++) { if (r[i]) { BasicBlock b = new BasicBlock(i); addNode(b); if (catchers[i]) { setCatchBlock(j); } j++; } } BasicBlock exit = new BasicBlock(-1); addNode(exit); }