All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jreversepro.runtime.JRunTimeContext Maven / Gradle / Ivy

/*
  @(#)JRunTimeContext.java JReversePro - Java Decompiler / Disassembler.
 * Copyright (C) 2000 2001 Karthik Kumar.
 * EMail: [email protected]
 * 

* This program is free software; you can redistribute it and/or modify * it , under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program.If not, write to * The Free Software Foundation, Inc., * 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package jreversepro.runtime; import jreversepro.common.Helper; import jreversepro.common.KeyWords; import jreversepro.parser.ClassParserException; import jreversepro.reflect.JInstruction; import jreversepro.reflect.JLineOfCode; import jreversepro.reflect.JMethod; import jreversepro.revengine.*; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Stack; /** * This contains the RunTime context. * * @author Karthik Kumar */ public class JRunTimeContext implements KeyWords, BranchConstants { /** * Contains the list of branchentries ( control blocks of source * code ). */ final JBranchTable branches; /** * Decompiler reference */ final JDecompiler decomp; /** * This Stack contains the individual control blocks. * Individual elements are BranchEntry. */ final Stack jcs; /** * Operand Stack reference. */ final JOperandStack jos; //preserves the context. /** * Method reference */ final JMethod method; /** * Runtime Frame contains SymbolTable and ConstantPool. */ final JRunTimeFrame rtf; /** * Control block that is on top of the Control Block stack. */ JBranchEntry currBlock; /** * If set then while executing instruction the contents of * stack are merged. Used for the case of ternary expressions. */ boolean mergeStack; /** * previous control block that was popped from the Control Stack. * See member jcs - Control Stack implementation. */ JBranchEntry prevBlock; /** * If the code is written for the block */ boolean writtenCode; /** * @param meth Method reference. * @param decomp Decompiler reference. * @param rtf RuntimeFrame input * @param jos OperandStack reference * @param branches BranchReference. */ public JRunTimeContext(JDecompiler decomp, JMethod meth, JRunTimeFrame rtf, JOperandStack jos, JBranchTable branches) { this.decomp = decomp; this.method = meth; this.jos = jos; this.rtf = rtf; this.branches = branches; mergeStack = false; writtenCode = false; this.jcs = new Stack<>(); } /** * Adds a line of code with byteoffset information * * @param sOffset Offset information * @param eOffset ??? Extended offset * @param fromPos FromPosition * @param toPos To Position */ public void addCode(int sOffset, int eOffset, int fromPos, int toPos) { addCode(sOffset, eOffset, fromPos, toPos, "");//No type information. } /** * Adds a line of code with byteoffset information * * @param sOffset Offset information * @param eOffset ??? Extended offset * @param fromPos FromPosition * @param toPos To Position * @param type ?? type. */ public void addCode(int sOffset, int eOffset, int fromPos, int toPos, String type) { setBlockWrittenFlag(); writtenCode = true; method.addLineOfCode(new JLineOfCode(sOffset, eOffset, fromPos, toPos, type + rtf.getStatement() + ";\n")); } /** * In case a statement has been identified for writing * for the current topmost block then that is set * the written flag. */ public void setBlockWrittenFlag() { if (!jcs.empty()) { currBlock.setWrittenFlag(); } } /** * Add text line to output code with indenting. * * @param txt Text to be added. */ public void addTextCode(String txt) { //PP *** Need to identify offsets for next line *** method.addLineOfCode(new JLineOfCode(-1, -1, -1, -1, txt + "\n")); } /** * Process JVM instruction. * * @param ins Instruction that is to be executed. * @throws RevEngineException thrown in case * any problem occurs while executing the instruction. * @throws ClassParserException Thrown in case of * an invalid reference to Constantpool. */ public void executeInstruction(JInstruction ins) throws RevEngineException, ClassParserException { if (mergeStack) { jos.mergeTopTwo(); } rtf.operateStack(ins, jos); mergeStack = false; } /** * @param listBranches List of branches * @param insIndex Instruction Index * @param symTable SymbolTable. * @throws RevEngineException thrown while generating the * beginning statement for the given block. */ public void getBeginStmt(List listBranches, int insIndex, JSymbolTable symTable) throws RevEngineException { for (Object listBranche : listBranches) { JBranchEntry ent = (JBranchEntry) listBranche; writeVariableDeclarations(ent, symTable); ent.appendStartBlockStmtX(decomp); setBlockWrittenFlag(); pushControlEntry(ent); if (ent.getType() == TYPE_IF) { JBranchEntry loop = getImmediateOuterLoop(); if (loop != null) { int target = ent.getTargetPc(); if (target == loop.getNextPc()) { //PP *** Need to identify offsets for next line *** method.addLineOfCode(new JLineOfCode(-1, -1, -1, -1, KeyWords.BREAK + ";\n")); ent.appendEndBlockStmt(decomp, jos); } else if (target == loop.getStartPc()) { //PP *** Need to identify offsets for next line *** method.addLineOfCode(new JLineOfCode(-1, -1, -1, -1, KeyWords.CONTINUE + ";\n")); ent.appendEndBlockStmt(decomp, jos); } } } } } /** * @param ent Entry ( Control Block ) for which all the * variable declarations are supposed to be in place. * @param symTable Reference to symbol table that is * necessary to get to know the names and datatypes of variables. * @throws RevEngineException Thrown in case of any problem * writing variable names in the table. */ public void writeVariableDeclarations(JBranchEntry ent, JSymbolTable symTable) throws RevEngineException { Enumeration enumVariables = Collections.enumeration(symTable.defineVariable(ent.getEndBlockPc())); while (enumVariables.hasMoreElements()) { String varDec = enumVariables.nextElement().toString(); //PP *** Need to identify offsets for next line *** method.addLineOfCode(new JLineOfCode(-1, -1, -1, -1, varDec + ";\n")); } } /** * @param newent NewEntry of the control block that is to be pushed * onto the stack. * @throws RevEngineException thrown if the end block of the entry * of the content to be pushed overlaps with the end of the entry existing * already on top of control block stack. */ public void pushControlEntry(JBranchEntry newent) throws RevEngineException { if (!jcs.empty()) { if (newent.getEndBlockPc() == -1) { JBranchEntry topEnt = jcs.peek(); newent.setEndBlockPc(topEnt.getEndBlockPc()); //This case is for // } catch ( ) { // //} catch ( ) { // //} //Resetting of the first catch end block pc. } else if (newent.getEndBlockPc() > currBlock.getEndBlockPc()) { if (newent.getType() == TYPE_CATCH || newent.getType() == TYPE_CATCH_ANY) { //We have guessed catch boundary in //JDecompiler :: closeCatchBlock too far. //Hence we are restricting it within the prev. //namespace. newent.setEndBlockPc(currBlock.getEndBlockPc()); } else if (newent.getType() == TYPE_TRY && (currBlock.getType() == TYPE_CATCH || currBlock.getType() == TYPE_CATCH_ANY)) { //try { // //}...catch { <-- currBlock // // try { <-- newent // // } catch ( ... ) { // // } //} currBlock.setEndBlockPc(newent.getEndBlockPc() + 1); //Ideally we have to guess the currentBlock Pc again. } else { //This overlap is bad. //We guessed wrong previously for this block. //No excuses . Go all over again here. throw new RevEngineException("Block overlap " + newent.toString() + " with " + currBlock .toString()); } } } jcs.push(newent); currBlock = newent; } /** * At any given stage this method returns the reference to * while/ do..while/ switch statement that enclosed this, to the * outermost reference. This method is mainly useful in case of * break and continue.. statements. * * @return Returns a reference to control block of outermost loop. */ public JBranchEntry getImmediateOuterLoop() { for (int i = jcs.size() - 1; i >= 0; i--) { JBranchEntry ent = jcs.get(i); if (ent.getType() == TYPE_DO_WHILE || ent.getType() == TYPE_WHILE || ent.getType() == TYPE_SWITCH) { return ent; } } return null; } /** * Close current branch block regularly. * For a given end-point of one or more control-blocks, * this appends the End-Of-Block statements. * * @param insIndex Instruction Index. * @throws RevEngineException Encountered while * trying to find the end statement. */ public void getEndStmt(int insIndex) throws RevEngineException { while (currBlock != null && currBlock.getEndBlockPc() == insIndex) { mergeStack |= currBlock.appendEndBlockStmt(decomp, jos); writtenCode = false; prevBlock = jcs.pop(); currBlock = (jcs.empty()) ? null : jcs.peek(); } } /** * After all the processing of the method is over, this * code generated the final block statement, if any. */ public void getFinalBlockStmt() { while (!jcs.empty()) { prevBlock = jcs.pop(); prevBlock.appendEndBlockStmt(decomp, jos); } } /** * Get JVM Operand stack. * * @return Returns Operand Stack. */ public JOperandStack getOperandStack() { return jos; } /** * @param startPc Startpc * @param targetPc TargetPc */ public void processBreakContinue(int startPc, int targetPc) { JBranchEntry loopEntry = getImmediateOuterLoop(); if (loopEntry == null) { return; } Helper.log("Outer loop " + loopEntry); if (targetPc == loopEntry.getNextPc()) { //PP *** Need to identify offsets for next line *** method.addLineOfCode(new JLineOfCode(-1, -1, -1, -1, BREAK + ";\n")); branches.deleteElse(startPc + 3); } else if (targetPc == loopEntry.getStartPc() && startPc != loopEntry.getNextPc() - 3) { //PP *** Need to identify offsets for next line *** method.addLineOfCode(new JLineOfCode(-1, -1, -1, -1, CONTINUE + ";\n")); branches.deleteElse(startPc + 3); } } /** * @return String representation of the class. */ public String toString() { return jcs.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy