Java tutorial
/* * Copyright 2010 Christian Schindelhauer, Peter Thiemann, Faisal Aslam, Luminous Fennell and Gidon Ernst. * All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This code is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * only, as published by the Free Software Foundation. * * This code 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 version 3 for more details (a copy is * included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU General Public License * version 3 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Faisal Aslam * (aslam AT informatik.uni-freibug.de or studentresearcher AT gmail.com) * if you need additional information or have any questions. */ package takatuka.classreader.dataObjs.attribute; import org.apache.commons.lang.builder.*; import takatuka.classreader.dataObjs.*; import takatuka.classreader.logic.file.*; import takatuka.io.*; import java.util.*; import takatuka.classreader.logic.factory.FactoryFacade; import takatuka.classreader.logic.factory.FactoryPlaceholder; import takatuka.classreader.logic.util.*; import takatuka.vm.autoGenerated.forExceptionPrettyPrint.LineNumberController; /** * <p>Title: </p> * <p>Description: </p> * @author Faisal Aslam * @version 1.0 */ public class Instruction implements BaseObject { private static long instructionCount = 1; protected long instructionId = 0; protected String cacheMne = null; private int opcode = -1; //Vector operands = new Vector(); private Un operands = null; private static final String OPNEM = "opcode-mnemonic.properties"; protected int offSet = 0; private static final Properties opcodeMnemoicProperties = PropertyReader.getInstanceOf().loadProperties(OPNEM); private static HashMap mnemonicOpcodeMap = new HashMap(); protected static FactoryFacade factory = FactoryPlaceholder.getInstanceOf().getFactory(); private Un originalOperand = null; private static TreeMap delMe = new TreeMap(); private int originalOffSet = -1; private CodeAtt parentCodeAtt = null; public Instruction() { if (this.instructionId == 0) { this.instructionId = instructionCount++; } } /** * * @return the unique Id per instruction. It is very important */ public long getInstructionId() { return instructionId; } /** * * @return the line number of the instruction. */ public int getLineNumber() { return LineNumberController.getInstanceOf().getLineNumberInfo(instructionId); } public Instruction(int opcode, Un operands, CodeAtt parentCodeAtt) { this(); this.opcode = opcode; try { if (operands == null) { operands = factory.createUn(); } } catch (Exception d) { d.printStackTrace(); Miscellaneous.exit(); } this.operands = operands; this.originalOperand = (Un) operands.clone(); this.parentCodeAtt = parentCodeAtt; } public CodeAtt getParentCodeAtt() { return parentCodeAtt; } public MethodInfo getMethod() { return getParentCodeAtt().getMethod(); } public void setOriginalOffSet(int offSet) { if (originalOffSet != -1) { Miscellaneous.printlnErr("Cannot set offset more than once"); Miscellaneous.exit(); } this.originalOffSet = offSet; } public int getOriginalOffSet() { return this.originalOffSet; } public static void printNotUsed_delMe() { for (int loop = 0; loop < 256; loop++) { if (!delMe.containsKey(loop) && opcodeMnemoicProperties.getProperty(loop + "") != null) { Miscellaneous.println(loop + ", " + opcodeMnemoicProperties.getProperty(loop + "")); } } } public Un getOriginalOperand() { return originalOperand; } /** * * @return true if the instruction referes to a constant pool */ public boolean isCPInstruction() { if (getMnemonic().startsWith("ANEWARRAY") || getMnemonic().startsWith("CHECKCAST") || getMnemonic().startsWith("GETFIELD") || getMnemonic().startsWith("GETSTATIC") || getMnemonic().startsWith("INSTANCEOF") || getMnemonic().startsWith("INVOKE") || getMnemonic().startsWith("LDC") || getMnemonic().startsWith("MULTIANEWARRAY") || getMnemonic().equals("NEW") || getMnemonic().startsWith("PUTFIELD") || getMnemonic().startsWith("PUTSTATIC")) { return true; } return false; } /** * It return ture or false based on the Mnmenonic of the instruction. For example * for instructions like ifeq, it returns true * @return true if this instrucion is branch source */ public boolean isBranchSourceInstruction() { if (getMnemonic().startsWith("GOTO") || getMnemonic().startsWith("IF") || getMnemonic().startsWith("JSR") || getMnemonic().startsWith("LOOKUPSWITCH") || getMnemonic().startsWith("TABLESWITCH")) { return true; } return false; } @Override public Object clone() { Instruction ret = null; try { ret = factory.createInstruction(opcode, (Un) operands.clone(), parentCodeAtt); } catch (Exception d) { d.printStackTrace(); Miscellaneous.exit(); } return ret; } public int getMaxStack1() { return 0; } public int getMaxLocals1() { return 0; } public Un getOperandsData() { return operands; } public void setOffSet(int address) { this.offSet = address; } public int getOffSet() { return offSet; } /** * returns the length of instruction. That is number of bytes used in all operands + 1(for opcode). * @return int */ public int length() { return operands.size() + 1; } public int getOpCode() { return opcode; } /** * Also set the Mnemonic. Otherwise, the instruction will have old cached Mnemonic. * @param opcode */ public void setOpCode(int opcode) { this.opcode = opcode; //cacheMne = null; //Mnemonic is changed too... } public void setOperandsData(Un data) { this.operands = data; } public void setMnemonic(String mn) { this.cacheMne = mn; } public static int getOpcode(String mneomonic) { if (mnemonicOpcodeMap == null || mnemonicOpcodeMap.size() == 0) { //following are opcodes Enumeration enm = opcodeMnemoicProperties.propertyNames(); while (enm.hasMoreElements()) { String name = (String) enm.nextElement(); //we have {mnemoic, opcode} map constructed here mnemonicOpcodeMap.put(opcodeMnemoicProperties.getProperty(name).trim().toUpperCase(), Integer.parseInt(name)); } } Integer retOPCODE = (Integer) mnemonicOpcodeMap.get(mneomonic); if (retOPCODE == null) { return -1; } return retOPCODE; } public static void setAllOffsets(Vector<Instruction> allInstrInput) { int offset = 0; for (int loop = 0; loop < allInstrInput.size(); loop++) { Instruction currInstr = allInstrInput.elementAt(loop); currInstr.setOffSet(offset); offset += currInstr.length(); } } public static String getMnemonic(int opcode) { try { return opcodeMnemoicProperties.getProperty(opcode + "").trim().toUpperCase(); } catch (NullPointerException ex) { Miscellaneous.printlnErr("cannot find mnemonic for opcode =" + opcode); ex.printStackTrace(); Miscellaneous.exit(); } return null; } public String getMnemonic() { if (cacheMne == null) { this.cacheMne = opcodeMnemoicProperties.getProperty(opcode + ""); if (cacheMne != null) { cacheMne = cacheMne.trim().toUpperCase(); } else { Miscellaneous.printlnErr("cannot get the mnemonic for opcode = " + opcode); Miscellaneous.exit(); } } return cacheMne; } @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof Instruction)) { return false; } Instruction inst = (Instruction) obj; if (opcode == inst.opcode && operands.equals(inst.operands) && getMnemonic().equals(inst.getMnemonic())) { return true; } return false; } @Override public int hashCode() { return (new HashCodeBuilder(17, 37)).append(opcode).append(operands).toHashCode(); } @Override public String toString() { String ret = ""; try { ret = writeSelected(null); } catch (Exception d) { d.printStackTrace(); Miscellaneous.exit(); } return ret; } @Override public String writeSelected(BufferedByteCountingOutputStream buff) throws Exception { String ret = ""; ret = ret + "0x" + Integer.toHexString(getOffSet()) + ":" + getInstructionId() + " " + getMnemonic(); new Un(getOpCode()).trim(1).writeSelected(buff); ret = ret + " " + (getOperandsData().size() > 0 ? "0x" : "") + getOperandsData().writeSelected(buff); return ret; } }