From: <mic...@us...> - 2007-07-29 13:13:15
|
Revision: 152 http://pearcolator.svn.sourceforge.net/pearcolator/?rev=152&view=rev Author: michael_baer Date: 2007-07-29 06:13:16 -0700 (Sun, 29 Jul 2007) Log Message: ----------- - Made profiling during interpretation a functionality provided by the ExecutionController - Added new ExecutionController - Restructured branch profiling slightly Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Options.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/generic/branchprofile/BranchProfile.java src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java src/org/binarytranslator/generic/decoder/CodeTranslator.java src/org/binarytranslator/generic/decoder/Interpreter.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/generic/decoder/Disassembler.java src/org/binarytranslator/generic/execution/ProfilingPredecodingInterpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-07-11 16:34:25 UTC (rev 151) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-07-29 13:13:16 UTC (rev 152) @@ -9,7 +9,6 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; -import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.decoder.Utils; @@ -23,7 +22,7 @@ * @author Michael Baer */ public class ARM_Interpreter implements Interpreter { - + /** The process space that we're interpreting.*/ protected final ARM_ProcessSpace ps; @@ -31,7 +30,7 @@ protected final ARM_Registers regs; /** The interpreter factory is creating the final instructions, which implement the Interpreter.Instruction interface. */ - protected final ARM_InstructionFactory<ARM_Instruction> instructionFactory; + protected final InterpreterFactory instructionFactory; public ARM_Interpreter(ARM_ProcessSpace ps) { this.ps = ps; @@ -41,9 +40,11 @@ /** Decodes the instruction at the given address.*/ public Instruction decode(int pc) { - + ARM_Instruction instruction; + instructionFactory.setInstructionAddress(pc); + if ((pc & 1) != 0) { short binaryInstruction = (short)ps.memory.loadInstruction16(pc & 0xFFFFFFFE); instruction = ARM_InstructionDecoder.Thumb.decode(binaryInstruction, instructionFactory); @@ -54,7 +55,7 @@ } if (instruction.getCondition() != Condition.AL) { - return new ConditionalDecorator(instruction); + return new ConditionalDecorator(instruction, pc); } return instruction; @@ -123,7 +124,7 @@ if (operand.getRegister() == ARM_Registers.PC) value = regs.readPC(); else - value =regs.get(operand.getRegister()); + value = regs.get(operand.getRegister()); value += operand.getOffset(); return; @@ -364,43 +365,66 @@ * instruction (or not). The instruction classes itself do not check any conditions. */ private final class ConditionalDecorator implements Interpreter.Instruction { + /** The conditional instruction. */ protected final ARM_Instruction conditionalInstruction; - private final Condition condition; + + /** The address of the successor of the conditional instruction. Can be -1, if it cannot be determined statically. */ + private final int conditionTrueSuccessor; + + /** The successor of this instruction, if the condition evaluates to false.*/ + private final int conditionFalseSuccessor; + + /** The address of the successor of this instrction if it is constant, otherwise -1. */ + private final int successorInstruction; + + /** The address of this instruction. */ + private final int instructionAddress; /** Decorates an ARM interpreter instruction, by making it execute conditionally. */ - protected ConditionalDecorator(ARM_Instruction i) { - conditionalInstruction = i; - this.condition = i.getCondition(); + protected ConditionalDecorator(ARM_Instruction i, int pc) { + this.conditionalInstruction = i; + + conditionTrueSuccessor = conditionalInstruction.getSuccessor(pc); + boolean inThumbMode = (pc & 1) == 0; + + if (conditionTrueSuccessor == pc + 4 && !inThumbMode) + successorInstruction = conditionTrueSuccessor; //ARM may have conditional instruction that are not jumps + else + successorInstruction = -1; + + conditionFalseSuccessor = pc + (inThumbMode ? 2 : 4); + instructionAddress = pc; } public void execute() { + if (isConditionTrue()) { - int nextInstruction = conditionalInstruction.getSuccessor(ps.getCurrentInstructionAddress()); conditionalInstruction.execute(); - if (nextInstruction != -1) - ps.setCurrentInstructionAddress(nextInstruction); + if (conditionTrueSuccessor != -1) { + ps.setCurrentInstructionAddress(conditionTrueSuccessor); + } + + if (successorInstruction != -1) { + ps.branchInfo.profileBranch(instructionAddress, conditionTrueSuccessor); + } } else { - ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress() + (regs.getThumbMode() ? 2 : 4)); + ps.setCurrentInstructionAddress(conditionFalseSuccessor); + + if (successorInstruction != -1) { + ps.branchInfo.profileBranch(instructionAddress, conditionFalseSuccessor); + } } } public int getSuccessor(int pc) { - //if this instruction is not a jump, then we can tell what the next instruction will be. - - int conditionalSuccessor = conditionalInstruction.getSuccessor(pc); - boolean thumbMode = (pc & 0x1) == 1; - - if (conditionalSuccessor == pc + 4 && !thumbMode) - return conditionalSuccessor; //ARM may have conditional non-jump instructions - else - return -1; + return successorInstruction; } /** Return true if the condition required by the conditional instruction is fulfilled, false otherwise.*/ private boolean isConditionTrue() { - switch (condition) { + switch (conditionalInstruction.getCondition()) { case AL: throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator."); @@ -450,7 +474,7 @@ return regs.isOverflowSet(); default: - throw new RuntimeException("Unexpected condition code: " + condition); + throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); } } @@ -514,10 +538,6 @@ if (i.Rd == ARM_Registers.PC) { if (regs.getThumbMode()) result |= 1; - - if (DBT_Options.profileDuringInterpretation) { - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH); - } } regs.set(i.Rd, result); @@ -533,13 +553,8 @@ setFlagsForSub(lhs, rhs); int result = lhs - rhs; - if (i.Rd == ARM_Registers.PC) { - if (regs.getThumbMode()) - result |= 1; - - if (DBT_Options.profileDuringInterpretation) { - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH); - } + if (i.Rd == ARM_Registers.PC && regs.getThumbMode()) { + result |= 1; } regs.set(i.Rd, result); @@ -595,8 +610,13 @@ * out value. The value of the barrel shifter is stored within this variable. */ protected boolean shifterCarryOut; - protected DataProcessing_Logical(ARM_Instructions.DataProcessing instr) { + protected DataProcessing_Logical(ARM_Instructions.DataProcessing instr, int instructionAddress) { super(instr); + + if (DBT_Options.profileDuringInterpretation) { + if (i.getOpcode() == Opcode.MOV && i.operand2.getType() == OperandWrapper.Type.Register && i.operand2.getRegister() == ARM_Registers.LR) + ps.branchInfo.registerReturnSite(instructionAddress); + } } /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift @@ -622,13 +642,6 @@ if (regs.getThumbMode()) result |= 1; - - if (DBT_Options.profileDuringInterpretation) { - if (i.getOpcode() == Opcode.MOV && i.operand2.getType() == OperandWrapper.Type.Register && i.operand2.getRegister() == ARM_Registers.LR) - ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), result); - else - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH); - } } regs.set(i.Rd, result); @@ -651,8 +664,8 @@ /** Binary and. <code>Rd = op1 & op2 </code>.*/ private final class DataProcessing_And extends DataProcessing_Logical { - protected DataProcessing_And(ARM_Instructions.DataProcessing instr) { - super(instr); + protected DataProcessing_And(ARM_Instructions.DataProcessing instr, int instructionAddress) { + super(instr, instructionAddress); } @Override @@ -665,8 +678,8 @@ /** Exclusive or. <code>Rd = op1 ^ op2 </code>.*/ private final class DataProcessing_Eor extends DataProcessing_Logical { - protected DataProcessing_Eor(ARM_Instructions.DataProcessing instr) { - super(instr); + protected DataProcessing_Eor(ARM_Instructions.DataProcessing instr, int instructionAddress) { + super(instr, instructionAddress); } @Override @@ -804,8 +817,8 @@ * <code>Flags = op1 & op2</code>*/ private final class DataProcessing_Tst extends DataProcessing_Logical { - protected DataProcessing_Tst(ARM_Instructions.DataProcessing instr) { - super(instr); + protected DataProcessing_Tst(ARM_Instructions.DataProcessing instr, int instructionAddress) { + super(instr, instructionAddress); } @Override @@ -818,8 +831,8 @@ * <code>Flags = op1 ^ op2</code> */ private final class DataProcessing_Teq extends DataProcessing_Logical { - protected DataProcessing_Teq(ARM_Instructions.DataProcessing instr) { - super(instr); + protected DataProcessing_Teq(ARM_Instructions.DataProcessing instr, int instructionAddress) { + super(instr, instructionAddress); } @Override @@ -859,8 +872,8 @@ /** Binary or. <code>Rd = op1 | op2</code>. */ private final class DataProcessing_Orr extends DataProcessing_Logical { - protected DataProcessing_Orr(ARM_Instructions.DataProcessing instr) { - super(instr); + protected DataProcessing_Orr(ARM_Instructions.DataProcessing instr, int instructionAddress) { + super(instr, instructionAddress); } @Override @@ -872,8 +885,8 @@ private final class DataProcessing_Mov extends DataProcessing_Logical { - protected DataProcessing_Mov(ARM_Instructions.DataProcessing instr) { - super(instr); + protected DataProcessing_Mov(ARM_Instructions.DataProcessing instr, int instructionAddress) { + super(instr, instructionAddress); } @Override @@ -888,8 +901,8 @@ * <code>Rd = op1 & (~op2)</code>.*/ private final class DataProcessing_Bic extends DataProcessing_Logical { - protected DataProcessing_Bic(ARM_Instructions.DataProcessing instr) { - super(instr); + protected DataProcessing_Bic(ARM_Instructions.DataProcessing instr, int instructionAddress) { + super(instr, instructionAddress); } @Override @@ -904,8 +917,8 @@ * <code>Rd = ~op2</code>.*/ private final class DataProcessing_Mvn extends DataProcessing_Logical { - protected DataProcessing_Mvn(ARM_Instructions.DataProcessing instr) { - super(instr); + protected DataProcessing_Mvn(ARM_Instructions.DataProcessing instr, int instructionAddress) { + super(instr, instructionAddress); } @Override @@ -1000,22 +1013,26 @@ /** Should writeback be performed? */ private final boolean doWriteback; - public BlockDataTransfer(ARM_Instructions.BlockDataTransfer instr) { + public BlockDataTransfer(ARM_Instructions.BlockDataTransfer instr, int instructionAddress) { i = instr; transferPC = i.transferRegister(ARM_Registers.PC); int regCount = 0; - for (int i = 0; i <= 14; i++) + for (int i = 0; i <= 14; i++) { if (this.i.transferRegister(i)) { registersToTransfer[regCount++] = i; } + } registersToTransfer[regCount] = -1; if (transferPC) regCount++; + if (DBT_Options.profileDuringInterpretation) + ps.branchInfo.registerReturnSite(instructionAddress); + if (!i.incrementBase) { if (i.postIndexing) { //post-indexing, backward reading @@ -1095,9 +1112,6 @@ nextAddress += 4; int newpc = ps.memory.load32(nextAddress); - if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), newpc); - if (i.forceUser) { //when we are transferring the PC with a forced-user transfer, then we also want to //restore the CPSR from the SPSR. @@ -1177,30 +1191,18 @@ public void execute() { - int destination; - BranchType branchType; - - if (i.offset.getType() != OperandWrapper.Type.Immediate) { - branchType = BranchType.INDIRECT_BRANCH; - } - else { - branchType = BranchType.DIRECT_BRANCH; - } - + int destination; destination = regs.readPC() + ResolvedOperand.resolve(regs, i.offset); - if (DBT_Options.profileDuringInterpretation) { - if (i.link) { - ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), destination, regs.get(ARM_Registers.PC) + i.size()); - } - else { - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), destination, branchType); - } - } - //if we're supposed to link, then write the previous address into the link register if (i.link) { - regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + i.size()); + int returnAddress = regs.get(ARM_Registers.PC) + i.size(); + + if (DBT_Options.profileDuringInterpretation) { + ps.branchInfo.registerCallSite(regs.get(ARM_Registers.PC), destination, returnAddress); + } + + regs.set(ARM_Registers.LR, returnAddress); } if (regs.getThumbMode()) @@ -1273,12 +1275,13 @@ //if we're supposed to link, then write the previous address into the link register if (i.link) { - regs.set(ARM_Registers.LR, regs.readPC() - (regs.getThumbMode() ? 2 : 4)); - ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), targetAddress, regs.get(ARM_Registers.PC) + i.size()); + int returnAddress = regs.readPC() - i.size(); + regs.set(ARM_Registers.LR, returnAddress); + + if (DBT_Options.profileDuringInterpretation) { + ps.branchInfo.registerCallSite(regs.get(ARM_Registers.PC), targetAddress, returnAddress); + } } - else { - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.DIRECT_BRANCH); - } //jump to the new address regs.set(ARM_Registers.PC, targetAddress); @@ -1372,8 +1375,8 @@ //get rid of the signs, if we're supposed to do unsigned multiplication if (i.unsigned) { - operand1 = operand1 & 0xFFFFFFFF; - operand2 = operand2 & 0xFFFFFFFF; + operand1 &= 0xFFFFFFFF; + operand2 &= 0xFFFFFFFF; } // calculate the result @@ -1634,11 +1637,6 @@ //finally, write the variable into a register regs.set(i.Rd, value); - - if (DBT_Options.profileDuringInterpretation) { - if (i.Rd == ARM_Registers.PC) - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), value, BranchType.INDIRECT_BRANCH); - } } else { //we are store a value from a register to memory. @@ -1743,6 +1741,8 @@ * the ARM_InstructionDecoder, which uses an abstract factory pattern to decode an instruction. */ private class InterpreterFactory implements ARM_InstructionFactory<ARM_Instruction> { + + private int instructionAddress; public ARM_Instruction createDataProcessing(int instr) { ARM_Instructions.DataProcessing i = new ARM_Instructions.DataProcessing(instr); @@ -1753,21 +1753,21 @@ case ADD: return new DataProcessing_Add(i); case AND: - return new DataProcessing_And(i); + return new DataProcessing_And(i, instructionAddress); case BIC: - return new DataProcessing_Bic(i); + return new DataProcessing_Bic(i, instructionAddress); case CMN: return new DataProcessing_Cmn(i); case CMP: return new DataProcessing_Cmp(i); case EOR: - return new DataProcessing_Eor(i); + return new DataProcessing_Eor(i, instructionAddress); case MOV: - return new DataProcessing_Mov(i); + return new DataProcessing_Mov(i, instructionAddress); case MVN: - return new DataProcessing_Mvn(i); + return new DataProcessing_Mvn(i, instructionAddress); case ORR: - return new DataProcessing_Orr(i); + return new DataProcessing_Orr(i, instructionAddress); case RSB: return new DataProcessing_Rsb(i); case RSC: @@ -1777,9 +1777,9 @@ case SUB: return new DataProcessing_Sub(i); case TEQ: - return new DataProcessing_Teq(i); + return new DataProcessing_Teq(i, instructionAddress); case TST: - return new DataProcessing_Tst(i); + return new DataProcessing_Tst(i, instructionAddress); case CLZ: return new DataProcessing_Clz(i); @@ -1788,8 +1788,12 @@ } } + public void setInstructionAddress(int pc) { + instructionAddress = pc; + } + public ARM_Instruction createBlockDataTransfer(int instr) { - return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr)); + return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr), instructionAddress); } public ARM_Instruction createBranch(int instr) { @@ -1854,7 +1858,7 @@ } public ARM_Instruction createBlockDataTransfer(short instr) { - return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr)); + return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr), instructionAddress); } public ARM_Instruction createBranch(short instr) { @@ -1874,21 +1878,21 @@ case ADD: return new DataProcessing_Add(i); case AND: - return new DataProcessing_And(i); + return new DataProcessing_And(i, instructionAddress); case BIC: - return new DataProcessing_Bic(i); + return new DataProcessing_Bic(i, instructionAddress); case CMN: return new DataProcessing_Cmn(i); case CMP: return new DataProcessing_Cmp(i); case EOR: - return new DataProcessing_Eor(i); + return new DataProcessing_Eor(i, instructionAddress); case MOV: - return new DataProcessing_Mov(i); + return new DataProcessing_Mov(i, instructionAddress); case MVN: - return new DataProcessing_Mvn(i); + return new DataProcessing_Mvn(i, instructionAddress); case ORR: - return new DataProcessing_Orr(i); + return new DataProcessing_Orr(i, instructionAddress); case RSB: return new DataProcessing_Rsb(i); case RSC: @@ -1898,9 +1902,9 @@ case SUB: return new DataProcessing_Sub(i); case TEQ: - return new DataProcessing_Teq(i); + return new DataProcessing_Teq(i, instructionAddress); case TST: - return new DataProcessing_Tst(i); + return new DataProcessing_Tst(i, instructionAddress); case CLZ: return new DataProcessing_Clz(i); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-07-11 16:34:25 UTC (rev 151) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-07-29 13:13:16 UTC (rev 152) @@ -1,6 +1,5 @@ package org.binarytranslator.arch.arm.decoder; public class ARM_Options { - public final static boolean FLAG_LAZINESS = false; public final static boolean DATAPROCESSING_DECODER_FASTPATH = false; } Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-11 16:34:25 UTC (rev 151) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-29 13:13:16 UTC (rev 152) @@ -3942,7 +3942,7 @@ int target_address = ps.lr; if (LK != 0) { ps.lr = ps.getCurrentInstructionAddress() + 4; - ps.branchInfo.registerCall(ps.getCurrentInstructionAddress(), ps + ps.branchInfo.registerCallSite(ps.getCurrentInstructionAddress(), ps .getCurrentInstructionAddress() + 4, target_address); } // decode BO @@ -4593,7 +4593,7 @@ int target_address = ps.ctr; if (LK != 0) { ps.lr = ps.getCurrentInstructionAddress() + 4; - ps.branchInfo.registerCall(ps.getCurrentInstructionAddress(), ps + ps.branchInfo.registerCallSite(ps.getCurrentInstructionAddress(), ps .getCurrentInstructionAddress() + 4, target_address); } // decode BO @@ -11618,7 +11618,7 @@ } if (LK != 0) { ps.lr = ps.getCurrentInstructionAddress() + 4; - ps.branchInfo.registerCall(ps.getCurrentInstructionAddress(), ps + ps.branchInfo.registerCallSite(ps.getCurrentInstructionAddress(), ps .getCurrentInstructionAddress() + 4, target_address); } // decode BO @@ -11767,7 +11767,7 @@ } if (lk != 0) { ps.lr = ps.getCurrentInstructionAddress() + 4; - ps.branchInfo.registerCall(ps.getCurrentInstructionAddress(), ps + ps.branchInfo.registerCallSite(ps.getCurrentInstructionAddress(), ps .getCurrentInstructionAddress() + 4, target_address); } ps.setCurrentInstructionAddress(target_address); Modified: src/org/binarytranslator/generic/branchprofile/BranchProfile.java =================================================================== --- src/org/binarytranslator/generic/branchprofile/BranchProfile.java 2007-07-11 16:34:25 UTC (rev 151) +++ src/org/binarytranslator/generic/branchprofile/BranchProfile.java 2007-07-29 13:13:16 UTC (rev 152) @@ -12,10 +12,12 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.util.HashSet; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; +import java.util.Map.Entry; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -49,10 +51,101 @@ private final SortedMap<Integer, ProcedureInformation> procedures; /** A set of switch like branchs sites and their destinations */ - private final SortedMap<Integer, Set<Integer>> branchSitesAndDestinations; + private final SortedMap<Integer, BranchInformation> branchSites; /** Global branch information */ private static BranchProfile global; + + /** + * Stores information on a single branch location. */ + private final static class BranchInformation { + + /** How often the branch instruction has been executed. */ + private int executionCount; + + /** The target addresses of the branch and how often they have been branched to. */ + private final Map<Integer, Integer> destinationsAndFrequencies; + + public BranchInformation() { + this.destinationsAndFrequencies = new HashMap<Integer, Integer>(); + } + + public BranchInformation(HashMap<Integer, Integer> destinationsAndFrequencies) { + this.destinationsAndFrequencies = destinationsAndFrequencies; + executionCount = 0; + + for (Entry<Integer, Integer> target : destinationsAndFrequencies.entrySet()) { + executionCount += target.getValue(); + } + } + + public void profile(int target) { + executionCount++; + Integer targetCount = destinationsAndFrequencies.get(target); + + targetCount = (targetCount == null) ? 1 : targetCount + 1; + destinationsAndFrequencies.put(target, targetCount); + } + + /** Returns a list of addresses that this branch jumps to. */ + public Set<Integer> getTargets() { + return destinationsAndFrequencies.keySet(); + } + + public Map<Integer, Integer> getTargetsAndFrequencies() { + return destinationsAndFrequencies; + } + + public void registerTargetSite(int target) { + if (destinationsAndFrequencies.get(target) == null) + destinationsAndFrequencies.put(target, 0); + } + + /** + * Loads a {@link BranchInformation} object from an XML element, given that the object + * was previously persisted by {@link #toXML(Document, Element)}. + * @param node + * The XML element that had been provided to {@link #toXML(Document, Element)}. + * @throws IOException + */ + public static BranchInformation fromXML(Element node) throws IOException { + HashMap<Integer, Integer> targetsAndFrequencies = new HashMap<Integer, Integer>(); + + for (int n = 0; n < node.getChildNodes().getLength(); n++) { + Node target = node.getChildNodes().item(n); + + if (target.getNodeType() != Node.ELEMENT_NODE) + continue; + + if (!target.getNodeName().equals("target")) + throw new IOException("File is not a valid XML branch profile."); + + int targetAddress = Integer.parseInt(((Element)target).getAttribute("address")); + int branchCount = Integer.parseInt(((Element)target).getAttribute("address")); + targetsAndFrequencies.put(targetAddress, branchCount); + } + + return new BranchInformation(targetsAndFrequencies); + } + + public void toXML(Document doc, Element parentNode) { + Element branchInfo = parentNode; + + Element targets = doc.createElement("targets"); + + for (Entry<Integer, Integer> branchTarget : destinationsAndFrequencies.entrySet()) { + int targetAddress = branchTarget.getKey(); + int branchCount = branchTarget.getValue(); + + Element branchTargetElement = doc.createElement("target"); + branchInfo.appendChild(branchTargetElement); + branchTargetElement.setAttribute("address", Integer.toString(targetAddress)); + branchTargetElement.setAttribute("branchCount", Integer.toString(branchCount)); + } + + branchInfo.appendChild(targets); + } + } /** * Constructor has 2 functions: (1) when making a local trace we don't want to @@ -62,10 +155,10 @@ public BranchProfile() { if (global == null) { global = this; - branchSitesAndDestinations = new TreeMap<Integer, Set<Integer>>(); + branchSites = new TreeMap<Integer, BranchInformation>(); } else { - branchSitesAndDestinations = global.branchSitesAndDestinations; + branchSites = global.branchSites; } procedures = new TreeMap<Integer, ProcedureInformation>(); } @@ -80,7 +173,7 @@ * @param ret * the address that will be returned to */ - public void registerCall(int pc, int dest, int ret) { + public void registerCallSite(int pc, int dest, int ret) { ProcedureInformation procedure = procedures.get(dest); if (procedure != null) { @@ -90,27 +183,66 @@ procedures.put(dest, procedure); } - registerBranch(pc, dest); + registerDynamicBranchSite(pc, dest); } + + /** + * Register a function return. + * + * @param pc + * the address of the return instruction + */ + public void registerReturnSite(int pc) { + + ProcedureInformation procedure = getLikelyProcedure(pc); + + if (procedure != null) { + procedure.registerReturn(pc); + } + } /** * Register a function return. * * @param pc - * the address of the branch instruction + * the address of the return instruction * @param lr * the return address (value of the link register) */ - public void registerReturn(int pc, int lr) { + public void registerReturnSite(int pc, int lr) { ProcedureInformation procedure = getLikelyProcedure(pc); if (procedure != null) { - procedure.registerReturn(pc, lr); + procedure.registerReturn(pc); } - registerBranch(pc, lr); + registerDynamicBranchSite(pc, lr); } + + /** + * Appends a branch from <code>origin</code> to <code>target</code> to the branch profile. + * + * @param origin + * The address that the branch is taking place from. + * @param target + * The branch target address. + */ + public void registerDynamicBranchSite(int origin, int target) { + //Perform the general branch registration, too + BranchInformation branch = branchSites.get(origin); + + if (branch != null) { + branch.registerTargetSite(target); + // This destination address is already registered + return; + } + else { + branch = new BranchInformation(); + branch.registerTargetSite(target); + branchSites.put(origin, branch); + } + } /** * Given an address within a procedure, returns the (most likely) procedure @@ -128,58 +260,19 @@ } } return null; - } - + } + /** - * Registers a branch from the address <code>origin</code> to the address <code>target</code>. - * The type of branch is determined by <code>type</code>, which is an ordinal from the - * {@link BranchType} enum. + * Records that a branch from <code>origin</code> to <code>target</code> has been observed while the program is running. * * @param origin - * The address from which the branch occurs. + * The address from which the branch took place. * @param target - * The address to which the program is branching. - * @param type - * The most likely type of the branch. This is taken from the {@link BranchType} enum. + * The address to which it took place. */ - public void registerBranch(int origin, int target, BranchType type) { - - switch (type) { - case CALL: - throw new RuntimeException("Use the more specific registerCall() for these cases."); - - case RETURN: - registerReturn(origin, target); - break; - - default: - registerBranch(origin, target); - } + public void profileBranch(int origin, int target) { + throw new RuntimeException("Not yet implemented."); } - - /** - * Appends a recorded branch from <code>origin</code> to <code>target</code> to the branch profile. - * - * @param origin - * The address that the branch is taking place from. - * @param target - * The branch target address. - */ - private void registerBranch(int origin, int target) { - //Perform the general branch registration, too - Set<Integer> dests = branchSitesAndDestinations.get(origin); - - if (dests != null && dests.contains(target)) { - // This destination address is already registered - return; - } - else { - dests = new HashSet<Integer>(); - branchSitesAndDestinations.put(origin, dests); - } - - dests.add(target); - } /** * Returns a list of known branch targets for the branch at address <code>pc</code>. @@ -191,7 +284,8 @@ * translated binary, if this list is not complete. */ public Set<Integer> getKnownBranchTargets(int pc) { - return branchSitesAndDestinations.get(pc); + BranchInformation branch = branchSites.get(pc); + return (branch == null) ? null : branch.getTargets(); } public void loadFromXML(String filename) throws IOException { @@ -234,17 +328,9 @@ if (!siteNode.getNodeName().equals("origin") || siteNode.getNodeType() != Node.ELEMENT_NODE) throw new IOException("File is not a valid XML branch profile."); - int pc = Integer.parseInt(((Element)siteNode).getAttribute("address")); - - for (int n = 0; n < siteNode.getChildNodes().getLength(); n++) { - Node target = siteNode.getChildNodes().item(n); - - if (!target.getNodeName().equals("target") || target.getNodeType() != Node.ELEMENT_NODE) - throw new IOException("File is not a valid XML branch profile."); - - int targetAddress = Integer.parseInt(((Element)target).getAttribute("address")); - registerBranch(pc, targetAddress); - } + int address = Integer.parseInt(((Element)siteNode).getAttribute("address")); + BranchInformation branchInfo = BranchInformation.fromXML((Element)siteNode); + branchSites.put(address, branchInfo); } } @@ -289,17 +375,16 @@ Element branchesElement = doc.createElement("branches"); root.appendChild(branchesElement); - - for (int pc : branchSitesAndDestinations.keySet()) { - Element branchSiteElement = doc.createElement("origin"); + + for (Entry<Integer, BranchInformation> branch : branchSites.entrySet()) { + + int address = branch.getKey(); + BranchInformation branchInfo = branch.getValue(); + + Element branchSiteElement = doc.createElement("branch"); branchesElement.appendChild(branchSiteElement); - branchSiteElement.setAttribute("address", Integer.toString(pc)); - - for (int target : getKnownBranchTargets(pc)) { - Element branchTargetElement = doc.createElement("target"); - branchSiteElement.appendChild(branchTargetElement); - branchTargetElement.setAttribute("address", Integer.toString(target)); - } + branchSiteElement.setAttribute("address", Integer.toString(address)); + branchInfo.toXML(doc, branchSiteElement); } //Output the resulting XML document Modified: src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java =================================================================== --- src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-07-11 16:34:25 UTC (rev 151) +++ src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-07-29 13:13:16 UTC (rev 152) @@ -91,13 +91,12 @@ * * @param pc * the address of the branch instruction - * @param ret - * the address that will be returned to */ - public void registerReturn(int pc, int ret) { + public void registerReturn(int pc) { if (returnSites == null) { returnSites = new HashSet<Integer>(); } + returnSites.add(new Integer(pc)); } @@ -186,11 +185,7 @@ throw new Error("The given XML node is not a valid ProcedureInformation entity."); } } - - - - - + return pi; } } Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-07-11 16:34:25 UTC (rev 151) +++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-07-29 13:13:16 UTC (rev 152) @@ -607,13 +607,15 @@ branch, (Laziness) targetLaziness.clone(), currentPC, targetPC, BranchType.CALL); unresolvedDirectBranches.add(unresolvedJump); - if (branchType == BranchType.CALL) - ps.branchInfo.registerCall(currentPC, targetPC, retAddr); - else - if (branchType == BranchType.RETURN) - ps.branchInfo.registerReturn(currentPC, targetPC); - else - ps.branchInfo.registerBranch(currentPC, targetPC, branchType); + switch (branchType) { + case CALL: + ps.branchInfo.registerCallSite(currentPC, targetPC, retAddr); + break; + + case RETURN: + ps.branchInfo.registerReturnSite(currentPC, targetPC); + break; + } } /** @@ -929,7 +931,7 @@ * the destination of the branch instruction */ public void registerBranchAndLink(int pc, int ret, int dest) { - ps.branchInfo.registerCall(pc, ret, dest); + ps.branchInfo.registerCallSite(pc, ret, dest); } /** Added: src/org/binarytranslator/generic/decoder/Disassembler.java =================================================================== --- src/org/binarytranslator/generic/decoder/Disassembler.java (rev 0) +++ src/org/binarytranslator/generic/decoder/Disassembler.java 2007-07-29 13:13:16 UTC (rev 152) @@ -0,0 +1,46 @@ +package org.binarytranslator.generic.decoder; + +public interface Disassembler { + /** + * Represents an instruction, after it has been decoded by a disassembler. + * The instruction should be printable in the format of the target system's assembly language. + * + * @author Michael Baer + */ + public interface Instruction { + /** + * Shall return the address of the instruction following this one in <i>code order</i>, given that + * the current instruction has been decoded from address <code>pc</code>. + * @param pc + * The address from which this instruction has been decoded. + * @return + * The address of the instruction following this one in code order. + */ + int getSuccessor(int pc); + + /** + * Shall return a string representation of the disassembled instruction. + * We might have used toString() here, but I wanted it to be obvious if a dedicated implementation + * of this method is missing. + * + * @return + * A string representation of the disassembled instruction. + * For example: + * <code> + * ADD r0, r1, #15 + * </code> + * for an ARM ADD instruction. + */ + String asString(); + } + + /** + * Disassemble the instruction at address <code>pc</code> and return an appropriate object representation. + * + * @param pc + * The address at which the instruction resides. + * @return + * An object representation of the said instruction. + */ + Instruction disassemble(int pc); +} Modified: src/org/binarytranslator/generic/decoder/Interpreter.java =================================================================== --- src/org/binarytranslator/generic/decoder/Interpreter.java 2007-07-11 16:34:25 UTC (rev 151) +++ src/org/binarytranslator/generic/decoder/Interpreter.java 2007-07-29 13:13:16 UTC (rev 152) @@ -1,5 +1,9 @@ package org.binarytranslator.generic.decoder; +/** + * TODO: Add comments for this interface. + * + */ public interface Interpreter { public interface Instruction { Modified: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-07-11 16:34:25 UTC (rev 151) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-07-29 13:13:16 UTC (rev 152) @@ -1,5 +1,6 @@ package org.binarytranslator.generic.execution; +import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -22,12 +23,19 @@ instruction.execute(); //System.out.println(ps.toString()); - pc = instruction.getSuccessor(pc); + int nextInstruction = instruction.getSuccessor(pc); - if (pc == -1) - pc = ps.getCurrentInstructionAddress(); - else - ps.setCurrentInstructionAddress(pc); + if (nextInstruction == -1) { + nextInstruction = ps.getCurrentInstructionAddress(); + + if (DBT_Options.profileDuringInterpretation) + ps.branchInfo.profileBranch(pc, ps.getCurrentInstructionAddress()); + } + else { + ps.setCurrentInstructionAddress(nextInstruction); + } + + pc = nextInstruction; } } } Modified: src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java =================================================================== --- src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-07-11 16:34:25 UTC (rev 151) +++ src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-07-29 13:13:16 UTC (rev 152) @@ -8,7 +8,7 @@ import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.os.process.ProcessSpace; -public final class PredecodingThreadedInterpreter extends ExecutionController { +public class PredecodingThreadedInterpreter extends ExecutionController { private final HashMap<Integer, List<Interpreter.Instruction>> traceCache = new HashMap<Integer, List<Interpreter.Instruction>>(); private final Interpreter interpreter; @@ -42,16 +42,19 @@ return newTrace; } - private void executeTrace(List<Interpreter.Instruction> trace, int pc) { + protected void executeTrace(List<Interpreter.Instruction> trace, int pc) { Iterator<Interpreter.Instruction> instructions = trace.iterator(); - while (instructions.hasNext()) { + while (true) { Interpreter.Instruction instr = instructions.next(); instr.execute(); - pc = instr.getSuccessor(pc); - if (pc != -1) + if (instructions.hasNext()) { + pc = instr.getSuccessor(pc); ps.setCurrentInstructionAddress(pc); + } + else + break; } } @@ -61,7 +64,7 @@ } @Override - public void run() { + public final void run() { int pc = ps.getCurrentInstructionAddress(); while (!ps.finished) { Added: src/org/binarytranslator/generic/execution/ProfilingPredecodingInterpreter.java =================================================================== --- src/org/binarytranslator/generic/execution/ProfilingPredecodingInterpreter.java (rev 0) +++ src/org/binarytranslator/generic/execution/ProfilingPredecodingInterpreter.java 2007-07-29 13:13:16 UTC (rev 152) @@ -0,0 +1,40 @@ +package org.binarytranslator.generic.execution; + +import java.util.Iterator; +import java.util.List; +import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.decoder.Interpreter.Instruction; +import org.binarytranslator.generic.os.process.ProcessSpace; + +/** + * Adds runtime profiling capabilities to {@link PredecodingThreadedInterpreter}. + */ +public class ProfilingPredecodingInterpreter extends PredecodingThreadedInterpreter { + + public ProfilingPredecodingInterpreter(ProcessSpace ps) { + super(ps); + } + + @Override + protected void executeTrace(List<Instruction> trace, int pc) { + Iterator<Interpreter.Instruction> instructions = trace.iterator(); + while (true) { + Interpreter.Instruction instr = instructions.next(); + + if (instructions.hasNext()) { + instr.execute(); + pc = instr.getSuccessor(pc); + ps.setCurrentInstructionAddress(pc); + + } + else { + int instructionAdddress = ps.getCurrentInstructionAddress(); + instr.execute(); + pc = ps.getCurrentInstructionAddress(); + ps.branchInfo.profileBranch(instructionAdddress, pc); + break; + } + } + } + +} Modified: src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java 2007-07-11 16:34:25 UTC (rev 151) +++ src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java 2007-07-29 13:13:16 UTC (rev 152) @@ -35,7 +35,7 @@ private int nextMemoryBlock = 1024*1024*1024; //start mapping libraries at 1GB (0x40000000) /** Maps a library name to a filename. */ - protected final HashMap<String, String> libNames = new HashMap<String, String>();; + protected final HashMap<String, String> libNames = new HashMap<String, String>(); public static class SharedObject { /** The libary's name. */ Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-07-11 16:34:25 UTC (rev 151) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-07-29 13:13:16 UTC (rev 152) @@ -155,15 +155,15 @@ switch (type) { case CALL: - branchInfo.registerCall(location, destination, returnAddress); + branchInfo.registerCallSite(location, destination, returnAddress); return; case RETURN: - branchInfo.registerReturn(location, destination); + branchInfo.registerReturnSite(location, destination); return; default: - branchInfo.registerBranch(location, destination, BranchType.values()[code]); + branchInfo.registerDynamicBranchSite(location, destination); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |