⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 controlflowgraph.java

📁 Java Bytecode Editor 是一个 JAVA 的字节码反汇编和修改器。它可以很方便的修改已经编译成 Class 文件的 JAVA 文件。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:

		/**
		 * Does the actual merging (vmspec2, page 146).
		 * Returns true IFF this.inFrame was changed in course of merging with inFrame.
		 */
		private boolean mergeInFrames(Frame inFrame){
			// TODO: Can be performance-improved.
			Frame inF = (Frame) inFrames.get(lastExecutionJSR());
			OperandStack oldstack = inF.getStack().getClone();
			LocalVariables oldlocals = inF.getLocals().getClone();
			try{
				inF.getStack().merge(inFrame.getStack());
				inF.getLocals().merge(inFrame.getLocals());
			}
			catch (StructuralCodeConstraintException sce){
				extendMessageWithFlow(sce);
				throw sce;
			}
			if (	oldstack.equals(inF.getStack()) &&
						oldlocals.equals(inF.getLocals()) ){
				return false;
			}
			else{
				return true;
			}
		}

		/**
		 * Returns the control flow execution chain. This is built
		 * while execute(Frame, ArrayList)-ing the code represented
		 * by the surrounding ControlFlowGraph.
		 */
		private String getExecutionChain(){
			String s = this.toString();
			for (int i=executionPredecessors.size()-1; i>=0; i--){
				s = executionPredecessors.get(i)+"\n" + s;
			}
			return s;
		}


		/**
		 * Extends the StructuralCodeConstraintException ("e") object with an at-the-end-extended message.
		 * This extended message will then reflect the execution flow needed to get to the constraint
		 * violation that triggered the throwing of the "e" object.
		 */
		private void extendMessageWithFlow(StructuralCodeConstraintException e){
			String s = "Execution flow:\n";
			e.extendMessage("", s+getExecutionChain());
		}

		/*
		 * Fulfils the contract of InstructionContext.getInstruction().
		 */
		public InstructionHandle getInstruction(){
			return instruction;
		}

		/**
		 * Returns the InstructionContextImpl with an JSR/JSR_W
		 * that was last in the ExecutionChain, without
		 * a corresponding RET, i.e.
		 * we were called by this one.
		 * Returns null if we were called from the top level.
		 */
		private InstructionContextImpl lastExecutionJSR(){
			
			int size = executionPredecessors.size();
			int retcount = 0;
			
			for (int i=size-1; i>=0; i--){
				InstructionContextImpl current = (InstructionContextImpl) (executionPredecessors.get(i));
				Instruction currentlast = current.getInstruction().getInstruction();
				if (currentlast instanceof RET) retcount++;
				if (currentlast instanceof JsrInstruction){
					retcount--;
					if (retcount == -1) return current;
				}
			}
			return null;
		}

		/* Satisfies InstructionContext.getSuccessors(). */
		public InstructionContext[] getSuccessors(){
			return contextsOf(_getSuccessors());
		}

		/**
		 * A utility method that calculates the successors of a given InstructionHandle
		 * That means, a RET does have successors as defined here.
		 * A JsrInstruction has its target as its successor
		 * (opposed to its physical successor) as defined here.
		 */
