package fr.lifl.stc.stan.implicitFlow.execution; import java.util.Iterator; import java.util.Vector; import org.apache.bcel.classfile.CodeException; import org.apache.bcel.classfile.Method; import org.apache.bcel.generic.ATHROW; import org.apache.bcel.generic.ExceptionThrower; import org.apache.bcel.generic.InstructionHandle; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.Select; import fr.lifl.stc.stan.analyser.MethodAnalyzer; import fr.lifl.stc.stan.implicitFlow.data.BooleanVariable; /** * * @author dorina * */ public class MethodInfoIF { /** * vector of BooleanVariable associated to conditional bytecodes */ private Vector conditions; private Method m; // private ConstantPoolGen cpg; private InstructionList i_list; // Positions (offsets) of all instructions in the list insts private int[] instruction_positions; public MethodInfoIF(MethodAnalyzer a) { this.m = a.getMethod(); // this.cpg = a.getCpg(); i_list = new InstructionList(m.getCode().getCode()); instruction_positions = i_list.getInstructionPositions(); conditions = new Vector(); //System.out.println("Method "+m.getName()+" in class = "+ className+" maxLocals="+ m.getCode().getMaxLocals()); extractConditionalBytecodes(); } private void extractConditionalBytecodes(){ InstructionList i_list; i_list = new InstructionList(m.getCode().getCode()); Iterator it = i_list.iterator(); //Instruction i; InstructionTypeIF itype; while(it.hasNext()) { InstructionHandle ih = it.next(); itype = InstructionTypeIF.getType(ih.getInstruction()); if( itype == InstructionTypeIF.CONDITIONAL_INSTRUCTION){ conditions.add( new BooleanVariable(ih.getPosition(), BooleanVariable.VARIABLE_TYPE)); } else if( itype == InstructionTypeIF.LOOKUPSWITCH_INSTRUCTION || itype == InstructionTypeIF.TABLESWITCH_INSTRUCTION){ Select inst = (Select)ih.getInstruction(); int noMatchs= inst.getMatchs().length; for(int i=0; i < noMatchs; i++){ conditions.add(new BooleanVariable(ih.getPosition(), BooleanVariable.SWITCH_TYPE, i)); } //conditions.add(new BooleanVariable(ih.getPosition(), BooleanVariable.SWITCH_TYPE, -1)); } } } public InstructionHandle[] getRealExceptionHandlers(InstructionHandle ih) { if(!(ih.getInstruction() instanceof ExceptionThrower || ih.getInstruction() instanceof ATHROW)) return null; Vector handlers = new Vector(); CodeException[] exh = sortExceptionHandlers(m.getCode().getExceptionTable(),ih.getPosition()); // TODO: see if we can do better // Insert all handlers because we're unable to determine which ones are reached for(int j = 0; j < exh.length; j++) { handlers.add(exh[j]); } InstructionHandle [] res = new InstructionHandle[handlers.size()]; for(int i = 0; i < res.length; i++) { res[i] = i_list.findHandle(handlers.elementAt(i).getHandlerPC()); } return res; } /** * * @param handlers * @param position * @return */ private CodeException[] sortExceptionHandlers(CodeException[] handlers, int position) { Vector h = new Vector(); for(int i = 0; i < handlers.length; i++) { if(handlers[i].getStartPC() > position || handlers[i].getEndPC() < position) // this handler is not for us continue; else { // insert the handler at the right position int j = 0; while(j < h.size()) { if(handlers[i].getStartPC() > h.elementAt(j).getStartPC()) { h.insertElementAt(handlers[i],j); break; } j++; } if(j == h.size()) { h.add(handlers[i]); } } } CodeException[] res = new CodeException[h.size()]; Object[] tab = h.toArray(); for(int i = 0; i < res.length; i++) { res[i] = (CodeException)tab[i]; } return res; } /** * * @return */ public BooleanVariable[] getConditions() { BooleanVariable[] b = new BooleanVariable[conditions.size()]; Iterator it = conditions.iterator(); int i=0; while(it.hasNext()) { b[i] = it.next(); i++; } return b; } /** * * @return */ public int instructionNumber() { return i_list.size(); } /** * * @return */ public InstructionHandle firstInstruction() { return i_list.getStart(); } /** * find the line number of the instruction 'ih' * @param ih * @return */ public int getInstructionLine(InstructionHandle ih) { if (ih != null) for (int i = 0; i < instruction_positions.length; i++) if (instruction_positions[i] == ih.getPosition()) return i; return -1; } }