/* * Created on Nov 25, 2004 * */ package fr.lifl.stc.stan.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.ANEWARRAY; import org.apache.bcel.generic.ATHROW; import org.apache.bcel.generic.ConstantPoolGen; import org.apache.bcel.generic.ExceptionThrower; import org.apache.bcel.generic.Instruction; import org.apache.bcel.generic.InstructionHandle; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.InvokeInstruction; import org.apache.bcel.generic.JSR; import org.apache.bcel.generic.MULTIANEWARRAY; import org.apache.bcel.generic.NEW; import org.apache.bcel.generic.NEWARRAY; import org.apache.bcel.generic.ReferenceType; import org.apache.bcel.generic.BasicType; import org.apache.bcel.generic.Type; import fr.lifl.stc.stan.analyser.MethodAnalyzer; import fr.lifl.stc.stan.execution.stack.Address; import fr.lifl.stc.stan.execution.stack.JvmType; import fr.lifl.stc.stan.execution.stack.Reference; import fr.lifl.stc.stan.execution.stack.Value; import fr.lifl.stc.stan.link.Link; import fr.lifl.stc.stan.policy.Policy; //import fr.lifl.rd2p.jits.tools.ea.util.Printer; /** * @author yann * @author dorina * */ public class MethodInfo { private Vector refs; private Vector
addr; private Vector vals; private Vector jvmAbstractValues; private Method m; private ConstantPoolGen cpg; private InstructionList i_list; private Policy policy; private String className; // Positions (offsets) of all instructions in the list insts private int[] instruction_positions; public MethodInfo(MethodAnalyzer a) { this.m = a.getMethod(); this.cpg = a.getCpg(); this.policy = a.getPolicy(); this.className = a.getClassName(); refs = new Vector(); addr = new Vector
(); vals = new Vector(); jvmAbstractValues = new Vector(); extractInfo(); for(int i = 0; i < jvmAbstractValues.size(); i++) jvmAbstractValues.get(i).setIndex(i); } private void extractInfo() { Reference tmp; Value tmpv; Address tmpa; // tmp = new Reference(Reference.ARETURN_TYPE,-1,null,false, JvmType.PUBLIC_PART, false); // refs.add(tmp); // jvmAbstractValues.add(tmp); tmp = new Reference(Reference.THROWN_TYPE, -1,null,false, JvmType.PUBLIC_PART, false); refs.add(tmp); jvmAbstractValues.add(tmp); // special ref for constant pool strings tmp = new Reference(Reference.CONSTANT_TYPE,-1,null,false, JvmType.PUBLIC_PART, false); refs.add(tmp); jvmAbstractValues.add(tmp); // special ref for null tmp = new Reference(Reference.NULL_TYPE,-1,null,false, JvmType.PUBLIC_PART, false); refs.add(tmp); jvmAbstractValues.add(tmp); // special ref for flux tmp = new Reference(Reference.FLUX_TYPE,-1,null,false, JvmType.PUBLIC_PART, false); refs.add(tmp); jvmAbstractValues.add(tmp); // special ref for static with id -2 tmp = new Reference(Reference.ARGUMENT_TYPE,-2 , null,false, JvmType.PUBLIC_PART, false); refs.add(tmp); jvmAbstractValues.add(tmp); vals.add(Value.getShortInstance()); vals.add(Value.getLongInstance()); jvmAbstractValues.add(Value.getShortInstance()); jvmAbstractValues.add(Value.getLongInstance()); // special ref for this with id -1 if(!m.isStatic()) { tmp = new Reference(Reference.ARGUMENT_TYPE,-1,null, false, JvmType.WHOLE_PART, true);//classHasSecret(this.className)); refs.add(tmp); jvmAbstractValues.add(tmp); } Type[] args = m.getArgumentTypes(); for(int i = 0; i < args.length; i++) { if(args[i] instanceof ReferenceType){ tmp = new Reference(Reference.ARGUMENT_TYPE,i,null,false, JvmType.WHOLE_PART, true);//classHasSecret(className)); refs.add(tmp); jvmAbstractValues.add(tmp); } else if(args[i] instanceof BasicType) { tmpv = new Value(Value.ARGUMENT_TYPE, args[i], i); vals.add(tmpv); jvmAbstractValues.add(tmpv); } } i_list = new InstructionList(m.getCode().getCode()); instruction_positions = i_list.getInstructionPositions(); Iterator it = i_list.iterator(); while(it.hasNext()) { InstructionHandle ih = it.next(); Instruction i = ih.getInstruction(); if (i instanceof ANEWARRAY) { tmp = new Reference(Reference.NEW_TYPE,getInstructionLine(ih),((ANEWARRAY)i).getType(cpg),true, JvmType.WHOLE_PART, true); refs.add(tmp); jvmAbstractValues.add(tmp); } else if (i instanceof MULTIANEWARRAY) { tmp = new Reference(Reference.NEW_TYPE,getInstructionLine(ih),((MULTIANEWARRAY)i).getType(cpg),true, JvmType.WHOLE_PART, true); refs.add(tmp); jvmAbstractValues.add(tmp); } else if (i instanceof NEW) { tmp = new Reference(Reference.NEW_TYPE,getInstructionLine(ih),((NEW)i).getType(cpg),true, JvmType.WHOLE_PART, true);//this.classHasSecret(className) ); refs.add(tmp); jvmAbstractValues.add(tmp); } else if (i instanceof NEWARRAY) { tmp = new Reference(Reference.NEW_TYPE,getInstructionLine(ih),((NEWARRAY)i).getType(),true, JvmType.PUBLIC_PART, false); refs.add(tmp); jvmAbstractValues.add(tmp); } else if (i instanceof JSR) { tmpa = new Address(getInstructionLine(ih)); addr.add(tmpa); jvmAbstractValues.add(tmpa); } else if (i instanceof InvokeInstruction) { InvokeInstruction ins = (InvokeInstruction) i; if (ins.getReturnType(cpg) instanceof ReferenceType) { int partType = MethodInfo.partType(ins.getReturnType(cpg)); tmp = new Reference(Reference.RETURNED_TYPE, getInstructionLine(ih), null, false, partType, (partType==JvmType.WHOLE_PART));//this.classHasSecret(name)); refs.add(tmp); jvmAbstractValues.add(tmp); } else if (ins.getReturnType(cpg) instanceof BasicType && ins.getReturnType(cpg)!=Type.VOID) { tmpv = new Value(Value.RETURNED_TYPE, ins.getReturnType(cpg), getInstructionLine(ih)); vals.add(tmpv); jvmAbstractValues.add(tmpv); } } /* if (i instanceof ExceptionThrower) { addToRefs(Reference.THROWN_TYPE,getInstructionLine(ih),null ,false, JvmType.PUBLIC_PART, false); } */ } } // private void addToRefs(int type, int id, Type t, boolean exactType, int part, boolean hasMult) { // Reference r = new Reference(type, id, t, exactType, part, hasMult); // refs.add(r); // } /** * * @return */ public ConstantPoolGen getCpg() { return cpg; } /** * * @return */ public Method getMethod() { return m; } /** * * @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; } public JvmType[] getJvmValues(){ JvmType[] res = new JvmType[jvmAbstractValues.size()]; Iterator it = jvmAbstractValues.iterator(); int i = 0; while(it.hasNext()) { res[i] = it.next(); i++; } return res; } /** * * @return */ public Reference[] getReferences() { Reference[] res = new Reference[refs.size()]; Iterator it = refs.iterator(); int i = 0; while(it.hasNext()) { res[i] = it.next(); i++; } return res; } /** * * @return */ public Address[] getAddresses() { Address[] res = new Address[refs.size()]; Iterator
it = addr.iterator(); int i = 0; while(it.hasNext()) { res[i] = it.next(); i++; } return res; } /** * * @return */ public Value[] getValues() { Value[] val = new Value[vals.size()]; Iterator it = vals.iterator(); int i=0; while(it.hasNext()) { val[i] = it.next(); i++; } return val; } /** * * @param index * @return */ public InstructionHandle getInstruction(int index) { Iterator it = i_list.iterator(); InstructionHandle ins; while(it.hasNext()) { ins = it.next(); if(getInstructionLine(ins) == index) return ins; } System.err.println("[error] MethodInfo.getInstruction() did not find an instruction for given index "+index+" in "+this.m.getSignature()); return null; } /** * * @param ih * @return */ 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()); // 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]); } } } return h.toArray(new CodeException[h.size()]); } /** * * @param className * @return */ public boolean classHasSecret(String className){ return policy.findClass(className); } /** * * @return */ public String getClassName(){ return this.className; } /** * * @param t * @return */ public static int partType(Type t){ if(t instanceof BasicType) return JvmType.PUBLIC_PART; /*if(t.getSignature().charAt(0)== '[') return JvmType.PUBLIC_PART;*/ return JvmType.WHOLE_PART; } /** * * @param t * @return */ public static int linkType(Type t){ if(t instanceof BasicType) return Link.VALUE_LINK; if(t instanceof ReferenceType) return Link.REFERENCE_LINK; return Link.ANY_LINK; } }