// TODO: implement caching!
		private InstructionHandle[] _getSuccessors(){
			final InstructionHandle[] empty = new InstructionHandle[0];
			final InstructionHandle[] single = new InstructionHandle[1];
			final InstructionHandle[] pair = new InstructionHandle[2];
		
			Instruction inst = getInstruction().getInstruction();
		
			if (inst instanceof RET){
				Subroutine s = subroutines.subroutineOf(getInstruction());
				if (s==null){ //return empty; // RET in dead code. "empty" would be the correct answer, but we know something about the surrounding project...
					throw new AssertionViolatedException("Asking for successors of a RET in dead code?!");
				}
//TODO: remove
throw new AssertionViolatedException("DID YOU REALLY WANT TO ASK FOR RET'S SUCCS?");
/*
				InstructionHandle[] jsrs = s.getEnteringJsrInstructions();
				InstructionHandle[] ret = new InstructionHandle[jsrs.length];
				for (int i=0; i<jsrs.length; i++){
					ret[i] = jsrs[i].getNext();
				}
				return ret;
*/
			}
		
			// Terminates method normally.
			if (inst instanceof ReturnInstruction){
				return empty;
			}
		
			// Terminates method abnormally, because JustIce mandates
			// subroutines not to be protected by exception handlers.
			if (inst instanceof ATHROW){
				return empty;
			}
		
			// See method comment.
			if (inst instanceof JsrInstruction){
				single[0] = ((JsrInstruction) inst).getTarget();
				return single;
			}

			if (inst instanceof GotoInstruction){
				single[0] = ((GotoInstruction) inst).getTarget();
				return single;
			}

			if (inst instanceof BranchInstruction){
				if (inst instanceof Select){
					// BCEL's getTargets() returns only the non-default targets,
					// thanks to Eli Tilevich for reporting.
					InstructionHandle[] matchTargets = ((Select) inst).getTargets();
					InstructionHandle[] ret = new InstructionHandle[matchTargets.length+1];
					ret[0] = ((Select) inst).getTarget();
					System.arraycopy(matchTargets, 0, ret, 1, matchTargets.length);
					return ret;
				}
				else{
					pair[0] = getInstruction().getNext();
					pair[1] = ((BranchInstruction) inst).getTarget();
					return pair;
				}
			}

			// default case: Fall through.		
			single[0] = getInstruction().getNext();
			return single;
		}

	} // End Inner InstructionContextImpl Class.

	/** The MethofGen object we're working on. */
	//private final MethodGen method_gen;

	/** The Subroutines object for the method whose control flow is represented by this ControlFlowGraph. */
	private final Subroutines subroutines;

	/** The ExceptionHandlers object for the method whose control flow is represented by this ControlFlowGraph. */
	private final ExceptionHandlers exceptionhandlers;

	/** All InstructionContext instances of this ControlFlowGraph. */
	private Hashtable<InstructionHandle, InstructionContextImpl> instructionContexts = new Hashtable<InstructionHandle, InstructionContextImpl>(); //keys: InstructionHandle, values: InstructionContextImpl

	/** 
	 * A Control Flow Graph.
	 */
	public ControlFlowGraph(MethodGen method_gen){
		subroutines = new Subroutines(method_gen);
		exceptionhandlers = new ExceptionHandlers(method_gen);

		InstructionHandle[] instructionhandles = method_gen.getInstructionList().getInstructionHandles();
		for (int i=0; i<instructionhandles.length; i++){
			instructionContexts.put(instructionhandles[i], new InstructionContextImpl(instructionhandles[i]));
		}
		
		//this.method_gen = method_gen;
	}

	/**
	 * Returns the InstructionContext of a given instruction.
	 */
	public InstructionContext contextOf(InstructionHandle inst){
		InstructionContext ic = (InstructionContext) instructionContexts.get(inst);
		if (ic == null){
			throw new AssertionViolatedException("InstructionContext requested for an InstructionHandle that's not known!");
		}
		return ic;
	}

	/**
	 * Returns the InstructionContext[] of a given InstructionHandle[],
	 * in a naturally ordered manner.
	 */
	public InstructionContext[] contextsOf(InstructionHandle[] insts){
		InstructionContext[] ret = new InstructionContext[insts.length];
		for (int i=0; i<insts.length; i++){
			ret[i] = contextOf(insts[i]);
		}
		return ret;
	}

	/**
	 * Returns an InstructionContext[] with all the InstructionContext instances
	 * for the method whose control flow is represented by this ControlFlowGraph
	 * <B>(NOT ORDERED!)</B>.
	 */
	public InstructionContext[] getInstructionContexts(){
		InstructionContext[] ret = new InstructionContext[instructionContexts.values().size()];
		return (InstructionContext[]) instructionContexts.values().toArray(ret);
	}

	/**
	 * Returns true, if and only if the said instruction is not reachable; that means,
	 * if it not part of this ControlFlowGraph.
	 */
	public boolean isDead(InstructionHandle i){
		return instructionContexts.containsKey(i);
	}	 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -