|
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.
|