public int countIndirectBranches() { int res = 0; for (Map.Entry<AbsoluteAddress, Instruction> entry : assemblyMap.entrySet()) { Instruction instr = entry.getValue(); if (instr instanceof BranchInstruction) { BranchInstruction branch = (BranchInstruction) instr; if (branch.isIndirect()) { // if branch target is not a memory operand pointing into a static data area of the binary // (imports) if (branch.getBranchDestination() instanceof MemoryOperand) { MemoryOperand memOp = (MemoryOperand) branch.getBranchDestination(); // Import calls have only displacement if (memOp.getBase() == null && memOp.getIndex() == null) { AbsoluteAddress disp = new AbsoluteAddress(memOp.getDisplacement()); // Check whether displacement points into import table ExecutableImage module = getModule(disp); if (module instanceof PEModule && ((PEModule) module).getImportTable().containsKey(disp)) continue; } } res++; // logger.verbose(entry.getKey() + "\t" + getInstructionString(entry.getKey())); } } } return res; }
public LinkedList<BranchInstruction> getIndirectBranches() { LinkedList<BranchInstruction> indirectBranches = new LinkedList<BranchInstruction>(); for (Map.Entry<AbsoluteAddress, Instruction> entry : assemblyMap.entrySet()) { Instruction instr = entry.getValue(); if (instr instanceof BranchInstruction) { BranchInstruction branch = (BranchInstruction) instr; if (branch.isIndirect()) { indirectBranches.add(branch); } } } return indirectBranches; }
public void visitBranchInstruction( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) { byte opcode = branchInstruction.opcode; // Evaluate the target instruction blocks. evaluateInstructionBlock(clazz, method, codeAttribute, offset + branchInstruction.branchOffset); // Evaluate the instructions after a subroutine branch. if (opcode == InstructionConstants.OP_JSR || opcode == InstructionConstants.OP_JSR_W) { // We assume subroutine calls (jsr and jsr_w instructions) don't // change the stack, other than popping the return value. stackSize -= 1; evaluateInstructionBlock( clazz, method, codeAttribute, offset + branchInstruction.length(offset)); } // Some branch instructions always end the current instruction block. exitInstructionBlock = opcode == InstructionConstants.OP_GOTO || opcode == InstructionConstants.OP_GOTO_W || opcode == InstructionConstants.OP_JSR || opcode == InstructionConstants.OP_JSR_W; }
/** @return complete, i.e., deep copy of this list */ public InstructionList copy() { Map<InstructionHandle, InstructionHandle> map = new HashMap<InstructionHandle, InstructionHandle>(); InstructionList il = new InstructionList(); /* Pass 1: Make copies of all instructions, append them to the new list * and associate old instruction references with the new ones, i.e., * a 1:1 mapping. */ for (InstructionHandle ih = start; ih != null; ih = ih.next) { Instruction i = ih.instruction; Instruction c = i.copy(); // Use clone for shallow copy if (c instanceof BranchInstruction) { map.put(ih, il.append((BranchInstruction) c)); } else { map.put(ih, il.append(c)); } } /* Pass 2: Update branch targets. */ InstructionHandle ih = start; InstructionHandle ch = il.start; while (ih != null) { Instruction i = ih.instruction; Instruction c = ch.instruction; if (i instanceof BranchInstruction) { BranchInstruction bi = (BranchInstruction) i; BranchInstruction bc = (BranchInstruction) c; InstructionHandle itarget = bi.getTarget(); // old target // New target is in hash map bc.setTarget(map.get(itarget)); if (bi instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH InstructionHandle[] itargets = ((Select) bi).getTargets(); InstructionHandle[] ctargets = ((Select) bc).getTargets(); for (int j = 0; j < itargets.length; j++) { // Update all targets ctargets[j] = map.get(itargets[j]); } } } ih = ih.next; ch = ch.next; } return il; }
/** * Redirect all references from old_target to new_target, i.e., update targets of branch * instructions. * * @param old_target the old target instruction handle * @param new_target the new target instruction handle */ public void redirectBranches(InstructionHandle old_target, InstructionHandle new_target) { for (InstructionHandle ih = start; ih != null; ih = ih.next) { Instruction i = ih.getInstruction(); if (i instanceof BranchInstruction) { BranchInstruction b = (BranchInstruction) i; InstructionHandle target = b.getTarget(); if (target == old_target) { b.setTarget(new_target); } if (b instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH InstructionHandle[] targets = ((Select) b).getTargets(); for (int j = 0; j < targets.length; j++) { if (targets[j] == old_target) { ((Select) b).setTarget(j, new_target); } } } } } }
public void visitBranchInstruction( Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) { // Check if the instruction is an unconditional goto instruction. byte opcode = branchInstruction.opcode; if (opcode == InstructionConstants.OP_GOTO || opcode == InstructionConstants.OP_GOTO_W) { // Check if the goto instruction points to another simple goto // instruction. int branchOffset = branchInstruction.branchOffset; int targetOffset = offset + branchOffset; if (branchOffset != branchInstruction.length(offset) && !codeAttributeEditor.isModified(offset) && !codeAttributeEditor.isModified(targetOffset)) { Instruction targetInstruction = InstructionFactory.create(codeAttribute.code, targetOffset); if (targetInstruction.opcode == InstructionConstants.OP_GOTO) { // Simplify the goto instruction. int targetBranchOffset = ((BranchInstruction) targetInstruction).branchOffset; Instruction newBranchInstruction = new BranchInstruction(opcode, (branchOffset + targetBranchOffset)); codeAttributeEditor.replaceInstruction(offset, newBranchInstruction); // Visit the instruction, if required. if (extraInstructionVisitor != null) { extraInstructionVisitor.visitBranchInstruction( clazz, method, codeAttribute, offset, branchInstruction); } } } } }
public void setInstruction(InstructionHandle ih) { BranchInstruction.notifyTarget(this.ih, ih, this); this.ih = ih; }
/** * Initialize instruction list from byte array. * * @param code byte array containing the instructions */ public InstructionList(byte[] code) { ByteSequence bytes = new ByteSequence(code); InstructionHandle[] ihs = new InstructionHandle[code.length]; int[] pos = new int[code.length]; // Can't be more than that int count = 0; // Contains actual length /* Pass 1: Create an object for each byte code and append them * to the list. */ try { while (bytes.available() > 0) { // Remember byte offset and associate it with the instruction int off = bytes.getIndex(); pos[count] = off; /* Read one instruction from the byte stream, the byte position is set * accordingly. */ Instruction i = Instruction.readInstruction(bytes); InstructionHandle ih; if (i instanceof BranchInstruction) { ih = append((BranchInstruction) i); } else { ih = append(i); } ih.setPosition(off); ihs[count] = ih; count++; } } catch (IOException e) { throw new ClassGenException(e.toString(), e); } byte_positions = new int[count]; // Trim to proper size System.arraycopy(pos, 0, byte_positions, 0, count); /* Pass 2: Look for BranchInstruction and update their targets, i.e., * convert offsets to instruction handles. */ for (int i = 0; i < count; i++) { if (ihs[i] instanceof BranchHandle) { BranchInstruction bi = (BranchInstruction) ihs[i].instruction; int target = bi.position + bi.getIndex(); /* Byte code position: * relative -> absolute. */ // Search for target position InstructionHandle ih = findHandle(ihs, pos, count, target); if (ih == null) { throw new ClassGenException("Couldn't find target for branch: " + bi); } bi.setTarget(ih); // Update target // If it is a Select instruction, update all branch targets if (bi instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH Select s = (Select) bi; int[] indices = s.getIndices(); for (int j = 0; j < indices.length; j++) { target = bi.position + indices[j]; ih = findHandle(ihs, pos, count, target); if (ih == null) { throw new ClassGenException("Couldn't find target for switch: " + bi); } s.setTarget(j, ih); // Update target } } } } }
public void setEnd(InstructionHandle end) { BranchInstruction.notifyTarget(this.end, end, this); this.end = end; }
public void setStart(InstructionHandle start) { BranchInstruction.notifyTarget(this.start, start, this); this.start = start; }