From: <mic...@us...> - 2007-08-15 16:24:04
|
Revision: 167 http://pearcolator.svn.sourceforge.net/pearcolator/?rev=167&view=rev Author: michael_baer Date: 2007-08-15 09:24:05 -0700 (Wed, 15 Aug 2007) Log Message: ----------- - Controlling ARM memory model using a command line paremter - added new option to disable pearcolator inlining Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Options.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-08-15 11:08:41 UTC (rev 166) +++ src/org/binarytranslator/DBT_Options.java 2007-08-15 16:24:05 UTC (rev 167) @@ -175,25 +175,12 @@ } else if (key.startsWith("arm:")) { key = key.substring(4); - parseArmOption(key, value); + ARM_Options.parseOption(key, value); } else { throw new Error("Unknown argument."); } } - - private static void parseArmOption(String key, String value) { - if (key.equalsIgnoreCase("optimizeByProfiling")) { - ARM_Options.optimizeTranslationByProfiling = Boolean.parseBoolean(value); - } else if (key.equalsIgnoreCase("flagEvaluation")) { - ARM_Options.flagEvaluation = ARM_Options.FlagBehaviour.valueOf(value); - } else if (key.equalsIgnoreCase("inline")) { - ARM_Options.inlining = ARM_Options.InliningBehaviour.valueOf(value); - } - else { - throw new Error("Unknown ARM option: " + key); - } - } private static void parseDbtOption(String key, String value) { if (key.equalsIgnoreCase("debugInstr")) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-15 11:08:41 UTC (rev 166) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-15 16:24:05 UTC (rev 167) @@ -468,6 +468,9 @@ switch (ARM_Options.inlining) { + case NoInlining: + return false; + case Default: return super.inlineBranchInstruction(targetPc, jump); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-15 11:08:41 UTC (rev 166) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-15 16:24:05 UTC (rev 167) @@ -8,6 +8,7 @@ } public enum InliningBehaviour { + NoInlining, Default, Functions, FunctionCalls, @@ -16,6 +17,11 @@ All, } + public enum MemoryModel { + IntAddressed, + ByteAddressed + } + /** Set to true to enable a fastpath for the decoding of data processing instructions.. */ public final static boolean DATAPROCESSING_DECODER_FASTPATH = false; @@ -27,4 +33,23 @@ /** Describes the default behaviour for dealing with ARM function calls and indirect jumps. */ public static InliningBehaviour inlining = InliningBehaviour.Default; + + /** Sets the memory model that ARM shall use. */ + public static MemoryModel memoryModel = MemoryModel.IntAddressed; + + + public static void parseOption(String key, String value) { + if (key.equalsIgnoreCase("optimizeByProfiling")) { + optimizeTranslationByProfiling = Boolean.parseBoolean(value); + } else if (key.equalsIgnoreCase("flagEvaluation")) { + flagEvaluation = ARM_Options.FlagBehaviour.valueOf(value); + } else if (key.equalsIgnoreCase("inline")) { + inlining = ARM_Options.InliningBehaviour.valueOf(value); + } else if (key.equalsIgnoreCase("memory")) { + memoryModel = ARM_Options.MemoryModel.valueOf(value); + } + else { + throw new Error("Unknown ARM option: " + key); + } + } } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-15 11:08:41 UTC (rev 166) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-15 16:24:05 UTC (rev 167) @@ -5,10 +5,12 @@ import org.binarytranslator.arch.arm.decoder.ARM2IR; import org.binarytranslator.arch.arm.decoder.ARM_Disassembler; import org.binarytranslator.arch.arm.decoder.ARM_Interpreter; +import org.binarytranslator.arch.arm.decoder.ARM_Options; import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.memory.ByteAddressedMemory; import org.binarytranslator.generic.memory.IntAddressedMemory; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -38,7 +40,20 @@ protected ARM_ProcessSpace() { registers = new ARM_Registers(); - memory = new IntAddressedMemory(); + + switch (ARM_Options.memoryModel) { + case ByteAddressed: + memory = new ByteAddressedMemory(); + break; + + case IntAddressed: + memory = new IntAddressedMemory(); + break; + + default: + throw new RuntimeException("Unexpected ARM memory model setting: " + ARM_Options.memoryModel); + } + } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-03-19 16:02:01
|
Revision: 5 http://svn.sourceforge.net/pearcolator/?rev=5&view=rev Author: captain5050 Date: 2007-03-19 09:01:57 -0700 (Mon, 19 Mar 2007) Log Message: ----------- Build fixes and small tidy ups Modified Paths: -------------- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/decoder/X86_FlagLaziness.java src/org/binarytranslator/generic/branch/ProcedureInformation.java src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/IntAddressedMemory.java src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/vmInterface/DBT_Trace.java Removed Paths: ------------- src/org/binarytranslator/generic/branch/ProcedureInformationComparator.java Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-03-18 22:49:42 UTC (rev 4) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-03-19 16:01:57 UTC (rev 5) @@ -81,41 +81,122 @@ */ public final class PPC2IR extends DecoderUtils implements OPT_HIRGenerator, OPT_Operators, OPT_Constants { - /** - * Construct the PPC2IR object for the generation context; then - * we'll be ready to start generating the HIR. - */ - public PPC2IR(OPT_GenerationContext context) { - super(context); - // Create register maps PPC -> OPT_Register - intRegMap = new OPT_Register[32]; - intRegInUseMap = new boolean[32]; - fpRegMap = new OPT_Register[32]; - fpRegInUseMap = new boolean[32]; - crFieldMap_Lt = new OPT_Register[8]; - crFieldMap_Gt = new OPT_Register[8]; - crFieldMap_Eq = new OPT_Register[8]; - crFieldMap_SO = new OPT_Register[8]; - crFieldInUseMap = new boolean[8]; + // -oO Caches of references to process space entities Oo- - // Debug - if(DBT_Options.debugCFG) { - report("CFG at end of constructor:\n" + gc.cfg); - } - } + /** Type reference to the PPC process space */ + private static final VM_TypeReference psTref; - /** - * Translate the instruction at the given pc - * @param lazy the status of the lazy evaluation - * @param pc the program counter for the instruction - * @return the next instruction address or -1 - */ - protected int translateInstruction(Laziness lazy, int pc) { - return PPC_InstructionDecoder.translateInstruction(this, (PPC_ProcessSpace)ps, (PPC_Laziness)lazy, pc); - } + /** References to PPC process space GPR register fields */ + private static final VM_FieldReference[] gprFieldRefs; - // -oO Creations for being a PPC translator Oo- + /** References to PPC process space FPR register fields */ + private static final VM_FieldReference[] fprFieldRefs; + /** Reference to PPC process space condition register lt array field */ + private static final VM_FieldReference crf_ltFieldRef; + + /** Reference to PPC process space condition register gt array field */ + private static final VM_FieldReference crf_gtFieldRef; + + /** Reference to PPC process space condition register eq array field */ + private static final VM_FieldReference crf_eqFieldRef; + + /** Reference to PPC process space condition register so array field */ + private static final VM_FieldReference crf_soFieldRef; + + /** Reference to PPC process space xer_so field */ + private static final VM_FieldReference xer_soFieldRef; + /** Reference to PPC process space xer_ov field */ + private static final VM_FieldReference xer_ovFieldRef; + /** Reference to PPC process space xer_ca field */ + private static final VM_FieldReference xer_caFieldRef; + /** Reference to PPC process space xer_byteCount field */ + private static final VM_FieldReference xer_byteCountFieldRef; + + /** Reference to PPC process space fpscr field */ + private static final VM_FieldReference fpscrFieldRef; + + /** Reference to PPC process space ctr field */ + private static final VM_FieldReference ctrFieldRef; + + /** Reference to PPC process space lr fild */ + private static final VM_FieldReference lrFieldRef; + + /** Reference to PPC process space pc field */ + private static final VM_FieldReference pcFieldRef; + + /** Reference to PPC process space recordUncaughtBclr method */ + private static final VM_MethodReference recordUncaughtBclrMethRef; + + /** Reference to PPC process space recordUncaughtBcctr method */ + private static final VM_MethodReference recordUncaughtBcctrMethRef; + + /* Static initializer */ + static { + psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), + VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") + ); + gprFieldRefs = new VM_FieldReference[32]; + fprFieldRefs = new VM_FieldReference[32]; + final VM_Atom intAtom = VM_Atom.findOrCreateAsciiAtom("I"); + final VM_Atom doubleAtom = VM_Atom.findOrCreateAsciiAtom("D"); + for (int i=0; i < 32; i++){ + gprFieldRefs[i] = VM_MemberReference.findOrCreate(psTref, + VM_Atom.findOrCreateAsciiAtom("r"+i), + intAtom + ).asFieldReference(); + fprFieldRefs[i] = VM_MemberReference.findOrCreate(psTref, + VM_Atom.findOrCreateAsciiAtom("f"+i), + doubleAtom + ).asFieldReference(); + } + final VM_Atom boolArrayAtom = VM_Atom.findOrCreateAsciiAtom("[Z"); + crf_ltFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_lt"), + boolArrayAtom + ).asFieldReference(); + crf_gtFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_gt"), + boolArrayAtom + ).asFieldReference(); + crf_eqFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_eq"), + boolArrayAtom + ).asFieldReference(); + crf_soFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_so"), + boolArrayAtom + ).asFieldReference(); + final VM_Atom boolAtom = VM_Atom.findOrCreateAsciiAtom("Z"); + xer_soFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("xer_so"), + boolAtom + ).asFieldReference(); + xer_ovFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("xer_ov"), + boolAtom + ).asFieldReference(); + xer_caFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("xer_ca"), + boolAtom + ).asFieldReference(); + final VM_Atom byteAtom = VM_Atom.findOrCreateAsciiAtom("B"); + xer_byteCountFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("xer_byteCount"), + byteAtom + ).asFieldReference(); + fpscrFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("fpscr"), + intAtom + ).asFieldReference(); + ctrFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("ctr"), + intAtom + ).asFieldReference(); + lrFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("lr"), + intAtom + ).asFieldReference(); + pcFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("pc"), + intAtom + ).asFieldReference(); + recordUncaughtBclrMethRef = (VM_MethodReference)VM_MemberReference.findOrCreate(psTref, + VM_Atom.findOrCreateAsciiAtom("recordUncaughtBclr"), + VM_Atom.findOrCreateAsciiAtom("(II)V")); + recordUncaughtBcctrMethRef = (VM_MethodReference)VM_MemberReference.findOrCreate(psTref, + VM_Atom.findOrCreateAsciiAtom("recordUncaughtBcctr"), + VM_Atom.findOrCreateAsciiAtom("(II)V")); + } + // -oO PPC register to HIR register mappings Oo- /** @@ -124,20 +205,20 @@ * block. This avoids potential inconsistencies caused by using lazy * allocation and backward branches. */ - private OPT_Register intRegMap[]; + private final OPT_Register intRegMap[]; /** * Which PPC general purpose registers are in use */ - private boolean intRegInUseMap[]; + private final boolean intRegInUseMap[]; /** * The mapping of PPC floating point registers to HIR registers. */ - private OPT_Register fpRegMap[]; + private final OPT_Register fpRegMap[]; /** * Which PPC floating point registers are in use */ - private boolean fpRegInUseMap[]; + private final boolean fpRegInUseMap[]; /** * The HIR register holding the PPC FPSCR register. @@ -167,12 +248,6 @@ private boolean lrRegInUse; /** - * The HIR register holding the PPC XER register when it is combined - * in a fillAll or spillAll block - */ - private OPT_Register xerRegMap; - - /** * The HIR register holding the PPC XER register's byte count (bits * 25 to 31) */ @@ -203,34 +278,67 @@ * value of the corresponding condition register field's SO * bit. */ - private OPT_Register crFieldMap_Lt[]; + private final OPT_Register crFieldMap_Lt[]; /** * These 8 registers hold a zero or non-zero value depending on the * value of the corresponding condition register field's SO * bit. */ - private OPT_Register crFieldMap_Gt[]; + private final OPT_Register crFieldMap_Gt[]; /** * These 8 registers hold a zero or non-zero value depending on the * value of the corresponding condition register field's SO * bit. */ - private OPT_Register crFieldMap_Eq[]; + private final OPT_Register crFieldMap_Eq[]; /** * These 8 registers hold a zero or non-zero value depending on the * value of the corresponding condition register field's SO * bit. */ - private OPT_Register crFieldMap_SO[]; + private final OPT_Register crFieldMap_SO[]; /** * What condition register fields are in use? */ - private boolean crFieldInUseMap[]; + private final boolean crFieldInUseMap[]; + /** + * Construct the PPC2IR object for the generation context; then + * we'll be ready to start generating the HIR. + */ + public PPC2IR(OPT_GenerationContext context) { + super(context); + // Create register maps PPC -> OPT_Register + intRegMap = new OPT_Register[32]; + intRegInUseMap = new boolean[32]; + fpRegMap = new OPT_Register[32]; + fpRegInUseMap = new boolean[32]; + crFieldMap_Lt = new OPT_Register[8]; + crFieldMap_Gt = new OPT_Register[8]; + crFieldMap_Eq = new OPT_Register[8]; + crFieldMap_SO = new OPT_Register[8]; + crFieldInUseMap = new boolean[8]; + + // Debug + if(DBT_Options.debugCFG) { + report("CFG at end of constructor:\n" + gc.cfg); + } + } + + /** + * Translate the instruction at the given pc + * @param lazy the status of the lazy evaluation + * @param pc the program counter for the instruction + * @return the next instruction address or -1 + */ + protected int translateInstruction(Laziness lazy, int pc) { + return PPC_InstructionDecoder.translateInstruction(this, (PPC_ProcessSpace)ps, (PPC_Laziness)lazy, pc); + } + // -oO Fill/spill registers between OPT_Registers and the PPC_ProcessSpace Oo- /** @@ -249,17 +357,10 @@ else { result = new OPT_RegisterOperand(intRegMap[r], VM_TypeReference.Int); } - - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("r"+r), - VM_Atom.findOrCreateAsciiAtom("I") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, result, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(gprFieldRefs[r].peekResolvedField().getOffset()), + new OPT_LocationOperand(gprFieldRefs[r]), new OPT_TrueGuardOperand()) ); } @@ -276,16 +377,10 @@ OPT_RegisterOperand regOp = new OPT_RegisterOperand(intRegMap[r], VM_TypeReference.Int); - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("r"+r), - VM_Atom.findOrCreateAsciiAtom("I") - ).asFieldReference(); appendInstructionToCurrentBlock(PutField.create(PUTFIELD, regOp, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(gprFieldRefs[r].peekResolvedField().getOffset()), + new OPT_LocationOperand(gprFieldRefs[r]), new OPT_TrueGuardOperand()) ); } @@ -308,16 +403,10 @@ result = new OPT_RegisterOperand(fpRegMap[r], VM_TypeReference.Double); } - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("f"+r), - VM_Atom.findOrCreateAsciiAtom("D") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, result, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(fprFieldRefs[r].peekResolvedField().getOffset()), + new OPT_LocationOperand(fprFieldRefs[r]), new OPT_TrueGuardOperand()) ); } @@ -334,16 +423,10 @@ OPT_RegisterOperand regOp = new OPT_RegisterOperand(fpRegMap[r], VM_TypeReference.Double); - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("f"+r), - VM_Atom.findOrCreateAsciiAtom("D") - ).asFieldReference(); appendInstructionToCurrentBlock(PutField.create(PUTFIELD, regOp, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(fprFieldRefs[r].peekResolvedField().getOffset()), + new OPT_LocationOperand(fprFieldRefs[r]), new OPT_TrueGuardOperand()) ); } @@ -368,55 +451,40 @@ OPT_RegisterOperand arrayref = gc.temps.makeTemp(VM_TypeReference.BooleanArray); - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_lt"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(crf_ltFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(crf_ltFieldRef), new OPT_TrueGuardOperand()) ); appendInstructionToCurrentBlock(ALoad.create(UBYTE_ALOAD, lt, arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_gt"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(crf_gtFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(crf_gtFieldRef), new OPT_TrueGuardOperand()) ); appendInstructionToCurrentBlock(ALoad.create(UBYTE_ALOAD, gt, arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_eq"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(crf_eqFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(crf_eqFieldRef), new OPT_TrueGuardOperand()) ); appendInstructionToCurrentBlock(ALoad.create(UBYTE_ALOAD, eq, arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_so"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(crf_soFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(crf_soFieldRef), new OPT_TrueGuardOperand()) ); appendInstructionToCurrentBlock(ALoad.create(UBYTE_ALOAD, so, @@ -439,55 +507,40 @@ OPT_RegisterOperand arrayref = gc.temps.makeTemp(VM_TypeReference.BooleanArray); - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_lt"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(crf_ltFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(crf_ltFieldRef), new OPT_TrueGuardOperand()) ); appendInstructionToCurrentBlock(AStore.create(BYTE_ASTORE, lt, arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_gt"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(crf_gtFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(crf_gtFieldRef), new OPT_TrueGuardOperand()) ); appendInstructionToCurrentBlock(AStore.create(BYTE_ASTORE, gt, arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_eq"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(crf_eqFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(crf_eqFieldRef), new OPT_TrueGuardOperand()) ); appendInstructionToCurrentBlock(AStore.create(BYTE_ASTORE, eq, arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_so"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(crf_soFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(crf_soFieldRef), new OPT_TrueGuardOperand()) ); appendInstructionToCurrentBlock(AStore.create(BYTE_ASTORE, so, @@ -510,20 +563,12 @@ else { result = new OPT_RegisterOperand(fpscrRegMap, VM_TypeReference.Int); } - - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("fpscr"), - VM_Atom.findOrCreateAsciiAtom("I") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, result, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(fpscrFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(fpscrFieldRef), new OPT_TrueGuardOperand()) ); - } /** @@ -533,16 +578,10 @@ { OPT_RegisterOperand regOp = new OPT_RegisterOperand(fpscrRegMap, VM_TypeReference.Int); - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("fpscr"), - VM_Atom.findOrCreateAsciiAtom("I") - ).asFieldReference(); appendInstructionToCurrentBlock(PutField.create(PUTFIELD, regOp, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(fpscrFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(fpscrFieldRef), new OPT_TrueGuardOperand()) ); } @@ -561,16 +600,10 @@ else { result = new OPT_RegisterOperand(ctrRegMap, VM_TypeReference.Int); } - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("ctr"), - VM_Atom.findOrCreateAsciiAtom("I") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, result, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(ctrFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(ctrFieldRef), new OPT_TrueGuardOperand()) ); } @@ -583,16 +616,10 @@ { OPT_RegisterOperand regOp = new OPT_RegisterOperand(ctrRegMap, VM_TypeReference.Int); - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("ctr"), - VM_Atom.findOrCreateAsciiAtom("I") - ).asFieldReference(); appendInstructionToCurrentBlock(PutField.create(PUTFIELD, regOp, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(ctrFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(ctrFieldRef), new OPT_TrueGuardOperand()) ); } @@ -604,69 +631,52 @@ */ private void fillXERRegister() { - OPT_RegisterOperand xerRegMap_Op; OPT_RegisterOperand xerRegMap_SO_Op; OPT_RegisterOperand xerRegMap_OV_Op; OPT_RegisterOperand xerRegMap_ByteCountOp; OPT_RegisterOperand xerRegMap_CA_Op; if (xerRegMap_SO == null) { - xerRegMap_Op = gc.temps.makeTempInt(); - xerRegMap_SO_Op = gc.temps.makeTempInt(); - xerRegMap_OV_Op = gc.temps.makeTempInt(); - xerRegMap_ByteCountOp = gc.temps.makeTempInt(); + xerRegMap_SO_Op = gc.temps.makeTempBoolean(); + xerRegMap_OV_Op = gc.temps.makeTempBoolean(); xerRegMap_CA_Op = gc.temps.makeTempBoolean(); + xerRegMap_ByteCountOp = gc.temps.makeTemp(VM_TypeReference.Byte); - xerRegMap = xerRegMap_Op.register; xerRegMap_SO = xerRegMap_SO_Op.register; xerRegMap_OV = xerRegMap_OV_Op.register; - xerRegMap_ByteCount = xerRegMap_ByteCountOp.register; xerRegMap_CA = xerRegMap_CA_Op.register; + xerRegMap_ByteCount = xerRegMap_ByteCountOp.register; } else { - xerRegMap_Op = new OPT_RegisterOperand(xerRegMap, VM_TypeReference.Int); - xerRegMap_SO_Op = new OPT_RegisterOperand(xerRegMap_SO, VM_TypeReference.Int); - xerRegMap_OV_Op = new OPT_RegisterOperand(xerRegMap_OV, VM_TypeReference.Int); - xerRegMap_ByteCountOp = new OPT_RegisterOperand(xerRegMap_ByteCount, VM_TypeReference.Int); + xerRegMap_SO_Op = new OPT_RegisterOperand(xerRegMap_SO, VM_TypeReference.Boolean); + xerRegMap_OV_Op = new OPT_RegisterOperand(xerRegMap_OV, VM_TypeReference.Boolean); xerRegMap_CA_Op = new OPT_RegisterOperand(xerRegMap_CA, VM_TypeReference.Boolean); + xerRegMap_ByteCountOp = new OPT_RegisterOperand(xerRegMap_ByteCount, VM_TypeReference.Byte); } - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("xer"), - VM_Atom.findOrCreateAsciiAtom("I") - ).asFieldReference(); - appendInstructionToCurrentBlock(GetField.create(GETFIELD, xerRegMap_Op, + appendInstructionToCurrentBlock(GetField.create(GETFIELD, xerRegMap_SO_Op, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(xer_soFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(xer_soFieldRef), new OPT_TrueGuardOperand()) ); - // Copy SO bit into XER[SO] register - appendInstructionToCurrentBlock(Binary.create(INT_AND, xerRegMap_SO_Op, - xerRegMap_Op.copyRO(), - new OPT_IntConstantOperand(1 << 31))); - - // Copy OV bit into XER[OV] register - appendInstructionToCurrentBlock(Binary.create(INT_AND, xerRegMap_OV_Op, - xerRegMap_Op.copyRO(), - new OPT_IntConstantOperand(1 << 30))); - - // Copy CA bit into XER[CA] register - OPT_RegisterOperand tempInt = getTempInt(0); - appendInstructionToCurrentBlock(Binary.create(INT_AND, tempInt, - xerRegMap_Op.copyRO(), - new OPT_IntConstantOperand(1 << 29))); - appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, xerRegMap_CA_Op, - tempInt.copyRO(), - new OPT_IntConstantOperand(0), - OPT_ConditionOperand.NOT_EQUAL(), - OPT_BranchProfileOperand.unlikely())); - - // Copy byte count bits out - appendInstructionToCurrentBlock(Binary.create(INT_AND, xerRegMap_ByteCountOp, - xerRegMap_Op.copyRO(), - new OPT_IntConstantOperand(0x3f))); + appendInstructionToCurrentBlock(GetField.create(GETFIELD, xerRegMap_OV_Op, + gc.makeLocal(1,psTref), + new OPT_AddressConstantOperand(xer_ovFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(xer_ovFieldRef), + new OPT_TrueGuardOperand()) + ); + appendInstructionToCurrentBlock(GetField.create(GETFIELD, xerRegMap_CA_Op, + gc.makeLocal(1,psTref), + new OPT_AddressConstantOperand(xer_caFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(xer_caFieldRef), + new OPT_TrueGuardOperand()) + ); + appendInstructionToCurrentBlock(GetField.create(GETFIELD, xerRegMap_ByteCountOp, + gc.makeLocal(1,psTref), + new OPT_AddressConstantOperand(xer_byteCountFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(xer_byteCountFieldRef), + new OPT_TrueGuardOperand()) + ); } /** @@ -675,60 +685,36 @@ */ private void spillXERRegister() { - // Set up xer register with byte count - OPT_RegisterOperand xer = new OPT_RegisterOperand(xerRegMap, VM_TypeReference.Int); - appendInstructionToCurrentBlock(Move.create(INT_MOVE, xer, - new OPT_RegisterOperand(xerRegMap_ByteCount, VM_TypeReference.Int)) + OPT_RegisterOperand xerRegMap_SO_Op = new OPT_RegisterOperand(xerRegMap_SO, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(PutField.create(PUTFIELD, xerRegMap_SO_Op, + gc.makeLocal(1,psTref), + new OPT_AddressConstantOperand(xer_soFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(xer_soFieldRef), + new OPT_TrueGuardOperand()) ); - // SO bit - OPT_RegisterOperand tempInt = getTempInt(0); - appendInstructionToCurrentBlock(CondMove.create(INT_COND_MOVE, - tempInt, - new OPT_RegisterOperand(xerRegMap_SO, VM_TypeReference.Int), - new OPT_IntConstantOperand(0), - OPT_ConditionOperand.EQUAL(), - new OPT_IntConstantOperand(0), - new OPT_IntConstantOperand(1 << 31))); - appendInstructionToCurrentBlock(Binary.create(INT_OR, xer.copyRO(), - xer.copy(), - tempInt.copyRO()) + + + OPT_RegisterOperand xerRegMap_OV_Op = new OPT_RegisterOperand(xerRegMap_OV, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(PutField.create(PUTFIELD, xerRegMap_OV_Op, + gc.makeLocal(1,psTref), + new OPT_AddressConstantOperand(xer_ovFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(xer_ovFieldRef), + new OPT_TrueGuardOperand()) ); - // OV bit - appendInstructionToCurrentBlock(CondMove.create(INT_COND_MOVE, - tempInt.copyRO(), - new OPT_RegisterOperand(xerRegMap_OV, VM_TypeReference.Int), - new OPT_IntConstantOperand(0), - OPT_ConditionOperand.EQUAL(), - new OPT_IntConstantOperand(0), - new OPT_IntConstantOperand(1 << 30))); - appendInstructionToCurrentBlock(Binary.create(INT_OR, xer.copyRO(), - xer.copy(), - tempInt.copyRO()) + + OPT_RegisterOperand xerRegMap_CA_Op = new OPT_RegisterOperand(xerRegMap_CA, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(PutField.create(PUTFIELD, xerRegMap_CA_Op, + gc.makeLocal(1,psTref), + new OPT_AddressConstantOperand(xer_caFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(xer_caFieldRef), + new OPT_TrueGuardOperand()) ); - - // CA bit - appendInstructionToCurrentBlock(CondMove.create(INT_COND_MOVE, - tempInt.copyRO(), - new OPT_RegisterOperand(xerRegMap_CA, VM_TypeReference.Boolean), - new OPT_IntConstantOperand(0), - OPT_ConditionOperand.EQUAL(), - new OPT_IntConstantOperand(0), - new OPT_IntConstantOperand(1 << 29))); - appendInstructionToCurrentBlock(Binary.create(INT_OR, xer.copyRO(), - xer.copy(), - tempInt.copyRO())); - - // Store to process space - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("xer"), - VM_Atom.findOrCreateAsciiAtom("I") - ).asFieldReference(); - appendInstructionToCurrentBlock(PutField.create(PUTFIELD, xer.copy(), + + OPT_RegisterOperand xerRegMap_ByteCountOp = new OPT_RegisterOperand(xerRegMap_ByteCount, VM_TypeReference.Byte); + appendInstructionToCurrentBlock(PutField.create(PUTFIELD, xerRegMap_ByteCountOp, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(xer_byteCountFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(xer_byteCountFieldRef), new OPT_TrueGuardOperand()) ); } @@ -748,16 +734,10 @@ else { result = new OPT_RegisterOperand(lrRegMap, VM_TypeReference.Int); } - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("lr"), - VM_Atom.findOrCreateAsciiAtom("I") - ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, result, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(lrFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(lrFieldRef), new OPT_TrueGuardOperand()) ); } @@ -769,17 +749,10 @@ private void spillLRRegister() { OPT_RegisterOperand regOp = new OPT_RegisterOperand(lrRegMap, VM_TypeReference.Int); - - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("lr"), - VM_Atom.findOrCreateAsciiAtom("I") - ).asFieldReference(); appendInstructionToCurrentBlock(PutField.create(PUTFIELD, regOp, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(lrFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(lrFieldRef), new OPT_TrueGuardOperand()) ); } @@ -835,16 +808,10 @@ * Spill a given PC value into the process space */ private void spillPC(int pc) { - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("pc"), - VM_Atom.findOrCreateAsciiAtom("I") - ).asFieldReference(); appendInstructionToCurrentBlock(PutField.create(PUTFIELD, new OPT_IntConstantOperand(pc), gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(pcFieldRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(pcFieldRef), new OPT_TrueGuardOperand())); } // -oO Find a register Oo- @@ -925,6 +892,7 @@ default: DBT_OptimizingCompilerException.UNREACHABLE(); } + return null; // stop compiler warnings } /** @@ -960,7 +928,7 @@ */ public OPT_RegisterOperand getXER_ByteCountRegister() { xerRegInUse = true; - return new OPT_RegisterOperand (xerRegMap_ByteCount, VM_TypeReference.Int); + return new OPT_RegisterOperand (xerRegMap_ByteCount, VM_TypeReference.Byte); } /** @@ -969,7 +937,7 @@ */ public OPT_RegisterOperand getXER_SO_Register() { xerRegInUse = true; - return new OPT_RegisterOperand (xerRegMap_SO, VM_TypeReference.Int); + return new OPT_RegisterOperand (xerRegMap_SO, VM_TypeReference.Boolean); } /** @@ -978,7 +946,7 @@ */ public OPT_RegisterOperand getXER_OV_Register() { xerRegInUse = true; - return new OPT_RegisterOperand (xerRegMap_OV, VM_TypeReference.Int); + return new OPT_RegisterOperand (xerRegMap_OV, VM_TypeReference.Boolean); } /** @@ -1062,14 +1030,8 @@ if((gc.options.getOptLevel() > 0) && (DBT_Options.plantUncaughtBclrWatcher)) { // Plant call OPT_Instruction s = Call.create(CALL, null, null, null, null, 3); - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom - ("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;")); - VM_MethodReference methRef = (VM_MethodReference)VM_MemberReference.findOrCreate(psTref, - VM_Atom.findOrCreateAsciiAtom("recordUncaughtBclr"), - VM_Atom.findOrCreateAsciiAtom("(II)V")); - VM_Method method = methRef.resolve(); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(methRef, method); + VM_Method method = recordUncaughtBclrMethRef.resolve(); + OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(recordUncaughtBclrMethRef, method); OPT_Operand psRef = gc.makeLocal(1,psTref); Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer @@ -1077,7 +1039,7 @@ Call.setParam(s, 2, lr); // Link register value Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); - Call.setAddress(s, new OPT_AddressConstantOperand(methRef.peekResolvedMethod().getOffset())); + Call.setAddress(s, new OPT_AddressConstantOperand(recordUncaughtBclrMethRef.peekResolvedMethod().getOffset())); s.position = gc.inlineSequence; s.bcIndex = 7; appendInstructionToCurrentBlock(s); @@ -1093,21 +1055,15 @@ if(DBT_Options.plantUncaughtBcctrWatcher) { // Plant call OPT_Instruction s = Call.create(CALL, null, null, null, null, 3); - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom - ("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;")); - VM_MethodReference methRef = (VM_MethodReference)VM_MemberReference.findOrCreate(psTref, - VM_Atom.findOrCreateAsciiAtom("recordUncaughtBcctr"), - VM_Atom.findOrCreateAsciiAtom("(II)V")); - VM_Method method = methRef.resolve(); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(methRef, method); + VM_Method method = recordUncaughtBcctrMethRef.resolve(); + OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(recordUncaughtBcctrMethRef, method); OPT_Operand psRef = gc.makeLocal(1,psTref); Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer Call.setParam(s, 1, new OPT_IntConstantOperand(pc)); // Address of bcctr instruction Call.setParam(s, 2, ctr); // Count register value Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); - Call.setAddress(s, new OPT_AddressConstantOperand(methRef.peekResolvedMethod().getOffset())); + Call.setAddress(s, new OPT_AddressConstantOperand(recordUncaughtBcctrMethRef.peekResolvedMethod().getOffset())); s.position = gc.inlineSequence; s.bcIndex = 13; appendInstructionToCurrentBlock(s); @@ -1147,7 +1103,6 @@ unusedRegisterList.add(lrRegMap); } if(xerRegInUse == false) { - unusedRegisterList.add(xerRegMap); unusedRegisterList.add(xerRegMap_SO); unusedRegisterList.add(xerRegMap_OV); unusedRegisterList.add(xerRegMap_ByteCount); Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-03-18 22:49:42 UTC (rev 4) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-03-19 16:01:57 UTC (rev 5) @@ -30,588 +30,588 @@ * implements default methods that just throw errors */ public class PPC_InstructionDecoder extends InstructionDecoder implements OPT_Operators { - /* Different instruction formats */ + /* Different instruction formats */ - /** Invalid opcode */ - protected static final int INVALID_OP = 0; - /** D form opcode */ - protected static final int D_FORM = 1; - /** B form opcode */ - protected static final int B_FORM = 2; - /** I form opcode */ - protected static final int I_FORM = 3; - /** SC form opcode */ - protected static final int SC_FORM = 4; - /** X form opcode */ - protected static final int X_FORM = 5; - /** XL form opcode */ - protected static final int XL_FORM = 6; - /** XFX form opcode */ - protected static final int XFX_FORM = 7; - /** XFL form opcode */ - protected static final int XFL_FORM = 8; - /** XO form opcode */ - protected static final int XO_FORM = 9; - /** A form opcode */ - protected static final int A_FORM = 10; - /** M form opcode */ - protected static final int M_FORM = 11; - /** Exetended form opcode */ - protected static final int EXTENDED = 12; + /** Invalid opcode */ + protected static final int INVALID_OP = 0; + /** D form opcode */ + protected static final int D_FORM = 1; + /** B form opcode */ + protected static final int B_FORM = 2; + /** I form opcode */ + protected static final int I_FORM = 3; + /** SC form opcode */ + protected static final int SC_FORM = 4; + /** X form opcode */ + protected static final int X_FORM = 5; + /** XL form opcode */ + protected static final int XL_FORM = 6; + /** XFX form opcode */ + protected static final int XFX_FORM = 7; + /** XFL form opcode */ + protected static final int XFL_FORM = 8; + /** XO form opcode */ + protected static final int XO_FORM = 9; + /** A form opcode */ + protected static final int A_FORM = 10; + /** M form opcode */ + protected static final int M_FORM = 11; + /** Exetended form opcode */ + protected static final int EXTENDED = 12; - /* Types of comparison */ + /* Types of comparison */ - /** Unsigned integer comparison */ - static final int UNSIGNED_INT_CMP=1; - /** Signed integer comparison */ - static final int SIGNED_INT_CMP=2; - /** Floating point unordered comparison */ - static final int FP_CMPU=3; + /** Unsigned integer comparison */ + static final int UNSIGNED_INT_CMP=1; + /** Signed integer comparison */ + static final int SIGNED_INT_CMP=2; + /** Floating point unordered comparison */ + static final int FP_CMPU=3; - /** - * Look up table to find instruction translator, performed using the - * instruction opcode. - */ - static final OpCodeLookUp[] opCodeLookUp = { - /* OPCD form mnemonic translator */ - /* ---- ---- -------- ---------- */ - ... [truncated message content] |
From: <cap...@us...> - 2007-03-21 15:20:25
|
Revision: 9 http://svn.sourceforge.net/pearcolator/?rev=9&view=rev Author: captain5050 Date: 2007-03-21 08:20:26 -0700 (Wed, 21 Mar 2007) Log Message: ----------- Fix to PowerPC stack initialization, still need to make a generic stack initializer Modified Paths: -------------- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-03-21 15:19:39 UTC (rev 8) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-03-21 15:20:26 UTC (rev 9) @@ -32,6 +32,11 @@ private int brk; /** + * The top of the stack + */ + private static final int STACK_TOP = 0xC0000000; + + /** * Constructor */ public X86_LinuxProcessSpace(Loader loader) { @@ -72,34 +77,10 @@ LinuxStackInitializer.AuxiliaryVectorType.AT_EGID, DBT_Options.GID, LinuxStackInitializer.AuxiliaryVectorType.AT_SECURE, 0, - // LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, LinuxStackInitializer.AuxiliaryVectorType.STACK_TOP - getPlatformString().length, + //LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, LinuxStackInitializer.AuxiliaryVectorType.STACK_TOP - getPlatformString().length, LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0}; - /* The cache sizes and flags are as for a test program running on - the iBook, softwood. AT_BASE will need to be changed for dynamically linked binaries. */ - - /* Environment variables, exactly as on softwood. Not that the number 8380 in SSH_* varies. */ - String[] env = {"HOSTNAME=softwood", "PVM_RSH=/usr/bin/rsh", - "HOST_JAVA_HOME=/home/amulocal/linux/appl/j2sdk1.4.2", "SHELL=/bin/bash", - "TERM=xterm", "HISTSIZE=1000", "SSH_CLIENT=130.88.194.110 8380 22", - "CVSROOT=/home/simgroup/cvsroot", "QTDIR=/usr/lib/qt-3.1", "SSH_TTY=/dev/pts/0", - "RVM_HOST_CONFIG=/home/matleyr/cvs/rvm/config/i686-pc-linux-gnu.ManCS", - "USER=matleyr", "LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:", "XENVIRONMENT=/home/matleyr/.Xdefaults", - "PVM_ROOT=/usr/share/pvm3", "CLASSPATH_ROOT=/home/matleyr/cvs/classpath", - "PATH=/home/matleyr/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/opt/lib/j2re1.3.1/bin:/home/matleyr/cvs/rvm/bin:/home/matleyr/bin", "MAIL=/var/spool/mail/matleyr", - "_=/bin/bash", "PWD=/home/matleyr/dhry", "INPUTRC=/etc/inputrc", - "LANG=en_GB.iso88591", "LAMHELPFILE=/etc/lam/lam-helpfile", - "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass", - "CSHOME=ma...@an...:/home/M03/cc/matleyr", "HOME=/home/matleyr", - "SHLVL=1", "SIM=/home/simgroup/matleyr", "XPVM_ROOT=/usr/share/pvm3/xpvm", - "RVM_ROOT=/home/matleyr/cvs", "LOGNAME=matleyr", "PRINTER=happy_duplex", - "SSH_CONNECTION=130.88.194.110 2380 130.88.198.215 22", - "LESSOPEN=|/usr/bin/lesspipe.sh %s", "RVM_BUILD=/tmp/RVMbuild", - "DISPLAY=localhost:10.0", - "RVM_TARGET_CONFIG=/home/matleyr/cvs/rvm/config/i686-pc-linux-gnu.ManCS", - "G_BROKEN_FILENAMES=1"}; - - return LinuxStackInitializer.stackInit(memory, 0xC0000000, args, env, auxVector); + return LinuxStackInitializer.stackInit(memory, STACK_TOP, args, getEnvironmentVariables(), auxVector); } /** Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-21 15:19:39 UTC (rev 8) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-21 15:20:26 UTC (rev 9) @@ -393,12 +393,32 @@ */ public abstract void doSysCall(); + private static final String[] env = {"HOSTNAME=softwood", "PVM_RSH=/usr/bin/rsh", + "HOST_JAVA_HOME=/home/amulocal/linux/appl/j2sdk1.4.2", "SHELL=/bin/bash", + "TERM=xterm", "HISTSIZE=1000", "SSH_CLIENT=130.88.194.110 8380 22", + "CVSROOT=/home/simgroup/cvsroot", "QTDIR=/usr/lib/qt-3.1", "SSH_TTY=/dev/pts/0", + "RVM_HOST_CONFIG=/home/matleyr/cvs/rvm/config/i686-pc-linux-gnu.ManCS", + "USER=matleyr", "LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:", "XENVIRONMENT=/home/matleyr/.Xdefaults", + "PVM_ROOT=/usr/share/pvm3", "CLASSPATH_ROOT=/home/matleyr/cvs/classpath", + "PATH=/home/matleyr/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/opt/lib/j2re1.3.1/bin:/home/matleyr/cvs/rvm/bin:/home/matleyr/bin", "MAIL=/var/spool/mail/matleyr", + "_=/bin/bash", "PWD=/home/matleyr/dhry", "INPUTRC=/etc/inputrc", + "LANG=en_GB.iso88591", "LAMHELPFILE=/etc/lam/lam-helpfile", + "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass", + "CSHOME=ma...@an...:/home/M03/cc/matleyr", "HOME=/home/matleyr", + "SHLVL=1", "SIM=/home/simgroup/matleyr", "XPVM_ROOT=/usr/share/pvm3/xpvm", + "RVM_ROOT=/home/matleyr/cvs", "LOGNAME=matleyr", "PRINTER=happy_duplex", + "SSH_CONNECTION=130.88.194.110 2380 130.88.198.215 22", + "LESSOPEN=|/usr/bin/lesspipe.sh %s", "RVM_BUILD=/tmp/RVMbuild", + "DISPLAY=localhost:10.0", + "RVM_TARGET_CONFIG=/home/matleyr/cvs/rvm/config/i686-pc-linux-gnu.ManCS", + "G_BROKEN_FILENAMES=1"}; /** * Method to return environment variables * @return an array of environment variable strings */ protected String[] getEnvironmentVariables() { - throw new Error("TODO!"); + /* Environment variables, exactly as on softwood. Not that the number 8380 in SSH_* varies. */ + return env; /* if (!DBT_Options.loadEnv) { Process printenv = Runtime.exec("/usr/bin/printenv"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-03-24 23:14:37
|
Revision: 10 http://svn.sourceforge.net/pearcolator/?rev=10&view=rev Author: captain5050 Date: 2007-03-24 16:14:38 -0700 (Sat, 24 Mar 2007) Log Message: ----------- Fix dynamic linking, fix for lazy keys, branch code tidy up, try to spread the use of final fields. Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/ppc/decoder/PPC_Laziness.java src/org/binarytranslator/arch/x86/decoder/X86_Laziness.java src/org/binarytranslator/generic/branch/BranchLogic.java src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/generic/decoder/Laziness.java src/org/binarytranslator/generic/memory/ByteAddressedByteSwapMemory.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/IntAddressedByteSwapMemory.java src/org/binarytranslator/generic/memory/IntAddressedMemory.java src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java src/org/binarytranslator/generic/memory/IntAddressedReversedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_Trace.java src/org/binarytranslator/vmInterface/DynamicCodeRunner.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/DBT_Options.java 2007-03-24 23:14:38 UTC (rev 10) @@ -54,16 +54,11 @@ public final static boolean optimizeBackwardBranches = true; /** - * Set this to true to record uncaught bclr instructions + * Set this to true to record uncaught branch instructions */ - public static boolean plantUncaughtBclrWatcher = false; + public static boolean plantUncaughtBranchWatcher = false; /** - * Set this to true to record uncaught bcctr instructions - */ - public static boolean plantUncaughtBcctrWatcher = true; - - /** * Should all branches (excluding to lr and ctr) be resolved in one * big go or one at at a time */ Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-03-24 23:14:38 UTC (rev 10) @@ -125,17 +125,9 @@ /** Reference to PPC process space pc field */ private static final VM_FieldReference pcFieldRef; - /** Reference to PPC process space recordUncaughtBclr method */ - private static final VM_MethodReference recordUncaughtBclrMethRef; - - /** Reference to PPC process space recordUncaughtBcctr method */ - private static final VM_MethodReference recordUncaughtBcctrMethRef; - /* Static initializer */ static { - psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); + psTref = VM_TypeReference.findOrCreate(PPC_ProcessSpace.class); gprFieldRefs = new VM_FieldReference[32]; fprFieldRefs = new VM_FieldReference[32]; final VM_Atom intAtom = VM_Atom.findOrCreateAsciiAtom("I"); @@ -189,12 +181,6 @@ pcFieldRef = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("pc"), intAtom ).asFieldReference(); - recordUncaughtBclrMethRef = (VM_MethodReference)VM_MemberReference.findOrCreate(psTref, - VM_Atom.findOrCreateAsciiAtom("recordUncaughtBclr"), - VM_Atom.findOrCreateAsciiAtom("(II)V")); - recordUncaughtBcctrMethRef = (VM_MethodReference)VM_MemberReference.findOrCreate(psTref, - VM_Atom.findOrCreateAsciiAtom("recordUncaughtBcctr"), - VM_Atom.findOrCreateAsciiAtom("(II)V")); } // -oO PPC register to HIR register mappings Oo- @@ -1018,58 +1004,6 @@ registerBranchAndLink(pc, pc+4, dest); } - // -oO Trace helping methods Oo- - - /** - * Plant a record bclr call. NB register state won't get resolved for call - * @param pc the address of the bclr instruction - * @param lr the link register value - */ - public void plantRecordUncaughtBclr(int pc, OPT_RegisterOperand lr) { - // Is it sensible to record this information? - if((gc.options.getOptLevel() > 0) && (DBT_Options.plantUncaughtBclrWatcher)) { - // Plant call - OPT_Instruction s = Call.create(CALL, null, null, null, null, 3); - VM_Method method = recordUncaughtBclrMethRef.resolve(); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(recordUncaughtBclrMethRef, method); - - OPT_Operand psRef = gc.makeLocal(1,psTref); - Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer - Call.setParam(s, 1, new OPT_IntConstantOperand(pc)); // Address of bclr instruction - Call.setParam(s, 2, lr); // Link register value - Call.setGuard(s, new OPT_TrueGuardOperand()); - Call.setMethod(s, methOp); - Call.setAddress(s, new OPT_AddressConstantOperand(recordUncaughtBclrMethRef.peekResolvedMethod().getOffset())); - s.position = gc.inlineSequence; - s.bcIndex = 7; - appendInstructionToCurrentBlock(s); - } - } - - /** - * Plant a record bcctr call. NB register state won't get resolved for call - * @param pc the address of the bclr instruction - * @param ctr the count register value - */ - public void plantRecordUncaughtBcctr(int pc, OPT_RegisterOperand ctr) { - if(DBT_Options.plantUncaughtBcctrWatcher) { - // Plant call - OPT_Instruction s = Call.create(CALL, null, null, null, null, 3); - VM_Method method = recordUncaughtBcctrMethRef.resolve(); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(recordUncaughtBcctrMethRef, method); - OPT_Operand psRef = gc.makeLocal(1,psTref); - Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer - Call.setParam(s, 1, new OPT_IntConstantOperand(pc)); // Address of bcctr instruction - Call.setParam(s, 2, ctr); // Count register value - Call.setGuard(s, new OPT_TrueGuardOperand()); - Call.setMethod(s, methOp); - Call.setAddress(s, new OPT_AddressConstantOperand(recordUncaughtBcctrMethRef.peekResolvedMethod().getOffset())); - s.position = gc.inlineSequence; - s.bcIndex = 13; - appendInstructionToCurrentBlock(s); - } - } - // -oO Optimisations on the generated HIR Oo- /** Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-03-24 23:14:38 UTC (rev 10) @@ -13,6 +13,7 @@ import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.decoder.InstructionDecoder; +import org.binarytranslator.generic.branch.BranchLogic; import org.jikesrvm.opt.ir.*; import org.jikesrvm.*; @@ -3338,7 +3339,7 @@ ppc2ir.appendInstructionToCurrentBlock(lookupswitch_instr); ppc2ir.registerLookupSwitchForReturnUnresolved(lookupswitch_instr, pc, (PPC_Laziness)lazy.clone()); ppc2ir.setCurrentBlock(fallThrough); - ppc2ir.plantRecordUncaughtBclr(pc, branchAddress.copyRO()); + ppc2ir.plantRecordUncaughtBranch(pc, branchAddress.copyRO(), BranchLogic.RETURN); ppc2ir.setReturnValueResolveLazinessAndBranchToFinish((PPC_Laziness)lazy.clone(), branchAddress.copyRO()); // stop translation on branch always @@ -3981,7 +3982,7 @@ ppc2ir.appendInstructionToCurrentBlock(lookupswitch_instr); ppc2ir.registerLookupSwitchForSwitchUnresolved(lookupswitch_instr, pc, (PPC_Laziness)lazy.clone(), lk != 0); ppc2ir.setCurrentBlock(fallThrough); - ppc2ir.plantRecordUncaughtBcctr(pc, branchAddress.copyRO()); + ppc2ir.plantRecordUncaughtBranch(pc, branchAddress.copyRO(), BranchLogic.INDIRECT_BRANCH); ppc2ir.setReturnValueResolveLazinessAndBranchToFinish((PPC_Laziness)lazy.clone(), branchAddress.copyRO()); // stop translation on branch always Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_Laziness.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_Laziness.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_Laziness.java 2007-03-24 23:14:38 UTC (rev 10) @@ -17,6 +17,25 @@ */ public final class PPC_Laziness extends Laziness { /** + * Key for when laziness is stored in a hash table along with a PC + */ + class PPC_LazinessKey extends Key { + int pc; + public int hashCode() { + return pc; + } + public boolean equals(Object o) { + return ((o instanceof PPC_LazinessKey) && ((PPC_LazinessKey)o).pc == pc); + } + PPC_LazinessKey (int pc) { + this.pc = pc; + } + public String toString() { + return "0x" + Integer.toHexString(pc); + } + } + + /** * Default constructor - nothing is lazy */ PPC_Laziness() { @@ -39,23 +58,8 @@ * Generate a key value encoding this laziness and a PC value * @parm pc the PC value we're trying to make a key for */ - public Object makeKey(int pc) { - class Key { - int pc; - public int hashCode() { - return pc; - } - public boolean equals(Object o) { - return ((o instanceof Key) && ((Key)o).pc == pc); - } - Key (int pc) { - this.pc = pc; - } - public String toString() { - return "0x" + Integer.toHexString(pc); - } - } - return new Key(pc); + public Key makeKey(int pc) { + return new PPC_LazinessKey(pc); } /** Modified: src/org/binarytranslator/arch/x86/decoder/X86_Laziness.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_Laziness.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/arch/x86/decoder/X86_Laziness.java 2007-03-24 23:14:38 UTC (rev 10) @@ -14,6 +14,32 @@ * Capture lazy information for X86 */ public class X86_Laziness extends Laziness { + /** + * Key for when laziness is stored in a hash table along with a PC + */ + static class X86_LazinessKey extends Key { + private final int mangledRegisterState; + private final int pc; + X86_LazinessKey(int mangledRegisterState, int pc) { + this.mangledRegisterState = mangledRegisterState; + this.pc = pc; + } + public boolean equals(Object o) { + if (o instanceof X86_LazinessKey) { + X86_LazinessKey other = (X86_LazinessKey)o; + return (other.pc == pc) && (other.mangledRegisterState == mangledRegisterState); + } else { + return false; + } + } + public int hashCode() { + return mangledRegisterState ^ pc; + } + public String toString() { + return "0x" + Integer.toHexString(pc) + ".0x" + Integer.toHexString(mangledRegisterState); + } + } + /** * In this state, is the 32bit register valid? (default) */ @@ -69,8 +95,8 @@ * Given the current program position make a key object that will * allow */ - public Object makeKey(int pc) { - return new Long(((long)mangledRegisterState << 32) | pc); + public Key makeKey(int pc) { + return new X86_LazinessKey(mangledRegisterState, pc); } /** Modified: src/org/binarytranslator/generic/branch/BranchLogic.java =================================================================== --- src/org/binarytranslator/generic/branch/BranchLogic.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/generic/branch/BranchLogic.java 2007-03-24 23:14:38 UTC (rev 10) @@ -22,15 +22,21 @@ * terminating on branches whose destinations aren't known */ public class BranchLogic { + /** Code to indicate branch was an indirect branch */ + public static final int INDIRECT_BRANCH=0; + + /** Code to indicate branch was a return */ + public static final int RETURN=1; + /** * A set of procedure information */ - private SortedMap procedures; + private final SortedMap procedures; /** * A set of switch like branchs sites and their destinations */ - private SortedMap branchSitesAndDestinations; + private final SortedMap branchSitesAndDestinations; /** * Global branch information @@ -61,13 +67,13 @@ * @param dest the destination of the branch instruction */ public void registerCall(int pc, int ret, int dest) { - ProcedureInformation procedure = (ProcedureInformation)procedures.get(new Integer(dest)); + ProcedureInformation procedure = (ProcedureInformation)procedures.get(Integer.valueOf(dest)); if (procedure != null) { procedure.registerCall(pc, ret); } else { procedure = new ProcedureInformation(pc, ret, dest); - procedures.put(new Integer(dest), procedure); + procedures.put(Integer.valueOf(dest), procedure); } } @@ -90,7 +96,7 @@ */ private ProcedureInformation getLikelyProcedure(int pc) { if (procedures.size() > 0) { - SortedMap priorProcedures = procedures.headMap(new Integer(pc)); + SortedMap priorProcedures = procedures.headMap(Integer.valueOf(pc)); if (priorProcedures.size() > 0) { Integer procedureEntry = (Integer)priorProcedures.lastKey(); return (ProcedureInformation)procedures.get(procedureEntry); @@ -104,19 +110,19 @@ * @param pc the address of the branch instruction * @param lr the value of the link register */ - public void registerBranch(int pc, int ctr) { - Set dests = (Set)branchSitesAndDestinations.get(new Integer(pc)); + public void registerBranch(int pc, int ctr, int type) { + Set dests = (Set)branchSitesAndDestinations.get(Integer.valueOf(pc)); if (dests != null) { - if (dests.contains(new Integer(ctr))) { + if (dests.contains(Integer.valueOf(ctr))) { // This ctr address is already registered return; } } else { dests = new HashSet(); - branchSitesAndDestinations.put(new Integer(pc), dests); + branchSitesAndDestinations.put(Integer.valueOf(pc), dests); } - dests.add(new Integer(ctr)); + dests.add(Integer.valueOf(ctr)); } } Modified: src/org/binarytranslator/generic/decoder/DecoderUtils.java =================================================================== --- src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-03-24 23:14:38 UTC (rev 10) @@ -18,6 +18,7 @@ import org.binarytranslator.vmInterface.DBT_Trace; import org.binarytranslator.vmInterface.TranslationHelper; import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.DBT_Options; import org.jikesrvm.VM; @@ -84,7 +85,174 @@ * </dl> */ public abstract class DecoderUtils implements OPT_Constants, OPT_Operators, TranslationHelper { + // -oO Constants Oo- + + /** + * VM_TypeReference of + * org.binarytranslator.generic.os.process.ProcessSpace + */ + private static final VM_TypeReference psTref; + + /** + * Method ProcessSpace.doSysCall + */ + public static final VM_Method sysCallMethod; + + /** + * VM_TypeReference of + * org.binarytranslator.generic.fault.BadInstructionException + */ + private static final VM_Class badInstrKlass; + + /** + * Method BadInstructionException.<init> + */ + public static final VM_Method badInstrKlassInitMethod; + + /** + * Method ProcessSpace.recordUncaughtBranchBadInstructionException.<init> + */ + public static final VM_Method recordUncaughtBranchMethod; + + static { + psTref = java.lang.JikesRVMSupport.getTypeForClass(ProcessSpace.class).getTypeRef(); + VM_MethodReference sysCallMethRef = (VM_MethodReference) + VM_MemberReference.findOrCreate(psTref, + VM_Atom.findOrCreateAsciiAtom("doSysCall"), + VM_Atom.findOrCreateAsciiAtom("()V")); + sysCallMethod = sysCallMethRef.resolveInvokeSpecial(); + + badInstrKlass = java.lang.JikesRVMSupport.getTypeForClass(BadInstructionException.class).asClass(); + + VM_MethodReference badInstrKlassInitMethRef = (VM_MethodReference) + VM_MemberReference.findOrCreate(badInstrKlass.getTypeRef(), + VM_Atom.findOrCreateAsciiAtom("<init>"), + VM_Atom.findOrCreateAsciiAtom("(I" + + psTref.getName() + + ")V")); + badInstrKlassInitMethod = badInstrKlassInitMethRef.resolveInvokeSpecial(); + + VM_MethodReference recordUncaughtBranchMethRef = (VM_MethodReference) + VM_MemberReference.findOrCreate(psTref, + VM_Atom.findOrCreateAsciiAtom("recordUncaughtBranch"), + VM_Atom.findOrCreateAsciiAtom("(III)V")); + recordUncaughtBranchMethod = recordUncaughtBranchMethRef.resolveInvokeSpecial(); + } + + + // -oO Global IR Oo- + + /** + * Number of translated instructions + */ + public int numberOfInstructions; + + /** + * The process space object used by the running PPC binary. + */ + public ProcessSpace ps; + + /** + * The generation context. + */ + protected OPT_GenerationContext gc; + + // -oO Global HIR basic blocks Oo- + + /** + * The OPT_BasicBlock in which instructions are currently being + * inserted + */ + protected OPT_BasicBlock currentBlock; + + /** + * The pc value corresponding to the instruction currently being + * translated + */ + protected int currentPC; + + /** + * The OPT_BasicBlock which will contain the next translated instruction + */ + protected OPT_BasicBlock nextBlock; + + /** + * The basic block is used by finish trace to hold all the code that + * must be executed before returning to the main run loop + */ + protected OPT_BasicBlock finishBlock; + + /** + * This block gets instructions to pre-fill registers inserted into + * it. + */ + protected OPT_BasicBlock preFillBlock; + + /** + * Map to locate HIR basic blocks to re-use translation within a + * trace + */ + protected final HashMap<Laziness.Key,OPT_BasicBlock> blockMap; + + /** + * List of unresolved Goto instructions + */ + protected final ArrayList<OPT_Instruction> unresolvedGoto; + + /** + * List of where unresolved Goto instructions are trying to go + */ + protected final ArrayList<Integer> unresolvedGoto_PC; + /** + * List of what the unresolved Goto instruction's target laziness should be + */ + protected final ArrayList<Laziness> unresolvedGoto_Laziness; + + /** + * List of unresolved IfCmp instructions + */ + protected final ArrayList<OPT_Instruction> unresolvedIfCmp; + /** + * List of where unresolved IfCmp instructions are trying to go + */ + protected final ArrayList<Integer> unresolvedIfCmp_PC; + /** + * List of what the unresolved IfCmp instruction's target laziness should be + */ + protected final ArrayList<Laziness> unresolvedIfCmp_Laziness; + + /** + * List of unresolved LookupSwitch instructions used for branching to the link register + */ + protected final ArrayList<OPT_Instruction> unresolvedLookupSwitchForReturns; + /** + * List of where unresolved Goto instructions are trying to go + */ + protected final ArrayList<Integer> unresolvedLookupSwitchForReturns_PC; + /** + * List of what the unresolved Goto instruction's target laziness should be + */ + protected final ArrayList<Laziness> unresolvedLookupSwitchForReturns_Laziness; + + /** + * List of unresolved LookupSwitch instructions used for branching to the count register + */ + protected final ArrayList<OPT_Instruction> unresolvedLookupSwitchForSwitches; + /** + * List of where unresolved LookupSwitch instructions are branching from + */ + protected final ArrayList<Integer> unresolvedLookupSwitchForSwitches_PC; + /** + * List of what the unresolved LookupSwitch instruction's target laziness should be + */ + protected final ArrayList<Laziness> unresolvedLookupSwitchForSwitches_Laziness; + /** + * List of whether the unresolved LookupSwitch instruction's was a call + */ + protected final ArrayList<Boolean> unresolvedLookupSwitchForSwitches_WasCall; + // -oO Debug Oo- + /** * Report some debug output */ @@ -117,22 +285,22 @@ finishBlock = createBlockAfterCurrent(); // Fix up stores - unresolvedGoto = new ArrayList(); - unresolvedGoto_PC = new ArrayList(); - unresolvedGoto_Laziness = new ArrayList(); + unresolvedGoto = new ArrayList<OPT_Instruction>(); + unresolvedGoto_PC = new ArrayList<Integer>(); + unresolvedGoto_Laziness = new ArrayList<Laziness>(); - unresolvedIfCmp = new ArrayList(); - unresolvedIfCmp_PC = new ArrayList(); - unresolvedIfCmp_Laziness = new ArrayList(); + unresolvedIfCmp = new ArrayList<OPT_Instruction>(); + unresolvedIfCmp_PC = new ArrayList<Integer>(); + unresolvedIfCmp_Laziness = new ArrayList<Laziness>(); - unresolvedLookupSwitchForReturns = new ArrayList(); - unresolvedLookupSwitchForReturns_PC = new ArrayList(); - unresolvedLookupSwitchForReturns_Laziness = new ArrayList(); + unresolvedLookupSwitchForReturns = new ArrayList<OPT_Instruction>(); + unresolvedLookupSwitchForReturns_PC = new ArrayList<Integer>(); + unresolvedLookupSwitchForReturns_Laziness = new ArrayList<Laziness>(); - unresolvedLookupSwitchForSwitches = new ArrayList(); - unresolvedLookupSwitchForSwitches_PC = new ArrayList(); - unresolvedLookupSwitchForSwitches_Laziness = new ArrayList(); - unresolvedLookupSwitchForSwitches_WasCall = new ArrayList(); + unresolvedLookupSwitchForSwitches = new ArrayList<OPT_Instruction>(); + unresolvedLookupSwitchForSwitches_PC = new ArrayList<Integer>(); + unresolvedLookupSwitchForSwitches_Laziness = new ArrayList<Laziness>(); + unresolvedLookupSwitchForSwitches_WasCall = new ArrayList<Boolean>(); } /** @@ -253,62 +421,7 @@ */ protected abstract int translateInstruction(Laziness lazy, int pc); - // -oO Global IR Oo- - /** - * Number of translated instructions - */ - public int numberOfInstructions; - - /** - * The process space object used by the running PPC binary. - */ - public ProcessSpace ps; - - /** - * The generation context. - */ - protected OPT_GenerationContext gc; - - /** - * Get the generation context. - */ - public OPT_GenerationContext getGenerationContext() { - return gc; - } - - // -oO Global HIR basic blocks Oo- - - /** - * The OPT_BasicBlock in which instructions are currently being - * inserted - */ - protected OPT_BasicBlock currentBlock; - - /** - * The pc value corresponding to the instruction currently being - * translated - */ - protected int currentPC; - - /** - * The OPT_BasicBlock which will contain the next translated instruction - */ - protected OPT_BasicBlock nextBlock; - - /** - * The basic block is used by finish trace to hold all the code that - * must be executed before returning to the main run loop - */ - protected OPT_BasicBlock finishBlock; - - /** - * This block gets instructions to pre-fill registers inserted into - * it. - */ - protected OPT_BasicBlock preFillBlock; - - /** * Get the block which is currently having instructions inserted * into it * @return the current block @@ -421,7 +534,12 @@ public void appendInstructionToCurrentBlock(OPT_Instruction i) { if(i.bcIndex == UNKNOWN_BCI) { i.position = gc.inlineSequence; - i.bcIndex = (currentPC >> 2) & 0xFFFF; + // we only have 16bits to distinguish instructions (the bcIndex + // is effective 16bit when stored in the machine code map), + // Intel can't distinguish branches within 16bytes, so neither + // can we, the top bit is saved for distinguished addresses we + // need to know to dynamically link things + i.bcIndex = (currentPC >> 4) & 0x7FFF; } currentBlock.appendInstruction(i); } @@ -447,71 +565,16 @@ spillAllRegisters(); } - // -oO Laziness Oo- - - /** - * Map to locate HIR basic blocks to re-use translation within a - * trace - */ - protected HashMap blockMap; - /** - * List of unresolved Goto instructions + * Get the generation context. */ - protected ArrayList unresolvedGoto; - /** - * List of where unresolved Goto instructions are trying to go - */ - protected ArrayList unresolvedGoto_PC; - /** - * List of what the unresolved Goto instruction's target laziness should be - */ - protected ArrayList unresolvedGoto_Laziness; + public OPT_GenerationContext getGenerationContext() { + return gc; + } - /** - * List of unresolved IfCmp instructions - */ - protected ArrayList unresolvedIfCmp; - /** - * List of where unresolved IfCmp instructions are trying to go - */ - protected ArrayList unresolvedIfCmp_PC; - /** - * List of what the unresolved IfCmp instruction's target laziness should be - */ - protected ArrayList unresolvedIfCmp_Laziness; + // -oO Laziness Oo- /** - * List of unresolved LookupSwitch instructions used for branching to the link register - */ - protected ArrayList unresolvedLookupSwitchForReturns; - /** - * List of where unresolved Goto instructions are trying to go - */ - protected ArrayList unresolvedLookupSwitchForReturns_PC; - /** - * List of what the unresolved Goto instruction's target laziness should be - */ - protected ArrayList unresolvedLookupSwitchForReturns_Laziness; - - /** - * List of unresolved LookupSwitch instructions used for branching to the count register - */ - protected ArrayList unresolvedLookupSwitchForSwitches; - /** - * List of where unresolved LookupSwitch instructions are branching from - */ - protected ArrayList unresolvedLookupSwitchForSwitches_PC; - /** - * List of what the unresolved LookupSwitch instruction's target laziness should be - */ - protected ArrayList unresolvedLookupSwitchForSwitches_Laziness; - /** - * List of whether the unresolved LookupSwitch instruction's was a call - */ - protected ArrayList unresolvedLookupSwitchForSwitches_WasCall; - - /** * Create the initial object for capturing lazy information */ protected abstract Laziness createInitialLaziness(); @@ -538,7 +601,7 @@ * @return basic block or null if no translation exists */ public OPT_BasicBlock findMapping(int pc, Laziness lazy) { - return (OPT_BasicBlock)blockMap.get(lazy.makeKey(pc)); + return blockMap.get(lazy.makeKey(pc)); } /** @@ -549,7 +612,7 @@ */ public void registerIfCmpTargetUnresolved(OPT_Instruction ifcmp_instr, int targetPC, Laziness targetLaziness){ unresolvedIfCmp.add(ifcmp_instr); - unresolvedIfCmp_PC.add(new Integer(targetPC)); + unresolvedIfCmp_PC.add(targetPC); unresolvedIfCmp_Laziness.add(targetLaziness); } @@ -596,7 +659,7 @@ */ public void registerGotoTargetUnresolved(OPT_Instruction goto_instr, int targetPC, Laziness targetLaziness){ unresolvedGoto.add(goto_instr); - unresolvedGoto_PC.add(new Integer(targetPC)); + unresolvedGoto_PC.add(targetPC); unresolvedGoto_Laziness.add(targetLaziness); } @@ -662,7 +725,7 @@ */ public void registerLookupSwitchForReturnUnresolved(OPT_Instruction lookupswitch_instr, int pc, Laziness targetLaziness){ unresolvedLookupSwitchForReturns.add(lookupswitch_instr); - unresolvedLookupSwitchForReturns_PC.add(new Integer(pc)); + unresolvedLookupSwitchForReturns_PC.add(pc); unresolvedLookupSwitchForReturns_Laziness.add(targetLaziness); } /** @@ -769,9 +832,9 @@ */ public void registerLookupSwitchForSwitchUnresolved(OPT_Instruction lookupswitch_instr, int pc, Laziness targetLaziness, boolean link){ unresolvedLookupSwitchForSwitches.add(lookupswitch_instr); - unresolvedLookupSwitchForSwitches_PC.add(new Integer(pc)); + unresolvedLookupSwitchForSwitches_PC.add(pc); unresolvedLookupSwitchForSwitches_Laziness.add(targetLaziness); - unresolvedLookupSwitchForSwitches_WasCall.add(Boolean.valueOf(link)); + unresolvedLookupSwitchForSwitches_WasCall.add(link); } /** * Are all LookupSwitch instructions for branches to CTR ready to be @@ -1024,25 +1087,19 @@ // Plant call OPT_Instruction s = Call.create(CALL, null, null, null, null, 1); - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - VM_MethodReference methRef = (VM_MethodReference)VM_MemberReference.findOrCreate(psTref, - VM_Atom.findOrCreateAsciiAtom("doSysCall"), - VM_Atom.findOrCreateAsciiAtom("()V")); - VM_Method method = methRef.resolveInvokeSpecial(); // VM_CompiledMethod cm = method.getCurrentCompiledMethod(); // OPT_MethodOperand methOp = OPT_MethodOperand.COMPILED(method, cm.getOsrJTOCoffset()); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(methRef, method); + OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(sysCallMethod.getMemberRef().asMethodReference(), + sysCallMethod); OPT_Operand psRef = gc.makeLocal(1,psTref); Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer for doSysCall Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); - Call.setAddress(s, new OPT_AddressConstantOperand(methRef.peekResolvedMethod().getOffset())); + Call.setAddress(s, new OPT_AddressConstantOperand(sysCallMethod.getOffset())); s.position = gc.inlineSequence; - s.bcIndex = 7; + s.bcIndex = DBT_Trace.DO_SYSCALL; appendInstructionToCurrentBlock(s); // Fill all registers again following system call @@ -1065,52 +1122,40 @@ resolveLaziness(lazy); spillAllRegisters(); - VM_TypeReference eTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/generic/os/fault/BadInstructionException;") - ); - VM_Class badInstrKlass = (VM_Class)eTref.peekResolvedType(); OPT_Operator newOperator; - OPT_TypeOperand typeOperand; + OPT_TypeOperand typeOperand = new OPT_TypeOperand(badInstrKlass); + VM_TypeReference eTref = badInstrKlass.getTypeRef(); - if ((badInstrKlass != null) && (badInstrKlass.isInitialized() || badInstrKlass.isInBootImage())) { + if (badInstrKlass.isInitialized() || badInstrKlass.isInBootImage()) { newOperator = NEW; - typeOperand = new OPT_TypeOperand(badInstrKlass); - } - else { + } else { newOperator = NEW_UNRESOLVED; - typeOperand = new OPT_TypeOperand(eTref); } OPT_RegisterOperand eRef = gc.temps.makeTemp(eTref); OPT_Instruction n = New.create(newOperator,eRef, typeOperand); n.position = gc.inlineSequence; - n.bcIndex = 0; + n.bcIndex = DBT_Trace.BAD_INSTRUCTION_NEW; - VM_MemberReference methRef = VM_MemberReference.findOrCreate(eTref, VM_Atom.findOrCreateAsciiAtom("<init>"), - VM_Atom.findOrCreateAsciiAtom("(ILorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;)V")); - VM_Method method = ((VM_MethodReference)methRef).resolveInvokeSpecial(); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL((VM_MethodReference)methRef, method); - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace;") - ); - OPT_Operand psRef = gc.makeLocal(1,psTref); OPT_Instruction c = Call.create(CALL, null, null, null, null, 3); + OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(badInstrKlassInitMethod.getMemberRef().asMethodReference(), + badInstrKlassInitMethod); Call.setParam(c, 0, eRef.copy()); // 'this' pointer in BadInstructionException.init Call.setParam(c, 1, new OPT_IntConstantOperand(pc)); Call.setParam(c, 2, psRef); Call.setGuard(c, new OPT_TrueGuardOperand()); Call.setMethod(c, methOp); - Call.setAddress(c, new OPT_AddressConstantOperand(((VM_MethodReference)methRef).peekResolvedMethod().getOffset())); + Call.setAddress(c, new OPT_AddressConstantOperand(badInstrKlassInitMethod.getOffset())); c.position = gc.inlineSequence; - c.bcIndex = 21; + c.bcIndex = DBT_Trace.BAD_INSTRUCTION_INIT; OPT_Instruction t = Athrow.create(ATHROW, eRef.copyRO()); t.position = gc.inlineSequence; - t.bcIndex = 0; + t.bcIndex = DBT_Trace.BAD_INSTRUCTION_THROW; appendInstructionToCurrentBlock(n); @@ -1122,6 +1167,35 @@ } } + // -oO Trace helping methods Oo- + + /** + * Plant a record uncaught branch call. NB register state won't get resolved for call + * @param pc the address of the branch instruction + * @param destination the register operand holding the destination + * @param code a code that can be a hint of the branch type + */ + public void plantRecordUncaughtBranch(int pc, OPT_RegisterOperand destination, int code) { + // Is it sensible to record this information? + if((gc.options.getOptLevel() > 0) && (DBT_Options.plantUncaughtBranchWatcher)) { + // Plant call + OPT_Instruction s = Call.create(CALL, null, null, null, null, 4); + OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(recordUncaughtBranchMethod.getMemberRef().asMethodReference(), + recordUncaughtBranchMethod); + OPT_Operand psRef = gc.makeLocal(1,psTref); + Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer + Call.setParam(s, 1, new OPT_IntConstantOperand(pc)); // Address of branch instruction + Call.setParam(s, 2, destination); // Destination of branch value + Call.setParam(s, 3, new OPT_IntConstantOperand(code)); // Branch code value + Call.setGuard(s, new OPT_TrueGuardOperand()); + Call.setMethod(s, methOp); + Call.setAddress(s, new OPT_AddressConstantOperand(recordUncaughtBranchMethod.getOffset())); + s.position = gc.inlineSequence; + s.bcIndex = DBT_Trace.RECORD_BRANCH; + appendInstructionToCurrentBlock(s); + } + } + // -oO Temporaries used during translation Oo- /** @@ -1274,8 +1348,8 @@ /** * Get the method */ - public VM_Method getMethod() { - return gc.method; + public DBT_Trace getMethod() { + return (DBT_Trace)gc.method; } /** * Make a temporary register Modified: src/org/binarytranslator/generic/decoder/Laziness.java =================================================================== --- src/org/binarytranslator/generic/decoder/Laziness.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/generic/decoder/Laziness.java 2007-03-24 23:14:38 UTC (rev 10) @@ -20,6 +20,12 @@ * elimination will suffice. */ public abstract class Laziness { + /** + * A Key class used when making a key from the laziness and PC + * value combined + */ + public static class Key {} + /** * Constructor */ @@ -35,7 +41,7 @@ * Given the current program position make a key object that will * allow */ - public abstract Object makeKey(int pc); + public abstract Key makeKey(int pc); /** * Create a copy of this lazy state - usually to record where one Modified: src/org/binarytranslator/generic/memory/ByteAddressedByteSwapMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/ByteAddressedByteSwapMemory.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/generic/memory/ByteAddressedByteSwapMemory.java 2007-03-24 23:14:38 UTC (rev 10) @@ -35,7 +35,7 @@ * Constructor - used when this is the instatiated class */ public ByteAddressedByteSwapMemory() { - super("org/binarytranslator/generic/memory/ByteAddressedByteSwapMemory"); + super(ByteAddressedByteSwapMemory.class); } /** * Perform a 16bit load where the sign extended result fills the Modified: src/org/binarytranslator/generic/memory/ByteAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-03-24 23:14:38 UTC (rev 10) @@ -63,17 +63,17 @@ * Constructor - used when this is the instatiated class */ public ByteAddressedMemory() { - super("org/binarytranslator/generic/memory/ByteAddressedMemory"); + super(ByteAddressedMemory.class); readableMemory = new byte[NUM_PAGES][]; writableMemory = new byte[NUM_PAGES][]; executableMemory = new byte[NUM_PAGES][]; } /** * Constructor - used when deriving a class - * @param className the name of the over-riding class + * @param classType the name of the over-riding class */ - protected ByteAddressedMemory(String className) { - super(className); + protected ByteAddressedMemory(Class classType) { + super(classType); readableMemory = new byte[NUM_PAGES][]; writableMemory = new byte[NUM_PAGES][]; executableMemory = new byte[NUM_PAGES][]; Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-03-24 23:14:38 UTC (rev 10) @@ -29,6 +29,8 @@ import org.jikesrvm.opt.ir.OPT_RegisterOperand; import org.jikesrvm.opt.ir.OPT_TrueGuardOperand; import org.binarytranslator.vmInterface.TranslationHelper; +import org.binarytranslator.vmInterface.DBT_Trace; +import org.binarytranslator.generic.os.process.ProcessSpace; /** * CallBasedMemory abstraction: @@ -37,23 +39,59 @@ * which are still abstract, ie there's no memory backing store yet */ public abstract class CallBasedMemory extends Memory implements OPT_Operators { + /** - * The name of the class we are to plant calls to + * The process space type reference */ - private final VM_Atom memoryClassName; + private static final VM_TypeReference psTref; /** - * The name of the store methods + * Field reference to ps.memory */ - private final VM_Atom store8, store16, store32; + private static final VM_FieldReference psMemoryRef; + + static { + psTref = VM_TypeReference.findOrCreate(ProcessSpace.class); + psMemoryRef = VM_MemberReference.findOrCreate(psTref, + VM_Atom.findOrCreateAsciiAtom("memory"), + VM_Atom.findOrCreateAsciiAtom + ("Lorg/binarytranslator/generic/memory/Memory;") + ).asFieldReference(); + } /** - * The name of the load methods + * The store 8 method */ - private final VM_Atom loadS8, loadU8, loadS16, loadU16, load32; + private final VM_Method store8; /** - * Descriptors for the methods + * The store 16 method */ - private final VM_Atom storeDescriptor, loadDescriptor; + private final VM_Method store16; /** + * The store 32 method + */ + private final VM_Method store32; + + /** + * The load signed 8 method + */ + private final VM_Method loadS8; + /** + * The load unsigned 8 method + */ + private final VM_Method loadU8; + /** + * The load signed 8 method + */ + private final VM_Method loadS16; + /** + * The load unsigned 8 method + */ + private final VM_Method loadU16; + /** + * The load 32 method + */ + private final VM_Method load32; + + /** * Type of underlying memory */ final VM_TypeReference memoryType; @@ -74,20 +112,44 @@ * Constructor * @param className the name of the over-riding class */ - protected CallBasedMemory(String className) { - this.memoryClassName = VM_Atom.findOrCreateAsciiAtom("L"+className+";"); - store8 = VM_Atom.findOrCreateAsciiAtom("store8"); - store16 = VM_Atom.findOrCreateAsciiAtom("store16"); - store32 = VM_Atom.findOrCreateAsciiAtom("store32"); - storeDescriptor = VM_Atom.findOrCreateAsciiAtom("(II)V"); - loadS8 = VM_Atom.findOrCreateAsciiAtom("loadSigned8"); - loadU8 = VM_Atom.findOrCreateAsciiAtom("loadUnsigned8"); - loadS16 = VM_Atom.findOrCreateAsciiAtom("loadSigned16"); - loadU16 = VM_Atom.findOrCreateAsciiAtom("loadUnsigned16"); - load32 = VM_Atom.findOrCreateAsciiAtom("load32"); - loadDescriptor = VM_Atom.findOrCreateAsciiAtom("(I)I"); - memoryType = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - memoryClassName); + protected CallBasedMemory(Class memoryClass) { + memoryType = VM_TypeReference.findOrCreate(memoryClass); + + VM_Atom storeDescriptor = VM_Atom.findOrCreateAsciiAtom("(II)V"); + store8 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("store8"), + storeDescriptor + ).asMethodReference().resolve(); + store16 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("store16"), + storeDescriptor + ).asMethodReference().resolve(); + store32 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("store32"), + storeDescriptor + ).asMethodReference().resolve(); + + VM_Atom loadDescriptor = VM_Atom.findOrCreateAsciiAtom("(I)I"); + loadS8 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("loadSigned8"), + loadDescriptor + ).asMethodReference().resolve(); + loadU8 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("loadUnsigned8"), + loadDescriptor + ).asMethodReference().resolve(); + loadS16 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("loadSigned16"), + loadDescriptor + ).asMethodReference().resolve(); + loadU16 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("loadUnsigned16"), + loadDescriptor + ).asMethodReference().resolve(); + load32 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("load32"), + loadDescriptor + ).asMethodReference().resolve(); } /** * Generate memory prologue,... for the beignning of a @@ -96,55 +158,35 @@ public void initTranslate(TranslationHelper helper) { this.helper = helper; this.gc = helper.getGenerationContext(); - VM_TypeReference psTref = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/generic/os/process/ProcessSpace;") - ); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref, VM_Atom.findOrCreateAsciiAtom("memory"), - VM_Atom.findOrCreateAsciiAtom - ("Lorg/binarytranslator/generic/memory/Memory;") - ).asFieldReference(); OPT_RegisterOperand memoryOp = helper.makeTemp(memoryType); helper.appendInstructionToCurrentBlock(GetField.create(GETFIELD, memoryOp, gc.makeLocal(1,psTref), - new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), - new OPT_LocationOperand(ref), + new OPT_AddressConstantOperand(psMemoryRef.peekResolvedField().getOffset()), + new OPT_LocationOperand(psMemoryRef), new OPT_TrueGuardOperand())); memory = memoryOp.register; } /** * Generate the IR code for the specified load - * @param loadType the atom name of the type of load + * @param loadMethod the load method to create * @param bcIndex the bytecode index in * DummyDynamicCodeRunner.invokeCode of this method call - required * for lazy method resolution. * @param dest the register to hold the result * @param addr the address of the value to load */ - private void translateLoad(VM_Atom loadType, int bcIndex, OPT_RegisterOperand addr, OPT_RegisterOperand dest) { + private void translateLoad(VM_Method loadMethod, int bcIndex, OPT_RegisterOperand addr, OPT_RegisterOperand dest) { OPT_Instruction s = Call.create(CALL, dest, null, null, null, - 2); - VM_MemberReference methRef = VM_MemberReference.findOrCreate(memoryType, - loadType, - loadDescriptor - ); - boolean unresolved = methRef.needsDynamicLink(helper.getMethod()); - VM_Method method = ((VM_MethodReference)methRef).resolveInvokeSpecial(); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL((VM_MethodReference)methRef, method); + 2); + VM_MethodReference loadMethRef = loadMethod.getMemberRef().asMethodReference(); + + OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(loadMethRef, loadMethod); OPT_RegisterOperand memoryOp = new OPT_RegisterOperand(memory, memoryType); Call.setParam(s, 0, memoryOp); // Sets 'this' pointer Call.setParam(s, 1, addr); Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); - if (unresolved) { - OPT_RegisterOperand offsetrop = gc.temps.makeTempOffset(); - helper.appendInstructionToCurrentBlock(Unary.create(RESOLVE_MEMBER, offsetrop, - Call.getMethod(s).copy())); - Call.setAddress(s, offsetrop.copyRO()); - } - else { - Call.setAddress(s, new OPT_AddressConstantOperand - (((VM_MethodReference)methRef).peekResolvedMethod().getOffset())); - } + Call.setAddress(s, new OPT_AddressConstantOperand(loadMethod.getOffset())); s.position = gc.inlineSequence; s.bcIndex = bcIndex; helper.appendInstructionToCurrentBlock(s); @@ -156,7 +198,7 @@ * @param addr the address of the value to load */ public void translateLoadSigned8(OPT_RegisterOperand addr, OPT_RegisterOperand dest) { - translateLoad(loadS8, 56, addr, dest); + translateLoad(loadS8, DBT_Trace.MEMORY_LOAD8, addr, dest); } /** * Generate the IR code for a byte load where the zero extended @@ -165,7 +207,7 @@ * @param addr the address of the value to load */ public void translateLoadUnsigned8(OPT_RegisterOperand addr, OPT_RegisterOperand dest) { - translateLoad(loadU8, 65, addr, dest); + translateLoad(loadU8, DBT_Trace.MEMORY_ULOAD8, addr, dest); } /** * Generate the IR code for a 16bit load where the sign extended @@ -174,7 +216,7 @@ * @param addr the address of the value to load */ public void translateLoadSigned16(OPT_RegisterOperand addr, OPT_RegisterOperand dest) { - translateLoad(loadS16, 74, addr, dest); + translateLoad(loadS16, DBT_Trace.MEMORY_LOAD16, addr, dest); } /** * Generate the IR code for a 16bit load where the zero extended @@ -183,7 +225,7 @@ * @param addr the address of the value to load */ public void translateLoadUnsigned16(OPT_RegisterOperand addr, OPT_RegisterOperand dest) { - translateLoad(loadU16, 83, addr, dest); + translateLoad(loadU16, DBT_Trace.MEMORY_ULOAD16, addr, dest); } /** * Generate the IR code for a 32bit load @@ -191,7 +233,7 @@ * @param addr the address of the value to load */ public void translateLoad32(OPT_RegisterOperand addr, OPT_RegisterOperand dest) { - translateLoad(load32, 92, addr, dest); + translateLoad(load32, DBT_Trace.MEMORY_LOAD32, addr, dest); } /** * Generate the IR code for a 16bit load where the sign extended @@ -200,7 +242,7 @@ * @param addr the address of the value to load */ protected void translateCallBasedLoadSigned16(OPT_RegisterOperand addr, OPT_RegisterOperand dest) { - translateLoad(loadS16, 74, addr, dest); + translateLoad(loadS16, DBT_Trace.MEMORY_LOAD16, addr, dest); } /** * Generate the IR code for a 16bit load where the zero extended @@ -209,7 +251,7 @@ * @param addr the address of the value to load */ protected void translateCallBasedLoadUnsigned16(OPT_RegisterOperand addr, OPT_RegisterOperand dest) { - translateLoad(loadU16, 83, addr, dest); + translateLoad(loadU16, DBT_Trace.MEMORY_ULOAD16, addr, dest); } /** * Generate the IR code for a 32bit load @@ -217,42 +259,28 @@ * @param addr the address of the value to load */ protected void translateCallBasedLoad32(OPT_RegisterOperand addr, OPT_RegisterOperand dest) { - translateLoad(load32, 92, addr, dest); + translateLoad(load32, DBT_Trace.MEMORY_LOAD32, addr, dest); } /** * Generate the IR code for the specified store - * @param storeType the atom name of the type of store + * @param storeMethod the store method to call * @param bcIndex the bytecode index in * DummyDynamicCodeRunner.invokeCode of this method call - required * for lazy method resolution. * @param src the register that holds the value to store * @param addr the address of the value to store */ - private void translateStore(VM_Atom storeType, int bcIndex, OPT_RegisterOperand addr, OPT_RegisterOperand src) { + private void translateStore(VM_Method storeMethod, int bcIndex, OPT_RegisterOperand addr, OPT_RegisterOperand src) { OPT_Instruction s = Call.create(CALL, null, null, null, null, 3); - VM_MemberReference methRef = VM_MemberReference.findOrCreate(memoryType, - storeType, - storeDescriptor - ); - boolean unresolved = methRef.needsDynamicLink(helper.getMethod()); - VM_Method method = ((VM_MethodReference)methRef).resolveInvokeSpecial(); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL((VM_MethodReference)methRef, method); + VM_MethodReference storeMethRef = storeMethod.getMemberRef().asMethodReference(); + OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(storeMethRef, storeMethod); OPT_RegisterOperand memoryOp = new OPT_RegisterOperand(memory, memoryType); Call.setParam(s, 0, memoryOp); // Sets 'this' pointer Call.setParam(s, 1, addr); Call.setParam(s, 2, src); Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); - if (unresolved) { - OPT_RegisterOperand offsetrop = gc.temps.makeTempOffset(); - helper.appendInstructionToCurrentBlock(Unary.create(RESOLVE_MEMBER, offsetrop, - Call.getMethod(s).copy())); - Call.setAddress(s, offsetrop.copyRO()); - } - else { - Call.setAddress(s, new OPT_AddressConstantOperand - (((VM_MethodReference)methRef).peekResolvedMethod().getOffset())); - } + Call.setAddress(s, new OPT_AddressConstantOperand(storeMethod.getOffset())); s.position = gc.inlineSequence; s.bcIndex = bcIndex; helper.appendInstructionToCurrentBlock(s); @@ -263,7 +291,7 @@ * @param addr the address of the value to store */ public void translateStore8(OPT_RegisterOperand addr, OPT_RegisterOperand src) { - translateStore(store8, 30, addr, src); + translateStore(store8, DBT_Trace.MEMORY_STORE8, addr, src); } /** * Generate the IR code for a 16bit store @@ -271,7 +299,7 @@ * @param addr the address of the value to store */ public void translateStore16(OPT_RegisterOperand addr, OPT_RegisterOperand src) { - translateStore(store16, 39, addr, src); + translateStore(store16, DBT_Trace.MEMORY_STORE16, addr, src); } /** * Generate the IR code for a 32bit store @@ -279,7 +307,7 @@ * @param addr the address of the value to store */ public void translateStore32(OPT_RegisterOperand addr, OPT_RegisterOperand src) { - translateStore(store32, 48, addr, src); + translateStore(store32, DBT_Trace.MEMORY_STORE32, addr, src); } /** * Generate the IR code for a byte store @@ -287,7 +315,7 @@ * @param addr the address of the value to store */ public void translateCallBasedStore8(OPT_RegisterOperand addr, OPT_RegisterOperand src) { - translateStore(store8, 30, addr, src); + translateStore(store8, DBT_Trace.MEMORY_STORE8, addr, src); } /** * Generate the IR code for a 16bit store @@ -295,7 +323,7 @@ * @param addr the address of the value to store */ public void translateCallBasedStore16(OPT_RegisterOperand addr, OPT_RegisterOperand src) { - translateStore(store16, 39, addr, src); + translateStore(store16, DBT_Trace.MEMORY_STORE16, addr, src); } /** * Generate the IR code for a 32bit store @@ -303,6 +331,32 @@ * @param addr the address of the value to store */ public void translateCallBasedStore32(OPT_RegisterOperand addr, OPT_RegisterOperand src) { - translateStore(store32, 48, addr, src); + translateStore(store32, DBT_Trace.MEMORY_STORE32, addr, src); } + /** + * Get method reference if linking a call + * @param callAddress the address associated with this call + */ + public VM_MethodReference getMethodRef(int callAddress) { + switch (callAddress) { + case DBT_Trace.MEMORY_STORE8: + return store8.getMemberRef().asMethodReference(); + case DBT_Trace.MEMORY_STORE16: + return store16.getMemberRef().asMethodReference(); + case DBT_Trace.MEMORY_STORE32: + return store32.getMemberRef().asMethodReference(); + case DBT_Trace.MEMORY_LOAD8: + return loadS8.getMemberRef().asMethodReference(); + case DBT_Trace.MEMORY_ULOAD8: + return loadU8.getMemberRef().asMethodReference(); + case DBT_Trace.MEMORY_LOAD16: + return loadS16.getMemberRef().asMethodReference(); + case DBT_Trace.MEMORY_ULOAD16: + return loadU16.getMemberRef().asMethodReference(); + case DBT_Trace.MEMORY_LOAD32: + return load32.getMemberRef().asMethodReference(); + default: + throw new Error("Error linking method at " + callAddress + " for memory model " + this.getClass()); + } + } } Modified: src/org/binarytranslator/generic/memory/IntAddressedByteSwapMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedByteSwapMemory.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/generic/memory/IntAddressedByteSwapMemory.java 2007-03-24 23:14:38 UTC (rev 10) @@ -31,7 +31,7 @@ * Constructor - used when this is the instatiated class */ public IntAddressedByteSwapMemory() { - super("org/binarytranslator/IntAddressedByteSwapMemory"); + super(IntAddressedByteSwapMemory.class); } /** * Perform a 16bit load where the sign extended result fills the Modified: src/org/binarytranslator/generic/memory/IntAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-03-24 23:14:38 UTC (rev 10) @@ -58,17 +58,17 @@ * Constructor - used when this is the instatiated class */ public IntAddressedMemory() { - super("org/binarytranslator/IntAddressedMemory"); + super(IntAddressedMemory.class); readableMemory = new int[NUM_PAGES][]; writableMemory = new int[NUM_PAGES][]; executableMemory = new int[NUM_PAGES][]; } /** * Constructor - used when deriving a class - * @param className the name of the over-riding class + * @param classType the type of the over-riding class */ - protected IntAddressedMemory(String className) { - super(className); + protected IntAddressedMemory(Class classType) { + super(classType); readableMemory = new int[NUM_PAGES][]; writableMemory = new int[NUM_PAGES][]; executableMemory = new int[NUM_PAGES][]; Modified: src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java 2007-03-24 23:14:38 UTC (rev 10) @@ -54,13 +54,13 @@ * Constructor */ public IntAddressedPreSwappedMemory() { - super("org/binarytranslator/IntAddressedPreSwappedMemory"); + super(IntAddressedPreSwappedMemory.class); } /** * Constructor */ - protected IntAddressedPreSwappedMemory(String className) { - super(className); + protected IntAddressedPreSwappedMemory(Class classType) { + super(classType); } /** * Read an int from RandomAccessFile ensuring that a byte swap is performed Modified: src/org/binarytranslator/generic/memory/IntAddressedReversedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedReversedMemory.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/generic/memory/IntAddressedReversedMemory.java 2007-03-24 23:14:38 UTC (rev 10) @@ -33,7 +33,7 @@ * Constructor */ public IntAddressedReversedMemory() { - super("org/binarytranslator/IntAddressedReversedMemory"); + super(IntAddressedReversedMemory.class); } /** * Return the offset part of the address Modified: src/org/binarytranslator/generic/memory/Memory.java =================================================================== --- src/org/binarytranslator/generic/memory/Memory.java 2007-03-21 15:20:26 UTC (rev 9) +++ src/org/binarytranslator/generic/memory/Memory.java 2007-03-24 23:14:38 UTC (rev 10) @@ -9,6 +9,7 @@ package org.binarytranslator.generic.memory; import org.jikesrvm.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.classloader.VM_MethodReference; import org.binarytranslator.vmInterface.TranslationHelper; import java.io.RandomAccessFile; @@ -182,4 +183,11 @@ * @param addr the address of the value to store */ public abstract void translateStore32(OPT_RegisterOperand addr, OPT_RegisterOperand src); + /** + * Get method reference if linking a call + * @param callAddress the address associated with this call + *... [truncated message content] |
From: <mic...@us...> - 2007-03-29 13:54:53
|
Revision: 14 http://svn.sourceforge.net/pearcolator/?rev=14&view=rev Author: michael_baer Date: 2007-03-29 06:53:07 -0700 (Thu, 29 Mar 2007) Log Message: ----------- Loading ARM ELF binaries Modified Paths: -------------- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/generic/os/loader/Loader.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/arch/arm/ src/org/binarytranslator/arch/arm/os/ src/org/binarytranslator/arch/arm/os/abi/ src/org/binarytranslator/arch/arm/os/abi/linux/ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java src/org/binarytranslator/arch/arm/os/process/ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/linux/ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java Added: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-03-29 13:53:07 UTC (rev 14) @@ -0,0 +1,23 @@ +package org.binarytranslator.arch.arm.os.abi.linux; + +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; + +public class ARM_LinuxSystemCalls extends LinuxSystemCalls { + + public ARM_LinuxSystemCalls(LinuxSystemCallGenerator src) { + super(src); + } + + @Override + protected String getMachine() { + //TODO: Grab this from a real machine + return "ARM"; + } + + @Override + public String sysCallToString(int syscall) { + throw new RuntimeException("Not yet implemented."); + } + +} Added: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) @@ -0,0 +1,158 @@ +package org.binarytranslator.arch.arm.os.process; + +import java.io.IOException; +import org.jikesrvm.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.opt.ir.OPT_GenerationContext; +import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; +import org.binarytranslator.arch.x86.decoder.X862IR; +import org.binarytranslator.arch.x86.os.process.X86_Registers; +import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; +import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.memory.ByteAddressedMemory; +import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.process.ProcessSpace; + +public abstract class ARM_ProcessSpace extends ProcessSpace { + + /* + * Instance data + */ + + /** + * Registers used by this process + */ + public ARM_Registers registers; + + /* GDB Interface */ + /** + * Read a register and turn into a byte array conforming to the endianness of + * the architecture + */ + public byte[] readRegisterGDB(int regNum) { + throw new RuntimeException("Not yet implemented"); + } + + /** + * Has frame base register? + */ + public boolean hasFrameBaseRegister() { + throw new RuntimeException("Not yet implemented"); + } + + /** + * Get the value of the frame base register + */ + public int getGDBFrameBaseRegister() { + throw new RuntimeException("Not yet implemented"); + } + + /** + * Get the value of the frame base register + */ + public int getGDBStackPointerRegister() { + throw new RuntimeException("Not yet implemented"); + } + + /** + * Get the value of the frame base register + */ + public int getGDBProgramCountRegister() { + throw new RuntimeException("Not yet implemented"); + } + + /* + * Utility functions + */ + + /** + * Debug information + * + * @param s + * string of debug information + */ + private static void report(String s) { + if (DBT_Options.debugLoader) { + System.out.print("ARM ProcessSpace:"); + System.out.println(s); + } + } + + /* + * Methods + */ + + /** + * Constructor + */ + protected ARM_ProcessSpace() { + registers = new ARM_Registers(); + memory = new ByteAddressedMemory(); + } + + /** + * Create an optimizing compiler HIR code generator suitable for this + * architecture + * + * @param context + * the generation context for the HIR generation + * @return a HIR generator + */ + public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { + throw new RuntimeException("Not yet implemented"); + } + + /** + * Given an ELF binary loader, create the appropriate process space + * + * @param elf + * the elf binary loader + * @return the appropriate process space + */ + public static ProcessSpace createProcessSpaceFromBinary(Loader loader) + throws IOException { + if (loader.isARM_ABI()) { + report("ARM ABI"); + return new ARM_LinuxProcessSpace(); + } else { + throw new UnsupportedOperationException("Binary of " + loader.getABIString() + + " ABI is unsupported for the ARM architecture"); + } + } + + /** + * Run a single instruction + */ + public void runOneInstruction() throws BadInstructionException { + // TODO + throw new RuntimeException("Not yet implemented"); + } + + /** + * Return as an integer the current instruction's address + */ + public int getCurrentInstructionAddress() { + return registers.getPC(); + } + + /** + * Sets the current instruction's address + */ + public void setCurrentInstructionAddress(int pc) { + registers.setPC(pc); + } + + /** + * Return as an integer the current instruction's address + */ + public int getCurrentStackAddress() { + throw new RuntimeException("Not yet implemented"); + } + + /** + * Turn the process space into a string (for debug) + */ + public String toString() { + return registers.toString(); + } +} Added: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-03-29 13:53:07 UTC (rev 14) @@ -0,0 +1,108 @@ +package org.binarytranslator.arch.arm.os.process; + +public final class ARM_Registers { + + /** + * The currently visible ARM general purpose registers. Register 15 also serves as the PC. + */ + private int regs[] = new int[16]; + + /** + * The ARM features a number of shadow registers, that are mapped into the register map + * depending on the operating mode. It contains + * 8 registers for fast IRQ handlers + * 3 registers for SWI handlers + * 3 registers for abort handlers + * 3 registers for irq handlers + * 3 registers for undefined instruction handlers + * 8 registers for temporarely storing the user mode registers during non-user modes + */ + private int shadowRegisters[] = new int[28]; + + /** + * The negative flag from the CPSR. + */ + private boolean flagNegative = false; + + /** + * The zero flag from the CPSR. + */ + private boolean flagZero = false; + + /** + * The carry flag from the CPSR. + */ + private boolean flagCarry = false; + + /** + * The overflow flag from the CPSR. + */ + private boolean flagOverflow = false; + + /** + * This flag from the CPSR denotes whether IRQs are currently accepted by the processor. + */ + private boolean flagIRQsDisabled = false; + + /** + * This flag from the CPSR denotes whether FIQs are currently accepted by the processor. + */ + private boolean flagFIQsDisabled = false; + + /** + * The operating mode from the CPSR register. Note that only the bottom five bits of this + * register may ever be set. + */ + private byte operatingMode = OPERATING_MODE_SVC; + + /** + * Definition of symbolic constants for all valid operating modes + */ + public final static byte OPERATING_MODE_USER = 0x10; + public final static byte OPERATING_MODE_FIQ = 0x11; + public final static byte OPERATING_MODE_IRQ = 0x12; + public final static byte OPERATING_MODE_SVC = 0x13; + public final static byte OPERATING_MODE_ABT = 0x17; + public final static byte OPERATING_MODE_UND = 0x1A; + + public ARM_Registers() { + } + + /** + * Sets the pc to a new value + */ + public void setPC(int pc) { + regs[15] = pc; + } + + /** + * Sets the pc to a new value + */ + public int getPC() { + return regs[15]; + } + + /** + * Returns the content of ARM's Current Program Status Register. + * @return + */ + public int getCPSR() { + return (flagNegative ? 1 << 31 : 0) | + (flagZero ? 1 << 30 : 0) | + (flagCarry ? 1 << 29 : 0) | + (flagOverflow ? 1 << 28 : 0) | + (flagIRQsDisabled ? 1 << 7 : 0) | + (flagFIQsDisabled ? 1 << 6 : 0) | + operatingMode; + } + + /** + * Restores the processor state to the state saved within the given CPSR. + * @param cpsr + * ARM CPSR register content + */ + private void setFlagsFromCPSR(int cpsr) { + throw new RuntimeException("Not yet implemented."); + } + +} Added: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) @@ -0,0 +1,91 @@ +package org.binarytranslator.arch.arm.os.process.linux; + +import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.os.abi.linux.ARM_LinuxSystemCalls; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.generic.os.abi.linux.LinuxStackInitializer; +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; +import org.binarytranslator.generic.os.loader.Loader; + +public class ARM_LinuxProcessSpace extends ARM_ProcessSpace implements LinuxSystemCallGenerator { + + /** + * A link to the current system call interface + */ + private final LinuxSystemCalls sysCalls; + + /** + * The top of the stack + */ + private static final int STACK_TOP = 0xC0000000; + + /** + * The top of the bss segment + */ + private int brk; + + public ARM_LinuxProcessSpace() { + sysCalls = new ARM_LinuxSystemCalls(this); + } + + @Override + public void doSysCall() { + sysCalls.doSysCall(); + } + + @Override + public void initialise(Loader loader, int pc, int brk, String[] args) { + registers.setPC(pc); + this.brk = brk; + + //initialize the stack + int[] auxVector = {LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, 0xffffe400, + LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO_EHDR, 0xffffe000, + LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x78bfbff, + LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 0x1000, + LinuxStackInitializer.AuxiliaryVectorType.AT_CLKTCK, 0x64, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, 0xBADADD8E, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, 0xBAD2BAD2, + LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, + LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, + LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, pc, + + LinuxStackInitializer.AuxiliaryVectorType.AT_UID, DBT_Options.UID, + LinuxStackInitializer.AuxiliaryVectorType.AT_EUID, DBT_Options.UID, + LinuxStackInitializer.AuxiliaryVectorType.AT_GID, DBT_Options.GID, + LinuxStackInitializer.AuxiliaryVectorType.AT_EGID, DBT_Options.GID, + + LinuxStackInitializer.AuxiliaryVectorType.AT_SECURE, 0, + LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0}; + + LinuxStackInitializer.stackInit(memory, STACK_TOP, args, getEnvironmentVariables(), auxVector); + } + + public int getBrk() { + return brk; + } + + public int[] getSysCallArguments(int n) { + // TODO Auto-generated method stub + return null; + } + + public int getSysCallNumber() { + // TODO Auto-generated method stub + return 0; + } + + public void setBrk(int address) { + brk = address; + } + + public void setSysCallError(int r) { + // TODO Auto-generated method stub + } + + public void setSysCallReturn(int r) { + // TODO Auto-generated method stub + } + +} Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-03-28 13:09:58 UTC (rev 13) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-03-29 13:53:07 UTC (rev 14) @@ -4623,6 +4623,7 @@ * Also modifies XER[CA]. */ protected int translateXO_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int rD, int rA, int rB, int OE, int secondaryOpcode, int Rc) { + if (VM.VerifyAssertions) VM._assert(rB == 0); // Get rA & rD OPT_RegisterOperand reg_rA = ppc2ir.getGPRegister(rA); Modified: src/org/binarytranslator/generic/os/loader/Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/Loader.java 2007-03-28 13:09:58 UTC (rev 13) +++ src/org/binarytranslator/generic/os/loader/Loader.java 2007-03-29 13:53:07 UTC (rev 14) @@ -65,6 +65,11 @@ * Is the binary for the Power PC ISA? */ abstract public boolean isPPC_ISA(); + + /** + * Is the binary for the ARM ISA? + */ + abstract public boolean isARM_ISA(); /** * Does this file support the SysV ABI? @@ -75,6 +80,11 @@ * Does this file support the Linux ABI? */ abstract public boolean isLinuxABI(); + + /** + * Does this file support the ARM ABI? + */ + abstract public boolean isARM_ABI(); /* * Static methods Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-03-28 13:09:58 UTC (rev 13) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-03-29 13:53:07 UTC (rev 14) @@ -192,6 +192,13 @@ public boolean isPPC_ISA() { return elfHeader.isPPC_ISA(); } + + /** + * Is this binary for the ARM architecture? + */ + public boolean isARM_ISA() { + return elfHeader.isARM_ISA(); + } /** * Does this file support the SysV ABI? @@ -205,6 +212,14 @@ public boolean isLinuxABI() { return elfHeader.isLinuxABI(); } + + /** + * Does this file support the ARM ABI? + * @return + */ + public boolean isARM_ABI() { + return elfHeader.isARM_ABI(); + } /* * Local classes holding structures from the ELF file @@ -341,7 +356,13 @@ * Hewlett-Packard Non-Stop Kernel */ private static final byte ELFOSABI_NSK = 14; + /** + * ARM ABI, probably using the ARM AAPCS. + */ + private static final byte ELFOSABI_ARM = 97; + + /** * Return the application binary interface (ABI) supported by this file */ String getABIString() { @@ -359,6 +380,7 @@ case ELFOSABI_OPENBSD: return "OpenBSD"; case ELFOSABI_OPENVMS: return "OpenVMS"; case ELFOSABI_NSK: return "Hewlett-Packard Non-Stop Kernel"; + case ELFOSABI_ARM: return "ARM ABI"; default: return "Unknown ELF ABI: " + e_ident[EI_OSABI]; } @@ -375,6 +397,11 @@ boolean isLinuxABI() { return e_ident[EI_OSABI] == ELFOSABI_LINUX; } + + boolean isARM_ABI() { + return e_ident[EI_OSABI] == ELFOSABI_ARM; + } + /** * Location of OS ABI version data */ @@ -424,6 +451,13 @@ boolean isLinuxABI() { return identity.isLinuxABI(); } + + /** + * Does this file support the ARM ABI? + */ + boolean isARM_ABI() { + return identity.isARM_ABI(); + } /** * Object file type @@ -537,6 +571,13 @@ } /** + * Is the elf binary for an ARM architecture? + */ + boolean isARM_ISA() { + return e_machine == EM_ARM; + } + + /** * Return the architecture (ISA) supported by this file */ public String getArchitectureString() { Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-28 13:09:58 UTC (rev 13) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) @@ -26,436 +26,488 @@ import org.binarytranslator.generic.gdbstub.GDBStub; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; /** - * A process space encapsulates a running process. This superclass - * contains non operating and architecture specific details of the - * process. + * A process space encapsulates a running process. This superclass contains non + * operating and architecture specific details of the process. */ public abstract class ProcessSpace { /* - * Runtime information - */ + * Runtime information + */ /** - * A record of branches to guide translation - */ + * A record of branches to guide translation + */ public final BranchLogic branchInfo; /** - * A hashtable containing translated traces of code - */ + * A hashtable containing translated traces of code + */ protected final Hashtable codeHash = new Hashtable(); /** - * Has a system call been called to terminate the process - */ + * Has a system call been called to terminate the process + */ public boolean finished = false; /* - * Interface to memory - */ + * Interface to memory + */ /** - * The memory for the process. As this is user mode code, it is a - * virtual address space - */ + * The memory for the process. As this is user mode code, it is a virtual + * address space + */ public Memory memory; /** - * Load a 32bit value from memory - */ + * Load a 32bit value from memory + */ public int memoryLoad32(int wordAddr) { - return memory.load32(wordAddr); + return memory.load32(wordAddr); } + /** - * Store a 32bit value to memory - */ + * Store a 32bit value to memory + */ public void memoryStore32(int address, int data) { - memory.store32(address,data); + memory.store32(address, data); } - + /** - * Load a 16bit value from memory - */ + * Load a 16bit value from memory + */ public int memoryLoad16(int hwAddr) { - return memory.loadSigned16(hwAddr); + return memory.loadSigned16(hwAddr); } + /** - * Store a 16bit value to memory - */ + * Store a 16bit value to memory + */ public void memoryStore16(int hwAddr, int iValue) { - memory.store16(hwAddr,iValue); + memory.store16(hwAddr, iValue); } /** - * Load a 8bit value from memory - */ + * Load a 8bit value from memory + */ public byte memoryLoad8(int address) { - return (byte)memory.loadSigned8(address); + return (byte) memory.loadSigned8(address); } + /** - * Store a 8bit value to memory - */ + * Store a 8bit value to memory + */ public void memoryStore8(int address, byte data) { - memory.store8(address, data); + memory.store8(address, data); } /** - * Read an ASCIIZ string from the process' memory into a Java String - */ + * Read an ASCIIZ string from the process' memory into a Java String + */ public String memoryReadString(int address) { - StringBuffer str = new StringBuffer(); - char c; - - while( (c = (char)memoryLoad8(address++)) != 0 ) - str.append(c); - - return str.toString(); + StringBuffer str = new StringBuffer(); + char c; + + while ((c = (char) memoryLoad8(address++)) != 0) + str.append(c); + + return str.toString(); } /** - * Write a Java string (crudely) to an ASCIIZ string in the process' - * memory - */ + * Write a Java string (crudely) to an ASCIIZ string in the process' memory + */ public void memoryWriteString(int byteAddr, String value) { - if (value != null) { - for(int i=0; i < value.length(); i++) { - memoryStore8(byteAddr+i, (byte)value.charAt(i)); - } - memoryStore8(byteAddr+value.length(), (byte)0); - } + if (value != null) { + for (int i = 0; i < value.length(); i++) { + memoryStore8(byteAddr + i, (byte) value.charAt(i)); + } + memoryStore8(byteAddr + value.length(), (byte) 0); + } } /** * Map an anonymous page of memory - * @param addr the address to map or NULL if don't care - * @param len the amount of memory to map - * @param read is the page readable - * @param write is the page writable - * @param exec is the page executable + * + * @param addr + * the address to map or NULL if don't care + * @param len + * the amount of memory to map + * @param read + * is the page readable + * @param write + * is the page writable + * @param exec + * is the page executable */ - public int memoryMap(int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException - { - return memory.map(addr, len, read, write, exec); + public int memoryMap(int addr, int len, boolean read, boolean write, + boolean exec) throws MemoryMapException { + return memory.map(addr, len, read, write, exec); } /** - * Simulate an munmap system call. - * @param start start of memory area to unmap. - * @param length length of area. - */ - public int munmap(int start, int length) - { - memory.unmap(start,length); - return 0; + * Simulate an munmap system call. + * + * @param start + * start of memory area to unmap. + * @param length + * length of area. + */ + public int munmap(int start, int length) { + memory.unmap(start, length); + return 0; } /* - * Utility functions - */ + * Utility functions + */ /** - * Debug information - * @param s string of debug information - */ - private static void report(String s){ - if (DBT_Options.debugLoader) { - System.out.print("ProcessSpace:"); - System.out.println(s); - } + * Debug information + * + * @param s + * string of debug information + */ + private static void report(String s) { + if (DBT_Options.debugLoader) { + System.out.print("ProcessSpace:"); + System.out.println(s); + } } /* - * Methods - */ + * Methods + */ /** - * Create an optimizing compiler HIR code generator suitable for a - * particular architecture - * @param context the generation context for the HIR generation - * @return a HIR generator - */ - public abstract OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context); + * Create an optimizing compiler HIR code generator suitable for a particular + * architecture + * + * @param context + * the generation context for the HIR generation + * @return a HIR generator + */ + public abstract OPT_HIRGenerator createHIRGenerator( + OPT_GenerationContext context); /** - * Given an ELF binary loader, create the appropriate process space - * @param elf the elf binary loader - * @return the appropriate process space - */ - public static ProcessSpace createProcessSpaceFromBinary (Loader loader) throws IOException { - ProcessSpace result; - if (loader.isX86_ISA()) { - report("X86 ELF Binary"); - result = X86_ProcessSpace.createProcessSpaceFromBinary(loader); - } - else if(loader.isPPC_ISA()){ - report("PPC ELF Binary"); - result = PPC_ProcessSpace.createProcessSpaceFromBinary(loader); - } - else { - throw new IOException("Binary of " + loader.getArchitectureString() + " architecture is unsupported"); - } - return result; + * Given an ELF binary loader, create the appropriate process space + * + * @param elf + * the elf binary loader + * @return the appropriate process space + */ + public static ProcessSpace createProcessSpaceFromBinary(Loader loader) + throws IOException { + ProcessSpace result; + if (loader.isX86_ISA()) { + report("X86 ELF Binary"); + result = X86_ProcessSpace.createProcessSpaceFromBinary(loader); + } else if (loader.isPPC_ISA()) { + report("PPC ELF Binary"); + result = PPC_ProcessSpace.createProcessSpaceFromBinary(loader); + } else if (loader.isARM_ISA()) { + report("ARM ELF Binary"); + result = ARM_ProcessSpace.createProcessSpaceFromBinary(loader); + } else { + throw new UnsupportedOperationException("Binary of " + loader.getArchitectureString() + + " architecture is unsupported"); + } + return result; } + /** - * Create a segment - * @param RandomAccessFile file to read segment data from if file size != 0 - * @param offset file offset - * @param address location of segment - * @param filesize size of segment in file - * @param memsize size of segment in memory - * @param read is segment readable - * @param write is segment writable - * @param exec is segment executable - */ - public void createSegment(RandomAccessFile file, - long offset, - int address, - int filesize, - int memsize, - boolean read, - boolean write, - boolean exec) throws MemoryMapException { - // Sanity check - if (memsize < filesize) { - throw new Error("Segment memory size (" + memsize + ")less than file size (" + filesize + ")"); - } - // Are we mapping anything from a file? - if(filesize == 0) { - // No: map anonymously - memory.map(address, memsize, read, write, exec); - } - else { - // align offset and address - int alignedAddress; - long alignedOffset; - int alignedFilesize; - if (memory.isPageAligned(address)) { - // memory and therefore offset should be aligned - alignedAddress = address; - alignedOffset = offset; - alignedFilesize = filesize; - } - else { - // Address not aligned - alignedAddress = memory.truncateToPage(address); - int delta = address - alignedAddress; - // adjust offset and length too - alignedOffset = offset - delta; - alignedFilesize = filesize + delta; - } - memory.map(file, alignedOffset, alignedAddress, alignedFilesize, read, write, exec); - // Do we need to map in some blank pages at the end of the segment? - if (filesize < memsize) { - alignedAddress = memory.truncateToNextPage(address + filesize); - memory.map(alignedAddress, memsize-filesize, read, write, exec); - } - } + * Create a segment + * + * @param RandomAccessFile + * file to read segment data from if file size != 0 + * @param offset + * file offset + * @param address + * location of segment + * @param filesize + * size of segment in file + * @param memsize + * size of segment in memory + * @param read + * is segment readable + * @param write + * is segment writable + * @param exec + * is segment executable + */ + public void createSegment(RandomAccessFile file, long offset, int address, + int filesize, int memsize, boolean read, boolean write, boolean exec) + throws MemoryMapException { + // Sanity check + if (memsize < filesize) { + throw new Error("Segment memory size (" + memsize + + ")less than file size (" + filesize + ")"); + } + // Are we mapping anything from a file? + if (filesize == 0) { + // No: map anonymously + memory.map(address, memsize, read, write, exec); + } else { + // align offset and address + int alignedAddress; + long alignedOffset; + int alignedFilesize; + if (memory.isPageAligned(address)) { + // memory and therefore offset should be aligned + alignedAddress = address; + alignedOffset = offset; + alignedFilesize = filesize; + } else { + // Address not aligned + alignedAddress = memory.truncateToPage(address); + int delta = address - alignedAddress; + // adjust offset and length too + alignedOffset = offset - delta; + alignedFilesize = filesize + delta; + } + memory.map(file, alignedOffset, alignedAddress, alignedFilesize, read, + write, exec); + // Do we need to map in some blank pages at the end of the segment? + if (filesize < memsize) { + alignedAddress = memory.truncateToNextPage(address + filesize); + memory.map(alignedAddress, memsize - filesize, read, write, exec); + } + } } /** - * Initialise the process space - * @param loader the loader that's created the process space - * @param pc the entry point - * @param brk the initial value for the top of BSS - * @param args command line arguments - */ + * Initialise the process space + * + * @param loader + * the loader that's created the process space + * @param pc + * the entry point + * @param brk + * the initial value for the top of BSS + * @param args + * command line arguments + */ public abstract void initialise(Loader loader, int pc, int brk, String args[]); /** - * Constructor - */ + * Constructor + */ protected ProcessSpace() { - branchInfo = new BranchLogic(); + branchInfo = new BranchLogic(); } /** - * Constructor - */ + * Constructor + */ public ProcessSpace(String[] args) throws IOException { - branchInfo = new BranchLogic(); + branchInfo = new BranchLogic(); } - /** - * Replace the compiled code for a trace (called by the adaptive - * system) - */ - public synchronized void replaceCompiledTrace(VM_CompiledMethod cm, DBT_Trace trace) { - VM_CodeArray code = cm.getEntryCodeArray(); - codeHash.put(trace.pc, code); + * Replace the compiled code for a trace (called by the adaptive system) + */ + public synchronized void replaceCompiledTrace(VM_CompiledMethod cm, + DBT_Trace trace) { + VM_CodeArray code = cm.getEntryCodeArray(); + codeHash.put(trace.pc, code); } - public synchronized VM_CodeArray getCodeForPC(int pc) { - VM_CodeArray code = (VM_CodeArray)codeHash.get(pc); - if(code == null) { - code = translateCode(new DBT_Trace(this, pc)); - } - return code; + VM_CodeArray code = (VM_CodeArray) codeHash.get(pc); + if (code == null) { + code = translateCode(new DBT_Trace(this, pc)); + } + return code; } - + private VM_CodeArray translateCode(DBT_Trace trace) { - if (DBT_Options.debugRuntime) { - report("Translating code for 0x" + Integer.toHexString(trace.pc)); - } - trace.compile(); - VM_CompiledMethod cm = trace.getCurrentCompiledMethod(); - replaceCompiledTrace(cm, trace); - return cm.getEntryCodeArray(); + if (DBT_Options.debugRuntime) { + report("Translating code for 0x" + Integer.toHexString(trace.pc)); + } + trace.compile(); + VM_CompiledMethod cm = trace.getCurrentCompiledMethod(); + replaceCompiledTrace(cm, trace); + return cm.getEntryCodeArray(); } /** * Record a branch instruction */ - public void recordUncaughtBranch(int location, int destination, int code) { - branchInfo.registerBranch(location, destination, code); + public void recordUncaughtBranch(int location, int destination, int code) { + branchInfo.registerBranch(location, destination, code); } /** - * Return as an integer the current instruction's address - */ + * Return as an integer the current instruction's address + */ public abstract int getCurrentInstructionAddress(); + /** - * Sets the current instruction's address - */ + * Sets the current instruction's address + */ public abstract void setCurrentInstructionAddress(int pc); + /** - * Return as an integer the current instruction's address - */ + * Return as an integer the current instruction's address + */ public abstract int getCurrentStackAddress(); + /** - * Print the stack - * @param words how many words to print from the stack - */ + * Print the stack + * + * @param words + * how many words to print from the stack + */ public void dumpStack(int words) { - int stackPtr = getCurrentStackAddress(); - for(int i=0; i < words; i++) { - if((i % 4) == 0) { - if(i != 0) { - System.out.println(); - } - System.out.print("0x" + Integer.toHexString(stackPtr)+":"); - } - String hexValue = Integer.toHexString(memory.load32(stackPtr)); - System.out.print(" 0x"); - for(int j=0; j < (8-hexValue.length()); j++) { - System.out.print("0"); - } - System.out.print(hexValue); - stackPtr+=4; - } - System.out.println(); + int stackPtr = getCurrentStackAddress(); + for (int i = 0; i < words; i++) { + if ((i % 4) == 0) { + if (i != 0) { + System.out.println(); + } + System.out.print("0x" + Integer.toHexString(stackPtr) + ":"); + } + String hexValue = Integer.toHexString(memory.load32(stackPtr)); + System.out.print(" 0x"); + for (int j = 0; j < (8 - hexValue.length()); j++) { + System.out.print("0"); + } + System.out.print(hexValue); + stackPtr += 4; + } + System.out.println(); } + /** - * Runtime loop, goes through the binary and looks in the Hashtable - * codeHash to see if we have already translated/compiled this piece - * of code, if not it is compiled. The compiled code is then run. + * Runtime loop, goes through the binary and looks in the Hashtable codeHash + * to see if we have already translated/compiled this piece of code, if not it + * is compiled. The compiled code is then run. */ public void run() { if (DBT_Options.debugRuntime) { System.out.println("Main: run"); } - - // The current block of compiled code. - VM_CodeArray code; - if(DBT_Options.debugPS) { + // The current block of compiled code. + VM_CodeArray code; + + if (DBT_Options.debugPS) { System.out.println("***** INITIAL PROCESS SPACE *****\n" + this); - System.out.println(this); - //dumpStack(20); + System.out.println(this); + // dumpStack(20); } - if(DBT_Options.gdbStub == false) { - try { - // interpretFrom(); // Interpreter - experimental - while(finished == false) { - // Get the compiled code - code = getCodeForPC(getCurrentInstructionAddress()); - // Run the compiled code. - setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, this)); - } - } - catch(BadInstructionException e) { - System.out.println(e.toString()); - } - } - else { - GDBStub gdbStub = new GDBStub(DBT_Options.gdbStubPort, this); - gdbStub.run(); - } + if (DBT_Options.gdbStub == false) { + try { + // interpretFrom(); // Interpreter - experimental + while (finished == false) { + // Get the compiled code + code = getCodeForPC(getCurrentInstructionAddress()); + // Run the compiled code. + setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, this)); + } + } catch (BadInstructionException e) { + System.out.println(e.toString()); + } + } else { + GDBStub gdbStub = new GDBStub(DBT_Options.gdbStubPort, this); + gdbStub.run(); + } } /** - * Entry point for system calls - */ + * Entry point for system calls + */ public abstract void doSysCall(); - private static final String[] env = {"HOSTNAME=softwood", "PVM_RSH=/usr/bin/rsh", - "HOST_JAVA_HOME=/home/amulocal/linux/appl/j2sdk1.4.2", "SHELL=/bin/bash", - "TERM=xterm", "HISTSIZE=1000", "SSH_CLIENT=130.88.194.110 8380 22", - "CVSROOT=/home/simgroup/cvsroot", "QTDIR=/usr/lib/qt-3.1", "SSH_TTY=/dev/pts/0", - "RVM_HOST_CONFIG=/home/matleyr/cvs/rvm/config/i686-pc-linux-gnu.ManCS", - "USER=matleyr", "LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:", "XENVIRONMENT=/home/matleyr/.Xdefaults", - "PVM_ROOT=/usr/share/pvm3", "CLASSPATH_ROOT=/home/matleyr/cvs/classpath", - "PATH=/home/matleyr/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/opt/lib/j2re1.3.1/bin:/home/matleyr/cvs/rvm/bin:/home/matleyr/bin", "MAIL=/var/spool/mail/matleyr", - "_=/bin/bash", "PWD=/home/matleyr/dhry", "INPUTRC=/etc/inputrc", - "LANG=en_GB.iso88591", "LAMHELPFILE=/etc/lam/lam-helpfile", - "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass", - "CSHOME=ma...@an...:/home/M03/cc/matleyr", "HOME=/home/matleyr", - "SHLVL=1", "SIM=/home/simgroup/matleyr", "XPVM_ROOT=/usr/share/pvm3/xpvm", - "RVM_ROOT=/home/matleyr/cvs", "LOGNAME=matleyr", "PRINTER=happy_duplex", - "SSH_CONNECTION=130.88.194.110 2380 130.88.198.215 22", - "LESSOPEN=|/usr/bin/lesspipe.sh %s", "RVM_BUILD=/tmp/RVMbuild", - "DISPLAY=localhost:10.0", - "RVM_TARGET_CONFIG=/home/matleyr/cvs/rvm/config/i686-pc-linux-gnu.ManCS", - "G_BROKEN_FILENAMES=1"}; + private static final String[] env = { + "HOSTNAME=softwood", + "PVM_RSH=/usr/bin/rsh", + "HOST_JAVA_HOME=/home/amulocal/linux/appl/j2sdk1.4.2", + "SHELL=/bin/bash", + "TERM=xterm", + "HISTSIZE=1000", + "SSH_CLIENT=130.88.194.110 8380 22", + "CVSROOT=/home/simgroup/cvsroot", + "QTDIR=/usr/lib/qt-3.1", + "SSH_TTY=/dev/pts/0", + "RVM_HOST_CONFIG=/home/matleyr/cvs/rvm/config/i686-pc-linux-gnu.ManCS", + "USER=matleyr", + "LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:", + "XENVIRONMENT=/home/matleyr/.Xdefaults", + "PVM_ROOT=/usr/share/pvm3", + "CLASSPATH_ROOT=/home/matleyr/cvs/classpath", + "PATH=/home/matleyr/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/opt/lib/j2re1.3.1/bin:/home/matleyr/cvs/rvm/bin:/home/matleyr/bin", + "MAIL=/var/spool/mail/matleyr", "_=/bin/bash", "PWD=/home/matleyr/dhry", + "INPUTRC=/etc/inputrc", "LANG=en_GB.iso88591", + "LAMHELPFILE=/etc/lam/lam-helpfile", + "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass", + "CSHOME=ma...@an...:/home/M03/cc/matleyr", + "HOME=/home/matleyr", "SHLVL=1", "SIM=/home/simgroup/matleyr", + "XPVM_ROOT=/usr/share/pvm3/xpvm", "RVM_ROOT=/home/matleyr/cvs", + "LOGNAME=matleyr", "PRINTER=happy_duplex", + "SSH_CONNECTION=130.88.194.110 2380 130.88.198.215 22", + "LESSOPEN=|/usr/bin/lesspipe.sh %s", "RVM_BUILD=/tmp/RVMbuild", + "DISPLAY=localhost:10.0", + "RVM_TARGET_CONFIG=/home/matleyr/cvs/rvm/config/i686-pc-linux-gnu.ManCS", + "G_BROKEN_FILENAMES=1" }; + /** - * Method to return environment variables - * @return an array of environment variable strings - */ + * Method to return environment variables + * + * @return an array of environment variable strings + */ protected String[] getEnvironmentVariables() { - /* Environment variables, exactly as on softwood. Not that the number 8380 in SSH_* varies. */ - return env; - /* - if (!DBT_Options.loadEnv) { - Process printenv = Runtime.exec("/usr/bin/printenv"); - InputStream variables = new DataInputStream(printenv.getInputStream()); - variables.readUTF(); - } - */ + /* + * Environment variables, exactly as on softwood. Not that the number 8380 + * in SSH_* varies. + */ + return env; + /* + * if (!DBT_Options.loadEnv) { Process printenv = + * Runtime.exec("/usr/bin/printenv"); InputStream variables = new + * DataInputStream(printenv.getInputStream()); variables.readUTF(); } + */ } /* GDB stub interface */ /** - * Read a register and turn into a byte array conforming to the - * endianness of the architecture - */ + * Read a register and turn into a byte array conforming to the endianness of + * the architecture + */ public abstract byte[] readRegisterGDB(int regNum); + /** - * Run a single instruction - */ + * Run a single instruction + */ public abstract void runOneInstruction() throws BadInstructionException; + /** - * Has frame base register? - */ + * Has frame base register? + */ public boolean hasFrameBaseRegister() { - return false; + return false; } + /** - * Get the value of the frame base register - */ + * Get the value of the frame base register + */ public int getGDBFrameBaseRegister() { - return -1; + return -1; } + /** - * Get the value of the frame base register - */ + * Get the value of the frame base register + */ public abstract int getGDBStackPointerRegister(); + /** - * Get the value of the frame base register - */ + * Get the value of the frame base register + */ public abstract int getGDBProgramCountRegister(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-03-30 15:38:56
|
Revision: 15 http://svn.sourceforge.net/pearcolator/?rev=15&view=rev Author: michael_baer Date: 2007-03-30 08:38:52 -0700 (Fri, 30 Mar 2007) Log Message: ----------- Introduced various refactorings Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/gdbstub/GDBStub.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/loader/Loader.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java src/org/binarytranslator/generic/gdbstub/GDBTarget.java src/org/binarytranslator/generic/os/loader/image/ src/org/binarytranslator/generic/os/loader/image/ImageLoader.java Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -4,6 +4,7 @@ import org.jikesrvm.opt.ir.OPT_HIRGenerator; import org.jikesrvm.opt.ir.OPT_GenerationContext; import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.os.process.image.ARM_SimpleProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; import org.binarytranslator.arch.x86.os.process.X86_Registers; @@ -24,43 +25,6 @@ */ public ARM_Registers registers; - /* GDB Interface */ - /** - * Read a register and turn into a byte array conforming to the endianness of - * the architecture - */ - public byte[] readRegisterGDB(int regNum) { - throw new RuntimeException("Not yet implemented"); - } - - /** - * Has frame base register? - */ - public boolean hasFrameBaseRegister() { - throw new RuntimeException("Not yet implemented"); - } - - /** - * Get the value of the frame base register - */ - public int getGDBFrameBaseRegister() { - throw new RuntimeException("Not yet implemented"); - } - - /** - * Get the value of the frame base register - */ - public int getGDBStackPointerRegister() { - throw new RuntimeException("Not yet implemented"); - } - - /** - * Get the value of the frame base register - */ - public int getGDBProgramCountRegister() { - throw new RuntimeException("Not yet implemented"); - } - /* * Utility functions */ @@ -99,6 +63,7 @@ * @return a HIR generator */ public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { + System.out.println("Executing instr: " + memory.load32(0)); throw new RuntimeException("Not yet implemented"); } @@ -111,12 +76,12 @@ */ public static ProcessSpace createProcessSpaceFromBinary(Loader loader) throws IOException { - if (loader.isARM_ABI()) { + if (loader.isARM_ABI() || loader.isSysV_ABI()) { report("ARM ABI"); return new ARM_LinuxProcessSpace(); } else { - throw new UnsupportedOperationException("Binary of " + loader.getABIString() - + " ABI is unsupported for the ARM architecture"); + report("Creating simple ARM process space."); + return new ARM_SimpleProcessSpace(); } } @@ -132,21 +97,21 @@ * Return as an integer the current instruction's address */ public int getCurrentInstructionAddress() { - return registers.getPC(); + return registers.read(ARM_Registers.PC); } /** * Sets the current instruction's address */ public void setCurrentInstructionAddress(int pc) { - registers.setPC(pc); + registers.write(ARM_Registers.PC, pc); } /** * Return as an integer the current instruction's address */ public int getCurrentStackAddress() { - throw new RuntimeException("Not yet implemented"); + return registers.read(14); } /** Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-03-30 15:38:52 UTC (rev 15) @@ -1,7 +1,12 @@ package org.binarytranslator.arch.arm.os.process; +import org.jikesrvm.VM; + public final class ARM_Registers { + public final static int SP = 14; + public final static int PC = 15; + /** * The currently visible ARM general purpose registers. Register 15 also serves as the PC. */ @@ -58,7 +63,7 @@ /** * Definition of symbolic constants for all valid operating modes */ - public final static byte OPERATING_MODE_USER = 0x10; + public final static byte OPERATING_MODE_USR = 0x10; public final static byte OPERATING_MODE_FIQ = 0x11; public final static byte OPERATING_MODE_IRQ = 0x12; public final static byte OPERATING_MODE_SVC = 0x13; @@ -68,18 +73,16 @@ public ARM_Registers() { } - /** - * Sets the pc to a new value - */ - public void setPC(int pc) { - regs[15] = pc; + public int read(int reg) { + if (VM.VerifyAssertions) VM._assert(reg < 16); + + return regs[reg]; } - /** - * Sets the pc to a new value - */ - public int getPC() { - return regs[15]; + public void write(int reg, int value) { + if (VM.VerifyAssertions) VM._assert(reg < 16); + + regs[reg] = value; } /** Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -3,6 +3,8 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.os.abi.linux.ARM_LinuxSystemCalls; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.generic.os.abi.linux.LinuxStackInitializer; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; @@ -16,6 +18,11 @@ private final LinuxSystemCalls sysCalls; /** + * A re-used iterator that allows enumerating the argument of the current system call + */ + private final ARM_SyscallArgumentIterator syscallArgs; + + /** * The top of the stack */ private static final int STACK_TOP = 0xC0000000; @@ -27,6 +34,7 @@ public ARM_LinuxProcessSpace() { sysCalls = new ARM_LinuxSystemCalls(this); + syscallArgs = new ARM_SyscallArgumentIterator(this); } @Override @@ -36,7 +44,7 @@ @Override public void initialise(Loader loader, int pc, int brk, String[] args) { - registers.setPC(pc); + registers.write(ARM_Registers.PC, pc); this.brk = brk; //initialize the stack @@ -66,15 +74,15 @@ return brk; } - public int[] getSysCallArguments(int n) { - // TODO Auto-generated method stub - return null; - } - public int getSysCallNumber() { // TODO Auto-generated method stub return 0; } + + public CallArgumentIterator getSysCallArguments() { + syscallArgs.reset(); + return syscallArgs; + } public void setBrk(int address) { brk = address; @@ -88,4 +96,10 @@ // TODO Auto-generated method stub } + @Override + public GDBTarget getGDBTarget() { + // TODO Auto-generated method stub + return null; + } + } Added: src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java 2007-03-30 15:38:52 UTC (rev 15) @@ -0,0 +1,35 @@ +package org.binarytranslator.arch.arm.os.process.linux; + +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; + +public class ARM_SyscallArgumentIterator implements LinuxSystemCallGenerator.CallArgumentIterator { + + private final ARM_LinuxProcessSpace ps; + private int currentArgument; + + public ARM_SyscallArgumentIterator(ARM_LinuxProcessSpace ps) { + this.ps = ps; + this.currentArgument = 0; + } + + public int nextInt() { + return ps.registers.read(currentArgument++); + } + + public long nextLong() { + // only start reading longs from even registers + if ((currentArgument & 1) == 1) + currentArgument++; + + //TODO: This code is actually assuming that we're on little endian + long lowWord = nextInt(); + long highWord = nextInt(); + + return highWord << 32 | lowWord; + } + + public void reset() { + currentArgument = 0; + } + +} Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -19,6 +19,7 @@ import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.vmInterface.*; import java.util.*; import java.io.*; @@ -26,7 +27,7 @@ /** * Capture the running of a PowerPC process */ -public abstract class PPC_ProcessSpace extends ProcessSpace +public abstract class PPC_ProcessSpace extends ProcessSpace implements GDBTarget { /* Here's what would be in the PowerPC's registers if the binary were running on a real PowerPC. For speed I am using individual Modified: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -11,6 +11,7 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; import org.binarytranslator.arch.ppc.os.abi.linux.PPC_LinuxSystemCalls; +import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.generic.os.abi.linux.LinuxStackInitializer; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; @@ -29,6 +30,11 @@ * System calls object for handling system calls generated by this process */ final LinuxSystemCalls syscalls; + + /** + * Provides access to the single arguments of a system call. + */ + final PPC_LinuxSyscallArgumentIterator syscallArgs; /** * The top of the bss segment @@ -45,6 +51,7 @@ */ public PPC_LinuxProcessSpace(Loader loader) { syscalls = new PPC_LinuxSystemCalls(this); + syscallArgs = new PPC_LinuxSyscallArgumentIterator(this); } /** @@ -114,15 +121,12 @@ } /** * Create an array of arguments for the system call - * @param n number of system call arguments to read * @return array of system call argument values */ - public int[] getSysCallArguments(int n) { - int args[] = new int[n]; - for (int i=0; i < n; i++) { - args[i] = getRegister(3+i); - } - return args; + public CallArgumentIterator getSysCallArguments() { + + syscallArgs.reset(); + return syscallArgs; } /** @@ -158,4 +162,16 @@ brk = address; } + public GDBTarget getGDBTarget() { + return this; + } + + public int getGDBFrameBaseRegister() { + return -1; + } + + public boolean hasFrameBaseRegister() { + return false; + } + } Added: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java (rev 0) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java 2007-03-30 15:38:52 UTC (rev 15) @@ -0,0 +1,54 @@ +package org.binarytranslator.arch.ppc.os.process.linux; + +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; + +final class PPC_LinuxSyscallArgumentIterator implements LinuxSystemCallGenerator.CallArgumentIterator { + + /** + * That process space that this class is enumerating the arguments from. + */ + private final PPC_LinuxProcessSpace ps; + + /** + * The index of the argument that is fetched by the next call to next<datatype>() + */ + private int nextArgument; + + public PPC_LinuxSyscallArgumentIterator(PPC_LinuxProcessSpace ps) { + this.ps = ps; + this.nextArgument = 0; + } + + /** + * Return the next integer argument by reading it from a register, starting with GPR3. + */ + public int nextInt() { + return ps.getRegister(3 + nextArgument++); + } + + /** + * Returns the next long argument. + * This implementation follows the information on p. 3-19f of http://refspecs.freestandards.org/elf/elfspec_ppc.pdf + */ + public long nextLong() { + + //Start reading long arguments only from uneven registers + if ((nextArgument & 1) == 0) { + nextArgument++; + } + + long lowWord = nextInt(); + long highWord = nextInt(); + + return highWord << 32 | lowWord; + } + + /** + * We're actually reusing that class instead of initializing a new one each time syscall arguments are inspected. + * Therefore, this function starts iterating over all arguments anew. + */ + public void reset() { + nextArgument = 0; + } + +} Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -17,6 +17,7 @@ import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.memory.ByteAddressedMemory; import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; import org.binarytranslator.generic.os.loader.Loader; @@ -24,7 +25,7 @@ /** * Encapsulate the parts of an X86 process that are common across operating systems */ -public abstract class X86_ProcessSpace extends ProcessSpace { +public abstract class X86_ProcessSpace extends ProcessSpace implements GDBTarget { /* * Process defaults @@ -104,6 +105,10 @@ public int getGDBProgramCountRegister() { return 8; } + + public GDBTarget getGDBTarget() { + return this; + } /* * Utility functions @@ -161,7 +166,7 @@ * Run a single instruction */ public void runOneInstruction() throws BadInstructionException { - // TODO + throw new UnsupportedOperationException("To be implemented"); } /** Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -12,6 +12,7 @@ import org.binarytranslator.generic.os.abi.linux.LinuxStackInitializer; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator.CallArgumentIterator; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; import org.binarytranslator.arch.x86.os.abi.linux.X86_LinuxSystemCalls; @@ -25,6 +26,11 @@ * System calls object for handling system calls generated by this process */ LinuxSystemCalls syscalls; + + /** + * Allows uniform access to the arguments of a system call. We cache this object for reuse. + */ + private final X86_LinuxSyscallArgumentIterator syscallArgs; /** * The top of the bss segment @@ -41,6 +47,7 @@ */ public X86_LinuxProcessSpace(Loader loader) { syscalls = new X86_LinuxSystemCalls(this); + syscallArgs = new X86_LinuxSyscallArgumentIterator(this); } /** @@ -97,22 +104,12 @@ return registers.readGP32(X86_Registers.EAX); } - public int[] getSysCallArguments(int n) { - int[] args = new int[n]; - if (n <= 6) { - int[] order = {X86_Registers.EBX, X86_Registers.ECX, X86_Registers.EDX, X86_Registers.ESI, X86_Registers.EDI, X86_Registers.EBP}; - - for (int i = 0; i < n; i++) { - args[i] = registers.readGP32(order[i]); - } - } else { - throw new Error("We should check this"); -// for (int i = 0; i < n; i++) { -// args[i] = memory.load32(registers.readGP32(X86_Registers.EBX) + (i * 4)); -// } - } - - return args; + /** + * Returns an interface to read the arguments of a system call. + */ + public CallArgumentIterator getSysCallArguments() { + syscallArgs.reset(); + return syscallArgs; } public void setSysCallReturn(int r) { Added: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java (rev 0) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java 2007-03-30 15:38:52 UTC (rev 15) @@ -0,0 +1,37 @@ +package org.binarytranslator.arch.x86.os.process.linux; + +import org.binarytranslator.arch.x86.os.process.X86_Registers; +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; +import org.jikesrvm.VM; + +public class X86_LinuxSyscallArgumentIterator implements LinuxSystemCallGenerator.CallArgumentIterator { + + private final static int[] order = {X86_Registers.EBX, X86_Registers.ECX, X86_Registers.EDX, X86_Registers.ESI, X86_Registers.EDI, X86_Registers.EBP}; + + private final X86_LinuxProcessSpace ps; + private int nextParameter; + + public X86_LinuxSyscallArgumentIterator(X86_LinuxProcessSpace ps) { + this.ps = ps; + this.nextParameter = 0; + } + + public int nextInt() { + if (VM.VerifyAssertions) VM._assert(nextParameter <= 6); + + return ps.registers.readGP32(order[nextParameter++]); + } + + public long nextLong() { + throw new UnsupportedOperationException("X86 System Calls do not support long arguments, yet."); + } + + /** + * We're actually reusing that class instead of initializing a new one each time syscall arguments are inspected. + * Therefore, this function starts iterating over all arguments anew. + */ + public void reset() { + nextParameter = 0; + } + +} Modified: src/org/binarytranslator/generic/gdbstub/GDBStub.java =================================================================== --- src/org/binarytranslator/generic/gdbstub/GDBStub.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/gdbstub/GDBStub.java 2007-03-30 15:38:52 UTC (rev 15) @@ -40,7 +40,7 @@ /** * The process being debugged */ - private final ProcessSpace ps; + private final GDBTarget target; /** * Thread to continue or step, a value of -1 means all threads, 0 * means any thread. @@ -93,7 +93,7 @@ /** * Constructor */ - public GDBStub(int port, ProcessSpace ps) { + public GDBStub(int port, GDBTarget target) { try { ServerSocket connectionSocket = new ServerSocket(port); socket = connectionSocket.accept(); @@ -105,7 +105,7 @@ throw new Error("Error opening socket", e); } breakpoints = new int[0]; - this.ps = ps; + this.target = target; } /** @@ -228,14 +228,14 @@ // byte command[] = {'S','0','5'}; <- a command to just say stopped by SIGTRAP byte command[]; int index; - if (ps.hasFrameBaseRegister()) { + if (target.hasFrameBaseRegister()) { // Add base pointer to packet command = new byte[39]; - int bpReg = ps.getGDBFrameBaseRegister(); + int bpReg = target.getGDBFrameBaseRegister(); command[3] = intToHex(bpReg >> 4); command[4] = intToHex(bpReg); command[5] = ':'; - byte bpVal[] = ps.readRegisterGDB(bpReg); + byte bpVal[] = target.readRegisterGDB(bpReg); command[6] = intToHex(bpVal[0] >> 4); command[7] = intToHex(bpVal[0]); command[8] = intToHex(bpVal[1] >> 4); @@ -254,11 +254,11 @@ command[1] = '0'; command[2] = '5'; // stopped by trap { // Add stack pointer to packet - int spReg = ps.getGDBStackPointerRegister(); + int spReg = target.getGDBStackPointerRegister(); command[index] = intToHex(spReg >> 4); index++; command[index] = intToHex(spReg); index++; command[index] = ':'; index++; - byte spVal[] = ps.readRegisterGDB(spReg); + byte spVal[] = target.readRegisterGDB(spReg); command[index] = intToHex(spVal[0] >> 4); index++; command[index] = intToHex(spVal[0]); index++; command[index] = intToHex(spVal[1] >> 4); index++; @@ -270,11 +270,11 @@ command[index] = ';'; index++; } { // Add program counter to packet - int pcReg = ps.getGDBProgramCountRegister(); + int pcReg = target.getGDBProgramCountRegister(); command[index] = intToHex(pcReg >> 4); index++; command[index] = intToHex(pcReg); index++; command[index] = ':'; index++; - byte pcVal[] = ps.readRegisterGDB(pcReg); + byte pcVal[] = target.readRegisterGDB(pcReg); command[index] = intToHex(pcVal[0] >> 4); index++; command[index] = intToHex(pcVal[0]); index++; command[index] = intToHex(pcVal[1] >> 4); index++; @@ -357,7 +357,7 @@ } else { regNum = hexToInt(buffer[2]); } - byte value[] = ps.readRegisterGDB(regNum); + byte value[] = target.readRegisterGDB(regNum); byte hexValue[] = new byte[value.length * 2]; for(int i=0; i < value.length; i++) { hexValue[i*2] = intToHex(value[i] >> 4); @@ -378,7 +378,7 @@ try { byte value[] = new byte[count*2]; for(int i=0; i < count; i++) { - byte byteVal = ps.memoryLoad8(address+i); + byte byteVal = target.memoryLoad8(address+i); value[i*2] = intToHex(byteVal >> 4); value[(i*2)+1] = intToHex(byteVal); } @@ -401,7 +401,7 @@ byte value[] = new byte[2]; for(int i=0; i < count; i++) { byte byteVal = (byte)((hexToInt(buffer[start+(i*2)]) << 4) | (hexToInt(buffer[start+(i*2)+1]))); - ps.memoryStore8(address+i, byteVal); + target.memoryStore8(address+i, byteVal); } replyOK(); } catch (NullPointerException e) { @@ -444,7 +444,7 @@ // the next two optional characters specify the thread // to step, we have one thread so we ignore them try { - ps.runOneInstruction(); + target.runOneInstruction(); index = dataEnd; // report that a SIGTRAP halted the debugger sendStoppedByTrap(); @@ -461,9 +461,9 @@ try { boolean hitBreakpoint; do { - ps.runOneInstruction(); + target.runOneInstruction(); hitBreakpoint = false; - int pc = ps.getCurrentInstructionAddress(); + int pc = target.getCurrentInstructionAddress(); for(int i=0; i < breakpoints.length; i++) { if(pc == breakpoints[i]) { hitBreakpoint = true; Added: src/org/binarytranslator/generic/gdbstub/GDBTarget.java =================================================================== --- src/org/binarytranslator/generic/gdbstub/GDBTarget.java (rev 0) +++ src/org/binarytranslator/generic/gdbstub/GDBTarget.java 2007-03-30 15:38:52 UTC (rev 15) @@ -0,0 +1,53 @@ +package org.binarytranslator.generic.gdbstub; + +import org.binarytranslator.generic.fault.BadInstructionException; + +public interface GDBTarget { + /** + * Read a register from the target machine. + * + * @param regNum + * A register number, starting from 0. + */ + byte[] readRegisterGDB(int regNum); + + /** + * Run a single instruction + */ + void runOneInstruction() throws BadInstructionException; + + /** + * Has frame base register? + */ + boolean hasFrameBaseRegister(); + + /** + * Get the value of the frame base register + */ + int getGDBFrameBaseRegister(); + + /** + * Get the value of the frame base register + */ + int getGDBStackPointerRegister(); + + /** + * Get the value of the frame base register + */ + int getGDBProgramCountRegister(); + + /** + * Return the address of the current instruction. + */ + int getCurrentInstructionAddress(); + + /** + * Store the given bye of data at the given address within the process. + */ + void memoryStore8(int address, byte data); + + /** + * Load a byte from the given address within the process. + */ + byte memoryLoad8(int address); +} Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-03-30 15:38:52 UTC (rev 15) @@ -15,7 +15,23 @@ * the memory and registers of various architectures. */ public interface LinuxSystemCallGenerator { + /** + * This interface allows you to iteratively grab all arguments to a system call. + */ + public interface CallArgumentIterator { + /** + * Interpret the next system call argument as an integer and return it. + */ + int nextInt(); + + /** + * Interpret the next system call argument as a long and return it. + */ + long nextLong(); + } + + /** * Return the system call number from the generator */ public int getSysCallNumber(); @@ -24,7 +40,7 @@ * @param n number of system call arguments to read * @return array of system call argument values */ - public int[] getSysCallArguments(int n); + public CallArgumentIterator getSysCallArguments(); /** * Set the return value for a system call * @param r the return value Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-03-30 15:38:52 UTC (rev 15) @@ -445,6 +445,14 @@ */ public abstract void doSysCall(); } + + abstract class ParameterizedSystemCall extends SystemCall { + protected LinuxSystemCallGenerator.CallArgumentIterator arguments; + + public ParameterizedSystemCall() { + arguments = src.getSysCallArguments(); + } + } /** * Unknown System Call @@ -466,11 +474,9 @@ /** * Exit system call */ - public class SysExit extends SystemCall { + public class SysExit extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(1); - int status = args[0]; - + int status = arguments.nextInt(); System.exit(status); } } @@ -478,12 +484,11 @@ /** * Read from a file */ - public class SysRead extends SystemCall { + public class SysRead extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(3); - int fd = args[0]; - int buf = args[1]; - int count = args[2]; + int fd = arguments.nextInt(); + int buf = arguments.nextInt(); + int count = arguments.nextInt(); if(fd == 0) { // read from stdin byte[] b = new byte[256]; @@ -528,12 +533,11 @@ /** * Write to a file */ - public class SysWrite extends SystemCall { + public class SysWrite extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(3); - int fd = args[0]; - int buf = args[1]; - int count = args[2]; + int fd = arguments.nextInt(); + int buf = arguments.nextInt(); + int count = arguments.nextInt(); if(fd == 1) { // stdout for(int c = 0 ; c < count; c++) { @@ -579,12 +583,11 @@ /** * Write data into multiple buffers */ - public class SysWriteV extends SystemCall { - public void doSysCall() { - int[] args = src.getSysCallArguments(3); - int fd = args[0]; - int vector = args[1]; - int count = args[2]; + public class SysWriteV extends ParameterizedSystemCall { + public void doSysCall() { + int fd = arguments.nextInt(); + int vector = arguments.nextInt(); + int count = arguments.nextInt(); if((fd == 1)||(fd == 2)) { // stdout || stderr PrintStream out = (fd == 1) ? System.out : System.err; @@ -609,11 +612,10 @@ } } - public class SysOpen extends SystemCall { + public class SysOpen extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(2); - int pathname = args[0]; - int flags = args[1]; + int pathname = arguments.nextInt(); + int flags = arguments.nextInt(); // Examine the flags argument and open read or read-write // accordingly. args[0] points to the file name. @@ -660,10 +662,9 @@ } } - public class SysClose extends SystemCall { + public class SysClose extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(1); - int fd = args[0]; + int fd = arguments.nextInt(); RandomAccessFile raFile = getRAFile(fd); // Check that fd is a valid file descriptor if(raFile == null) { @@ -705,16 +706,17 @@ } } - public class SysBrk extends SystemCall { + public class SysBrk extends ParameterizedSystemCall { public void doSysCall() { - int args[] = src.getSysCallArguments(1); - if(args[0] == 0) { + int brk = arguments.nextInt(); + + if(brk == 0) { // Request for the current top of bss. src.setSysCallReturn(src.getBrk()); } else { // Changing the value. - src.setBrk(args[0]); + src.setBrk(brk); } } } @@ -724,13 +726,11 @@ } } - public class SysFcntl64 extends SystemCall { + public class SysFcntl64 extends ParameterizedSystemCall { public void doSysCall() { // This is complicated so fudge it for now. - int[] args = src.getSysCallArguments(2); - - int fd = args[0]; - int cmd = args[1]; + int fd = arguments.nextInt(); + int cmd = arguments.nextInt(); if( ((fd == 0) | (fd == 1) | (fd == 2)) & (cmd == 1) ) src.setSysCallReturn(0); @@ -739,11 +739,12 @@ } } - public class SysUname extends SystemCall { + public class SysUname extends ParameterizedSystemCall { public void doSysCall() { // Simple uname support - int[] args = src.getSysCallArguments(1); - if (args[0] != 0) { + int addr = arguments.nextInt(); + + if (addr != 0) { String localhostString, domainName, hostName; try { InetAddress localhost = InetAddress.getLocalHost(); @@ -762,12 +763,12 @@ hostName = localhostString.substring(0,index); } // Fill in utsname struct - see /usr/include/sys/utsname.h - src.memoryWriteString (args[0], getSysName()); // sysname - src.memoryWriteString (args[0]+65, hostName); // nodename - src.memoryWriteString (args[0]+130, getRelease()); // release - src.memoryWriteString (args[0]+195, getVersion()); // version - src.memoryWriteString (args[0]+260, getMachine()); // machine - src.memoryWriteString (args[0]+325, domainName); // __domainname + src.memoryWriteString (addr, getSysName()); // sysname + src.memoryWriteString (addr+65, hostName); // nodename + src.memoryWriteString (addr+130, getRelease()); // release + src.memoryWriteString (addr+195, getVersion()); // version + src.memoryWriteString (addr+260, getMachine()); // machine + src.memoryWriteString (addr+325, domainName); // __domainname src.setSysCallReturn(0); } else { @@ -777,15 +778,15 @@ } } - public class SysMmap extends SystemCall { + public class SysMmap extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(6); - int start = args[0]; - int length = args[1]; - int prot = args[2]; - int flags = args[3]; - int fd = args[4]; - int offset = args[5]; + + int start = arguments.nextInt(); + int length = arguments.nextInt(); + int prot = arguments.nextInt(); + int flags = arguments.nextInt(); + int fd = arguments.nextInt(); + int offset = arguments.nextInt(); if((flags & mman.MAP_ANONYMOUS) != 0 ) { try { src.setSysCallReturn(src.memoryMap(start, length, @@ -802,20 +803,20 @@ } } - public class SysMunmap extends SystemCall { + public class SysMunmap extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(2); - int start = args[0]; - int length = args[1]; + + int start = arguments.nextInt(); + int length = arguments.nextInt(); throw new Error("TODO!"); //src.setSysCallReturn(src.munmap(start, length)); } } - public class SysExitGroup extends SystemCall { + public class SysExitGroup extends ParameterizedSystemCall { public void doSysCall() { // For now, equivalent to SysExit - System.exit(src.getSysCallArguments(1)[0]); + System.exit(arguments.nextInt()); } } } Modified: src/org/binarytranslator/generic/os/loader/Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/Loader.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/os/loader/Loader.java 2007-03-30 15:38:52 UTC (rev 15) @@ -10,6 +10,7 @@ import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.os.loader.elf.ELF_Loader; +import org.binarytranslator.generic.os.loader.image.ImageLoader; import org.binarytranslator.DBT_Options; import java.io.*; @@ -97,30 +98,19 @@ * @return a binaryloader to create a process */ public static Loader getLoader(String filename) throws IOException - { - File file = new File(filename); - RandomAccessFile rFile = new RandomAccessFile(file, "r"); - report("Opened file: " + filename); - - byte[] id = new byte[4]; - rFile.read(id); - report("Read ID"); - - if (isELF_Binary(id)) { + { + if (ELF_Loader.conforms(filename)) { report("ELF object file found"); return new ELF_Loader(); - } else { + } + else if (ImageLoader.conforms(filename)) { + report("Image Loader file found."); + return new ImageLoader(); + } + else { throw new Error("File " + filename + " has an unrecognized binary format"); } } - /** - * Determine if the id array corresponds with the initial part of an - * ELF binary - * @param id start of binary - * @return whether this is an ELF binary - */ - private static boolean isELF_Binary(byte[] id) { - return (id[0] == 0x7f) && (id[1] == 'E') && (id[2] == 'L') && (id[3] == 'F'); - } + } Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-03-30 15:38:52 UTC (rev 15) @@ -121,9 +121,8 @@ */ public ProcessSpace readBinary(String[] args) throws IOException { - File elfFile = new File(args[0]); - RandomAccessFile rFile = new RandomAccessFile(elfFile, "r"); - report("Opened File: " + elfFile); + report("Opening File: " + args[0]); + RandomAccessFile rFile = new RandomAccessFile(args[0], "r"); elfHeader = new ELF_Header(rFile); //NB also sets up reader report("ELF header read successfully"); @@ -154,6 +153,35 @@ return ps; } + + /** + * Determine if the id array corresponds with the initial part of an + * ELF binary + * @param filename Name of the file to check + * @return whether this is an ELF binary + */ + public static boolean conforms(String filename) { + + RandomAccessFile rFile = null; + report("Testing is file is ELF: " + filename); + + try { + rFile = new RandomAccessFile(filename, "r"); + byte[] id = new byte[4]; + rFile.read(id); + + return (id[0] == 0x7f) && (id[1] == 'E') && (id[2] == 'L') && (id[3] == 'F'); + } + catch (Exception e) { + return false; + } + finally { + try { + rFile.close(); + } + catch(Exception e) {} + } + } /** * Read and construct the program segment headers Added: src/org/binarytranslator/generic/os/loader/image/ImageLoader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/image/ImageLoader.java (rev 0) +++ src/org/binarytranslator/generic/os/loader/image/ImageLoader.java 2007-03-30 15:38:52 UTC (rev 15) @@ -0,0 +1,156 @@ +package org.binarytranslator.generic.os.loader.image; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.io.UnsupportedEncodingException; + +import org.binarytranslator.DBT_Options; +import org.binarytranslator.generic.memory.MemoryMapException; +import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.process.ProcessSpace; + +/** + * A very simple loader, that will load binary directly into memory and then start executing it from address 0. + * Actually, this is just a hack to the .bin file format to include some header information that tells us the + * architecture for this image. + * The file format is: + * [Identifier] <8 ASCII-CHARS> EXT_IMG\0 + * [File Version] <1 BYTE> 0x0 + * [Architecture ID] <4 ASCII-CHARS> <ARM|PPC|X86> \0 + * [Padding] <3 BYTE> + * [Image data] <BINARY-Data> <Assembly Code, to be loaded at addr #0> + * @author baerm + * + */ +public class ImageLoader extends Loader { + + private String architecture; + + @Override + public String getABIString() { + return null; + } + + @Override + public String getArchitectureString() { + return architecture; + } + + @Override + public boolean isARM_ABI() { + return false; + } + + @Override + public boolean isARM_ISA() { + return architecture.equals("ARM"); + } + + @Override + public boolean isLinuxABI() { + return false; + } + + @Override + public boolean isPPC_ISA() { + return architecture.equals("ISA"); + } + + @Override + public boolean isSysV_ABI() { + return false; + } + + @Override + public boolean isX86_ISA() { + return architecture.equals("X86"); + } + + /** + * Read from the given file and determine whether it contains the correct ID string for an + * ASM Loader file. + */ + private static boolean readAndCheckID(RandomAccessFile file) { + try { + byte[] ID = new byte[8]; + if (file.read(ID) != ID.length) + return false; + + return ID[0] == 'E' && ID[1] == 'X' && ID[2] == 'T' && ID[3] == '_' + && ID[4] == 'I' && ID[5] == 'M' && ID[6] == 'G' && ID[7] == 0; + } + catch (Exception e) { + return false; + } + } + + public ProcessSpace readBinary(String[] args) throws IOException { + + report("Reading: " + args[0]); + RandomAccessFile file = new RandomAccessFile(args[0], "r"); + + if (!readAndCheckID(file)) + throw new IOException("File does not contain the expected EXT_IMG ID string."); + + //check the file version. Currently, we only support one version anyway. + byte version = file.readByte(); + + if (version != 0) { + throw new IOException("Unsupported image file version."); + } + + byte[] architecture = new byte[3]; + if (file.read(architecture) != architecture.length) + throw new IOException("Unable to read architecture string."); + + //read the architecture string + this.architecture = new String(architecture, "ASCII"); + + //skip the double-word padding and the delimiter of the architecture string + //file.skipBytes(4); + + ProcessSpace ps = ProcessSpace.createProcessSpaceFromBinary(this); + + int fileAndMemSize = (int)file.length() - 16; + try { + ps.createSegment(file, 16, 0, fileAndMemSize, fileAndMemSize, true, true, true); + } + catch (MemoryMapException e) { + e.printStackTrace(); + return null; + } + + ps.initialise(this, 0, -1, args); + return ps; + } + + /** + * Checks if the given file is an ASM Loader file. + */ + public static boolean conforms(String filename) { + + report("Testing if file conforms: " + filename); + RandomAccessFile file = null; + + try { + //if the file contains the correct ID string, then we assume it to be an ASM loader file + file = new RandomAccessFile(filename, "r"); + return readAndCheckID(file); + } + catch (Exception e) { + return false; + } + finally { + try { + file.close(); + } + catch (Exception e) {} + } + } + + private static void report(String s){ + if (DBT_Options.debugLoader) { + System.out.print("Image Loader:"); + System.out.println(s); + } + } +} Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -24,6 +24,7 @@ import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.gdbstub.GDBStub; +import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; @@ -191,8 +192,10 @@ * the generation context for the HIR generation * @return a HIR generator */ + public abstract OPT_HIRGenerator createHIRGenerator( - OPT_GenerationContext context); + OPT_GenerationContext context); + /** * Given an ELF binary loader, create the appropriate process space @@ -316,7 +319,7 @@ VM_CodeArray code = cm.getEntryCodeArray(); codeHash.put(trace.pc, code); } - + public synchronized VM_CodeArray getCodeForPC(int pc) { VM_CodeArray code = (VM_CodeArray) codeHash.get(pc); if (code == null) { @@ -324,7 +327,7 @@ } return code; } - + private VM_CodeArray translateCode(DBT_Trace trace) { if (DBT_Options.debugRuntime) { report("Translating code for 0x" + Integer.toHexString(trace.pc)); @@ -334,6 +337,8 @@ replaceCompiledTrace(cm, trace); return cm.getEntryCodeArray(); } + + /* /** * Record a branch instruction @@ -415,7 +420,7 @@ System.out.println(e.toString()); } } else { - GDBStub gdbStub = new GDBStub(DBT_Options.gdbStubPort, this); + GDBStub gdbStub = new GDBStub(DBT_Options.gdbStubPort, getGDBTarget()); gdbStub.run(); } } @@ -474,40 +479,9 @@ * DataInputStream(printenv.getInputStream()); variables.readUTF(); } */ } - - /* GDB stub interface */ + /** - * Read a register and turn into a byte array conforming to the endianness of - * the architecture + * Return an interface that allows GDB to read from this process */ - public abstract byte[] readRegisterGDB(int regNum); - - /** - * Run a single instruction - */ - public abstract void runOneInstruction() throws BadInstructionException; - - /** - * Has frame base register? - */ - public boolean hasFrameBaseRegister() { - return false; - } - - /** - * Get the value of the frame base register - */ - public int getGDBFrameBaseRegister() { - return -1; - } - - /** - * Get the value of the frame base register - */ - public abstract int getGDBStackPointerRegister(); - - /** - * Get the value of the frame base register - */ - public abstract int getGDBProgramCountRegister(); + public abstract GDBTarget getGDBTarget(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-03-31 14:04:41
|
Revision: 16 http://svn.sourceforge.net/pearcolator/?rev=16&view=rev Author: michael_baer Date: 2007-03-31 07:04:36 -0700 (Sat, 31 Mar 2007) Log Message: ----------- Added missing files for a working build Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/arch/arm/os/process/image/ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-03-31 14:04:36 UTC (rev 16) @@ -4,7 +4,7 @@ import org.jikesrvm.opt.ir.OPT_HIRGenerator; import org.jikesrvm.opt.ir.OPT_GenerationContext; import org.binarytranslator.DBT_Options; -import org.binarytranslator.arch.arm.os.process.image.ARM_SimpleProcessSpace; +import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; import org.binarytranslator.arch.x86.os.process.X86_Registers; @@ -77,11 +77,11 @@ public static ProcessSpace createProcessSpaceFromBinary(Loader loader) throws IOException { if (loader.isARM_ABI() || loader.isSysV_ABI()) { - report("ARM ABI"); + report("Creating ARM Linux ABI [rocess space"); return new ARM_LinuxProcessSpace(); } else { - report("Creating simple ARM process space."); - return new ARM_SimpleProcessSpace(); + report("Creating ARM image process space."); + return new ARM_ImageProcessSpace(); } } Added: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-03-31 14:04:36 UTC (rev 16) @@ -0,0 +1,25 @@ +package org.binarytranslator.arch.arm.os.process.image; + +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.generic.gdbstub.GDBTarget; +import org.binarytranslator.generic.os.loader.Loader; + +public class ARM_ImageProcessSpace extends ARM_ProcessSpace { + + @Override + public void doSysCall() { + throw new UnsupportedOperationException("Syscalls not supported."); + } + + @Override + public GDBTarget getGDBTarget() { + throw new UnsupportedOperationException("GDB not implemented."); + } + + @Override + public void initialise(Loader loader, int pc, int brk, String[] args) { + registers.write(ARM_Registers.PC, pc); + } + +} Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-31 14:04:36 UTC (rev 16) @@ -208,13 +208,13 @@ throws IOException { ProcessSpace result; if (loader.isX86_ISA()) { - report("X86 ELF Binary"); + report("X86 Binary"); result = X86_ProcessSpace.createProcessSpaceFromBinary(loader); } else if (loader.isPPC_ISA()) { - report("PPC ELF Binary"); + report("PPC Binary"); result = PPC_ProcessSpace.createProcessSpaceFromBinary(loader); } else if (loader.isARM_ISA()) { - report("ARM ELF Binary"); + report("ARM Binary"); result = ARM_ProcessSpace.createProcessSpaceFromBinary(loader); } else { throw new UnsupportedOperationException("Binary of " + loader.getArchitectureString() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-03-31 22:03:22
|
Revision: 17 http://svn.sourceforge.net/pearcolator/?rev=17&view=rev Author: michael_baer Date: 2007-03-31 15:03:22 -0700 (Sat, 31 Mar 2007) Log Message: ----------- Enforced JRVM formatting guidelines, introduced generics, reduced no. of warnings Modified Paths: -------------- ext/org/jikesrvm/classloader/VM_Member.java ext/org/jikesrvm/classloader/VM_Method.java ext/org/jikesrvm/classloader/VM_NormalMethod.java ext/org/jikesrvm/ppc/PPC_Disassembler.java ext/org/jikesrvm/ppc/opcodeXX.java ext/org/jikesrvm/ppc/opcode_tab.java src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_Constants.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/ppc/decoder/PPC_Laziness.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_Constants.java src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java src/org/binarytranslator/arch/x86/decoder/X86_FlagLaziness.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X86_Laziness.java src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java src/org/binarytranslator/arch/x86/decoder/X86_RegisterSyncLaziness.java src/org/binarytranslator/arch/x86/decoder/X86_Registers.java src/org/binarytranslator/arch/x86/decoder/X86_SIB_Decoder.java src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java src/org/binarytranslator/generic/branch/BranchLogic.java src/org/binarytranslator/generic/branch/CallAndReturnAddress.java src/org/binarytranslator/generic/branch/ProcedureInformation.java src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/generic/decoder/InstructionDecoder.java src/org/binarytranslator/generic/decoder/Laziness.java src/org/binarytranslator/generic/gdbstub/GDBStub.java src/org/binarytranslator/generic/gdbstub/GDBTarget.java src/org/binarytranslator/generic/memory/ByteAddressedByteSwapMemory.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/memory/ByteAddressedReversedMemory.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/IntAddressedByteSwapMemory.java src/org/binarytranslator/generic/memory/IntAddressedMemory.java src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java src/org/binarytranslator/generic/memory/IntAddressedReversedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/memory/MemoryMapException.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/generic/os/loader/image/ImageLoader.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java src/org/binarytranslator/vmInterface/DBT_Trace.java src/org/binarytranslator/vmInterface/DynamicCodeRunner.java src/org/binarytranslator/vmInterface/TranslationHelper.java Modified: ext/org/jikesrvm/classloader/VM_Member.java =================================================================== --- ext/org/jikesrvm/classloader/VM_Member.java 2007-03-31 14:04:36 UTC (rev 16) +++ ext/org/jikesrvm/classloader/VM_Member.java 2007-03-31 22:03:22 UTC (rev 17) @@ -14,16 +14,17 @@ /** * A field or method of a java class. - * + * * @author Bowen Alpern * @author Dave Grove * @author Derek Lieber */ -public abstract class VM_Member extends VM_AnnotatedElement implements VM_Constants, VM_ClassLoaderConstants { +public abstract class VM_Member extends VM_AnnotatedElement implements + VM_Constants, VM_ClassLoaderConstants { /** - * The class that declared this member, avaliable by calling - * getDeclaringClass once the class is loaded. + * The class that declared this member, avaliable by calling getDeclaringClass + * once the class is loaded. */ private final VM_TypeReference declaringClass; @@ -38,46 +39,53 @@ public final short modifiers; /** - * The signature is a string representing the generic type for this - * field or method declaration, may be null + * The signature is a string representing the generic type for this field or + * method declaration, may be null */ private final VM_Atom signature; /** - * The member's jtoc/obj/tib offset in bytes. - * Set by {@link VM_Class#resolve()} + * The member's jtoc/obj/tib offset in bytes. Set by + * {@link VM_Class#resolve()} */ protected int offset; /** - * NOTE: Only {@link VM_Class} is allowed to create an instance of a VM_Member. + * NOTE: Only {@link VM_Class} is allowed to create an instance of a + * VM_Member. * - * @param declaringClass the VM_TypeReference object of the class that declared this member - * @param memRef the canonical memberReference for this member. - * @param modifiers modifiers associated with this member. - * @param signature generic type of this member - * @param annotations array of runtime visible annotations + * @param declaringClass + * the VM_TypeReference object of the class that declared this member + * @param memRef + * the canonical memberReference for this member. + * @param modifiers + * modifiers associated with this member. + * @param signature + * generic type of this member + * @param annotations + * array of runtime visible annotations */ - protected VM_Member(VM_TypeReference declaringClass, VM_MemberReference memRef, - short modifiers, VM_Atom signature, - VM_Annotation[] annotations) { + protected VM_Member(VM_TypeReference declaringClass, + VM_MemberReference memRef, short modifiers, VM_Atom signature, + VM_Annotation[] annotations) { super(annotations); this.declaringClass = declaringClass; this.memRef = memRef; this.modifiers = modifiers; this.signature = signature; - this.offset = Short.MIN_VALUE+1; // invalid value. Set to valid value during VM_Class.resolve() + this.offset = Short.MIN_VALUE + 1; // invalid value. Set to valid value + // during VM_Class.resolve() } - //--------------------------------------------------------------------// - // Section 1. // - // The following are available after class loading. // - //--------------------------------------------------------------------// + // --------------------------------------------------------------------// + // Section 1. // + // The following are available after class loading. // + // --------------------------------------------------------------------// /** - * Class that declared this field or method. Not available before - * the class is loaded. - */ + * Class that declared this field or method. Not available before the class is + * loaded. + */ @Uninterruptible public final VM_Class getDeclaringClass() { return declaringClass.peekResolvedType().asClass(); @@ -85,26 +93,26 @@ /** * Canonical member reference for this member. - */ + */ @Uninterruptible - public final VM_MemberReference getMemberRef() { + public final VM_MemberReference getMemberRef() { return memRef; } /** * Name of this member. - */ + */ @Uninterruptible - public final VM_Atom getName() { + public final VM_Atom getName() { return memRef.getName(); } /** - * Descriptor for this member. - * something like "I" for a field or "(I)V" for a method. - */ + * Descriptor for this member. something like "I" for a field or "(I)V" for a + * method. + */ @Uninterruptible - public final VM_Atom getDescriptor() { + public final VM_Atom getDescriptor() { return memRef.getDescriptor(); } @@ -116,47 +124,47 @@ } /** - * Get a unique id for this member. - * The id is the id of the canonical VM_MemberReference for this member - * and thus may be used to find the member by first finding the member reference. + * Get a unique id for this member. The id is the id of the canonical + * VM_MemberReference for this member and thus may be used to find the member + * by first finding the member reference. */ @Uninterruptible - public final int getId() { + public final int getId() { return memRef.getId(); } /* - * Define hashcode in terms of VM_Atom.hashCode to enable - * consistent hash codes during bootImage writing and run-time. + * Define hashcode in terms of VM_Atom.hashCode to enable consistent hash + * codes during bootImage writing and run-time. */ - public int hashCode() { + public int hashCode() { return memRef.hashCode(); } public final String toString() { return declaringClass + "." + getName() + " " + getDescriptor(); } - + /** * Usable from classes outside its package? - */ + */ public final boolean isPublic() { - return (modifiers & ACC_PUBLIC) != 0; + return (modifiers & ACC_PUBLIC) != 0; } /** * Usable only from this class? - */ - public final boolean isPrivate() { - return (modifiers & ACC_PRIVATE) != 0; + */ + public final boolean isPrivate() { + return (modifiers & ACC_PRIVATE) != 0; } - + /** * Usable from subclasses? - */ - public final boolean isProtected() { - return (modifiers & ACC_PROTECTED) != 0; - } + */ + public final boolean isProtected() { + return (modifiers & ACC_PROTECTED) != 0; + } /** * Get the member's modifiers. @@ -165,31 +173,34 @@ return modifiers; } - //------------------------------------------------------------------// - // Section 2. // - // The following are available after the declaring class has been // - // "resolved". // - //------------------------------------------------------------------// + // ------------------------------------------------------------------// + // Section 2. // + // The following are available after the declaring class has been // + // "resolved". // + // ------------------------------------------------------------------// /** * Offset of this field or method, in bytes. * <ul> - * <li> For a static field: offset of field from start of jtoc - * <li> For a static method: offset of code object reference from start of jtoc - * <li> For a non-static field: offset of field from start of object - * <li> For a non-static method: offset of code object reference from start of tib + * <li> For a static field: offset of field from start of jtoc + * <li> For a static method: offset of code object reference from start of + * jtoc + * <li> For a non-static field: offset of field from start of object + * <li> For a non-static method: offset of code object reference from start of + * tib * </ul> - */ + */ @Uninterruptible - public final Offset getOffset() { - if (VM.VerifyAssertions) VM._assert(declaringClass.isResolved()); + public final Offset getOffset() { + if (VM.VerifyAssertions) + VM._assert(declaringClass.isResolved()); return Offset.fromIntSignExtend(offset); } /** - * Only meant to be used by VM_ObjectModel.layoutInstanceFields. - * TODO: refactor system so this functionality is in the classloader package - * and this method doesn't have to be final. + * Only meant to be used by VM_ObjectModel.layoutInstanceFields. TODO: + * refactor system so this functionality is in the classloader package and + * this method doesn't have to be final. */ public final void setOffset(Offset off) { offset = off.toInt(); Modified: ext/org/jikesrvm/classloader/VM_Method.java =================================================================== --- ext/org/jikesrvm/classloader/VM_Method.java 2007-03-31 14:04:36 UTC (rev 16) +++ ext/org/jikesrvm/classloader/VM_Method.java 2007-03-31 22:03:22 UTC (rev 17) @@ -21,121 +21,143 @@ import org.vmmagic.pragma.*; /** - * A method of a java class corresponding to a method_info structure - * in the class file. A method is read from a class file using the - * {@link #readMethod} method. - * + * A method of a java class corresponding to a method_info structure in the + * class file. A method is read from a class file using the {@link #readMethod} + * method. + * * @author Bowen Alpern * @author Dave Grove * @author Derek Lieber * @author Ian Rogers */ -public abstract class VM_Method extends VM_Member implements VM_BytecodeConstants { +public abstract class VM_Method extends VM_Member implements + VM_BytecodeConstants { /** * current compiled method for this method */ protected VM_CompiledMethod currentCompiledMethod; + /** * exceptions this method might throw (null --> none) */ protected final VM_TypeReference[] exceptionTypes; + /** - * Method paramter annotations from the class file that are - * described as runtime visible. These annotations are available to - * the reflection API. + * Method paramter annotations from the class file that are described as + * runtime visible. These annotations are available to the reflection API. */ protected final VM_Annotation[] parameterAnnotations; + /** * A value present in the method info tables of annotation types. It * represents the default result from an annotation method. */ protected final Object annotationDefault; + /** - * The offset of this virtual method in the jtoc if it's been placed - * there by constant propagation, otherwise 0. + * The offset of this virtual method in the jtoc if it's been placed there by + * constant propagation, otherwise 0. */ private Offset jtocOffset; /** * Construct a read method - * - * @param declaringClass the VM_Class object of the class that declared this field - * @param memRef the canonical memberReference for this method. - * @param modifiers modifiers associated with this method. - * @param exceptionTypes exceptions thrown by this method. - * @param signature generic type of this method. - * @param annotations array of runtime visible annotations - * @param parameterAnnotations array of runtime visible parameter annotations - * @param annotationDefault value for this annotation that appears + * + * @param declaringClass + * the VM_Class object of the class that declared this field + * @param memRef + * the canonical memberReference for this method. + * @param modifiers + * modifiers associated with this method. + * @param exceptionTypes + * exceptions thrown by this method. + * @param signature + * generic type of this method. + * @param annotations + * array of runtime visible annotations + * @param parameterAnnotations + * array of runtime visible parameter annotations + * @param annotationDefault + * value for this annotation that appears */ - protected VM_Method(VM_TypeReference declaringClass, VM_MemberReference memRef, - short modifiers, VM_TypeReference[] exceptionTypes, VM_Atom signature, - VM_Annotation[] annotations, - VM_Annotation[] parameterAnnotations, - Object annotationDefault) - { - super(declaringClass, memRef, (short)(modifiers & APPLICABLE_TO_METHODS), signature, annotations); + protected VM_Method(VM_TypeReference declaringClass, + VM_MemberReference memRef, short modifiers, + VM_TypeReference[] exceptionTypes, VM_Atom signature, + VM_Annotation[] annotations, VM_Annotation[] parameterAnnotations, + Object annotationDefault) { + super(declaringClass, memRef, (short) (modifiers & APPLICABLE_TO_METHODS), + signature, annotations); this.parameterAnnotations = parameterAnnotations; this.annotationDefault = annotationDefault; memRef.asMethodReference().setResolvedMember(this); this.exceptionTypes = exceptionTypes; this.jtocOffset = Offset.fromIntSignExtend(-1); } - + /** - * Called from {@link VM_Class#readClass(VM_TypeReference, DataInputStream)} to create an - * instance of a VM_Method by reading the relevant data from the argument bytecode stream. + * Called from {@link VM_Class#readClass(VM_TypeReference, DataInputStream)} + * to create an instance of a VM_Method by reading the relevant data from the + * argument bytecode stream. * - * @param declaringClass the VM_TypeReference of the class being loaded - * @param constantPool the constantPool of the VM_Class object that's being constructed - * @param memRef the canonical memberReference for this member. - * @param modifiers modifiers associated with this member. - * @param input the DataInputStream to read the method's attributes from + * @param declaringClass + * the VM_TypeReference of the class being loaded + * @param constantPool + * the constantPool of the VM_Class object that's being constructed + * @param memRef + * the canonical memberReference for this member. + * @param modifiers + * modifiers associated with this member. + * @param input + * the DataInputStream to read the method's attributes from */ - static VM_Method readMethod(VM_TypeReference declaringClass, int[] constantPool, VM_MemberReference memRef, - short modifiers, DataInputStream input) throws IOException { + static VM_Method readMethod(VM_TypeReference declaringClass, + int[] constantPool, VM_MemberReference memRef, short modifiers, + DataInputStream input) throws IOException { short tmp_localWords = 0; - short tmp_operandWords = 0; - byte[] tmp_bytecodes = null; + short tmp_operandWords = 0; + byte[] tmp_bytecodes = null; VM_ExceptionHandlerMap tmp_exceptionHandlerMap = null; VM_TypeReference[] tmp_exceptionTypes = null; - int[] tmp_lineNumberMap = null; + int[] tmp_lineNumberMap = null; VM_Atom tmp_signature = null; VM_Annotation[] annotations = null; VM_Annotation[] parameterAnnotations = null; Object tmp_annotationDefault = null; // Read the attributes - for (int i = 0, n = input.readUnsignedShort(); i<n; i++) { - VM_Atom attName = VM_Class.getUtf(constantPool, input.readUnsignedShort()); - int attLength = input.readInt(); + for (int i = 0, n = input.readUnsignedShort(); i < n; i++) { + VM_Atom attName = VM_Class + .getUtf(constantPool, input.readUnsignedShort()); + int attLength = input.readInt(); // Only bother to interpret non-boring Method attributes if (attName == VM_ClassLoader.codeAttributeName) { tmp_operandWords = input.readShort(); - tmp_localWords = input.readShort(); + tmp_localWords = input.readShort(); tmp_bytecodes = new byte[input.readInt()]; input.readFully(tmp_bytecodes); - tmp_exceptionHandlerMap = VM_ExceptionHandlerMap.readExceptionHandlerMap(input, constantPool); + tmp_exceptionHandlerMap = VM_ExceptionHandlerMap + .readExceptionHandlerMap(input, constantPool); // Read the attributes portion of the code attribute - for (int j = 0, n2 = input.readUnsignedShort(); j<n2; j++) { - attName = VM_Class.getUtf(constantPool, input.readUnsignedShort()); + for (int j = 0, n2 = input.readUnsignedShort(); j < n2; j++) { + attName = VM_Class.getUtf(constantPool, input.readUnsignedShort()); attLength = input.readInt(); if (attName == VM_ClassLoader.lineNumberTableAttributeName) { int cnt = input.readUnsignedShort(); if (cnt != 0) { tmp_lineNumberMap = new int[cnt]; - for (int k = 0; k<cnt; k++) { + for (int k = 0; k < cnt; k++) { int startPC = input.readUnsignedShort(); int lineNumber = input.readUnsignedShort(); tmp_lineNumberMap[k] = (lineNumber << BITS_IN_SHORT) | startPC; } } } else { - // All other entries in the attribute portion of the code attribute are boring. + // All other entries in the attribute portion of the code attribute + // are boring. input.skipBytes(attLength); } } @@ -144,24 +166,26 @@ if (cnt != 0) { tmp_exceptionTypes = new VM_TypeReference[cnt]; for (int j = 0, m = tmp_exceptionTypes.length; j < m; ++j) { - tmp_exceptionTypes[j] = VM_Class.getTypeRef(constantPool, input.readUnsignedShort()); + tmp_exceptionTypes[j] = VM_Class.getTypeRef(constantPool, input + .readUnsignedShort()); } } } else if (attName == VM_ClassLoader.syntheticAttributeName) { modifiers |= ACC_SYNTHETIC; } else if (attName == VM_ClassLoader.signatureAttributeName) { - tmp_signature = VM_Class.getUtf(constantPool, input.readUnsignedShort()); + tmp_signature = VM_Class + .getUtf(constantPool, input.readUnsignedShort()); } else if (attName == VM_ClassLoader.runtimeVisibleAnnotationsAttributeName) { - annotations = VM_AnnotatedElement.readAnnotations(constantPool, input, 2, - declaringClass.getClassLoader()); + annotations = VM_AnnotatedElement.readAnnotations(constantPool, input, + 2, declaringClass.getClassLoader()); } else if (attName == VM_ClassLoader.runtimeVisibleParameterAnnotationsAttributeName) { - parameterAnnotations = VM_AnnotatedElement.readAnnotations(constantPool, input, 1, - declaringClass.getClassLoader()); + parameterAnnotations = VM_AnnotatedElement.readAnnotations( + constantPool, input, 1, declaringClass.getClassLoader()); } else if (attName == VM_ClassLoader.annotationDefaultAttributeName) { try { - tmp_annotationDefault = VM_Annotation.readValue(constantPool, input, declaringClass.getClassLoader()); - } - catch (ClassNotFoundException e){ + tmp_annotationDefault = VM_Annotation.readValue(constantPool, input, + declaringClass.getClassLoader()); + } catch (ClassNotFoundException e) { throw new Error(e); } } else { @@ -171,175 +195,173 @@ } VM_Method method; if ((modifiers & ACC_NATIVE) != 0) { - method = new VM_NativeMethod(declaringClass, memRef, modifiers, tmp_exceptionTypes, tmp_signature, - annotations, parameterAnnotations, tmp_annotationDefault); + method = new VM_NativeMethod(declaringClass, memRef, modifiers, + tmp_exceptionTypes, tmp_signature, annotations, parameterAnnotations, + tmp_annotationDefault); } else if ((modifiers & ACC_ABSTRACT) != 0) { - method = new VM_AbstractMethod(declaringClass, memRef, modifiers, tmp_exceptionTypes, tmp_signature, - annotations, parameterAnnotations, tmp_annotationDefault); + method = new VM_AbstractMethod(declaringClass, memRef, modifiers, + tmp_exceptionTypes, tmp_signature, annotations, parameterAnnotations, + tmp_annotationDefault); } else { - method = new VM_NormalMethod(declaringClass, memRef, modifiers, tmp_exceptionTypes, - tmp_localWords, tmp_operandWords, tmp_bytecodes, - tmp_exceptionHandlerMap, tmp_lineNumberMap, - constantPool, tmp_signature, - annotations, parameterAnnotations, tmp_annotationDefault); + method = new VM_NormalMethod(declaringClass, memRef, modifiers, + tmp_exceptionTypes, tmp_localWords, tmp_operandWords, tmp_bytecodes, + tmp_exceptionHandlerMap, tmp_lineNumberMap, constantPool, + tmp_signature, annotations, parameterAnnotations, + tmp_annotationDefault); } return method; } /** - * Create a copy of the method that occurs in the annotation - * interface. The method body will contain a read of the field at - * the constant pool index specified. - * - * @param annotationClass the class this method belongs to - * @param constantPool for the class - * @param memRef the member reference corresponding to this method - * @param interfaceMethod the interface method that will copied to - * produce the annotation method - * @param constantPoolIndex the index of the field that will be - * returned by this method + * Create a copy of the method that occurs in the annotation interface. The + * method body will contain a read of the field at the constant pool index + * specified. + * + * @param annotationClass + * the class this method belongs to + * @param constantPool + * for the class + * @param memRef + * the member reference corresponding to this method + * @param interfaceMethod + * the interface method that will copied to produce the annotation + * method + * @param constantPoolIndex + * the index of the field that will be returned by this method * @return the created method */ - static VM_Method createAnnotationMethod(VM_TypeReference annotationClass, int[] constantPool, - VM_MemberReference memRef, VM_Method interfaceMethod, - int constantPoolIndex) { - byte[] bytecodes = new byte[] { - (byte)JBC_aload_0, - (byte)JBC_getfield, - (byte)(constantPoolIndex >>> 8), - (byte)constantPoolIndex, - // Xreturn - (byte)typeRefToReturnBytecode(interfaceMethod.getReturnType()) - }; - return new VM_NormalMethod(annotationClass, memRef, (short)(ACC_PUBLIC|ACC_FINAL|ACC_SYNTHETIC), null, - (short)1, (short)2, bytecodes, - null, null, - constantPool, - null, null, null, null); + static VM_Method createAnnotationMethod(VM_TypeReference annotationClass, + int[] constantPool, VM_MemberReference memRef, VM_Method interfaceMethod, + int constantPoolIndex) { + byte[] bytecodes = new byte[] { (byte) JBC_aload_0, (byte) JBC_getfield, + (byte) (constantPoolIndex >>> 8), (byte) constantPoolIndex, + // Xreturn + (byte) typeRefToReturnBytecode(interfaceMethod.getReturnType()) }; + return new VM_NormalMethod(annotationClass, memRef, (short) (ACC_PUBLIC + | ACC_FINAL | ACC_SYNTHETIC), null, (short) 1, (short) 2, bytecodes, + null, null, constantPool, null, null, null, null); } + /** * Create a method to initialise the annotation class - * - * @param aClass the class this method belongs to - * @param constantPool for the class - * @param memRef the member reference corresponding to this method - * @param objectInitIndex an index into the constant pool for a - * method reference to java.lang.Object.<init> + * + * @param aClass + * the class this method belongs to + * @param constantPool + * for the class + * @param memRef + * the member reference corresponding to this method + * @param objectInitIndex + * an index into the constant pool for a method reference to + * java.lang.Object.<init> * @param aFields * @param aMethods * @return the created method */ - static VM_Method createAnnotationInit(VM_TypeReference aClass, int[] constantPool, - VM_MemberReference memRef, int objectInitIndex, - VM_Field[] aFields, VM_Method[] aMethods, - int[] defaultConstants) { - byte[] bytecode = new byte[6+(defaultConstants.length*7)]; - bytecode[0] = (byte)JBC_aload_0; // stack[0] = this - bytecode[1] = (byte)JBC_aload_1; // stack[1] = instanceof VM_Annotation - bytecode[2] = (byte)JBC_invokespecial; - bytecode[3] = (byte)(objectInitIndex >>> 8); - bytecode[4] = (byte)objectInitIndex; - for(int i=0, j=0; i < aMethods.length; i++) { - if(aMethods[i].annotationDefault != null) { - bytecode[(j*7)+5+0] = (byte)JBC_aload_0; // stack[0] = this - if(VM_Class.getLiteralSize(constantPool, defaultConstants[j]) == BYTES_IN_INT) { - bytecode[(j*7)+5+1] = (byte)JBC_ldc_w; // stack[1] = value + static VM_Method createAnnotationInit(VM_TypeReference aClass, + int[] constantPool, VM_MemberReference memRef, int objectInitIndex, + VM_Field[] aFields, VM_Method[] aMethods, int[] defaultConstants) { + byte[] bytecode = new byte[6 + (defaultConstants.length * 7)]; + bytecode[0] = (byte) JBC_aload_0; // stack[0] = this + bytecode[1] = (byte) JBC_aload_1; // stack[1] = instanceof VM_Annotation + bytecode[2] = (byte) JBC_invokespecial; + bytecode[3] = (byte) (objectInitIndex >>> 8); + bytecode[4] = (byte) objectInitIndex; + for (int i = 0, j = 0; i < aMethods.length; i++) { + if (aMethods[i].annotationDefault != null) { + bytecode[(j * 7) + 5 + 0] = (byte) JBC_aload_0; // stack[0] = this + if (VM_Class.getLiteralSize(constantPool, defaultConstants[j]) == BYTES_IN_INT) { + bytecode[(j * 7) + 5 + 1] = (byte) JBC_ldc_w; // stack[1] = value + } else { + bytecode[(j * 7) + 5 + 1] = (byte) JBC_ldc2_w;// stack[1&2] = value } - else { - bytecode[(j*7)+5+1] = (byte)JBC_ldc2_w;// stack[1&2] = value - } - bytecode[(j*7)+5+2] = (byte)(defaultConstants[j] >>> 8); - bytecode[(j*7)+5+3] = (byte)defaultConstants[j]; - bytecode[(j*7)+5+4] = (byte)JBC_putfield; - bytecode[(j*7)+5+5] = (byte)(i >>> 8); - bytecode[(j*7)+5+6] = (byte)i; + bytecode[(j * 7) + 5 + 2] = (byte) (defaultConstants[j] >>> 8); + bytecode[(j * 7) + 5 + 3] = (byte) defaultConstants[j]; + bytecode[(j * 7) + 5 + 4] = (byte) JBC_putfield; + bytecode[(j * 7) + 5 + 5] = (byte) (i >>> 8); + bytecode[(j * 7) + 5 + 6] = (byte) i; j++; } } - bytecode[bytecode.length-1] = (byte)JBC_return; - return new VM_NormalMethod(aClass, memRef, (short)(ACC_PUBLIC|ACC_FINAL|ACC_SYNTHETIC), null, - (short)2, (short)3, bytecode, - null, null, - constantPool, - null, null, null, null); + bytecode[bytecode.length - 1] = (byte) JBC_return; + return new VM_NormalMethod(aClass, memRef, + (short) (ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC), null, (short) 2, + (short) 3, bytecode, null, null, constantPool, null, null, null, null); } /** - * What would be the appropriate return bytecode for the given type - * reference? + * What would be the appropriate return bytecode for the given type reference? */ private static int typeRefToReturnBytecode(VM_TypeReference tr) { - if(!tr.isPrimitiveType()) { + if (!tr.isPrimitiveType()) { return JBC_areturn; } else { - VM_Primitive pt = (VM_Primitive)tr.peekResolvedType(); - if((pt == VM_Type.BooleanType)||(pt == VM_Type.ByteType)||(pt == VM_Type.ShortType)|| - (pt == VM_Type.CharType)||(pt == VM_Type.IntType)) { + VM_Primitive pt = (VM_Primitive) tr.peekResolvedType(); + if ((pt == VM_Type.BooleanType) || (pt == VM_Type.ByteType) + || (pt == VM_Type.ShortType) || (pt == VM_Type.CharType) + || (pt == VM_Type.IntType)) { return JBC_ireturn; - } - else if(pt == VM_Type.LongType) { + } else if (pt == VM_Type.LongType) { return JBC_lreturn; - } - else if(pt == VM_Type.FloatType) { + } else if (pt == VM_Type.FloatType) { return JBC_freturn; - } - else if(pt == VM_Type.DoubleType) { + } else if (pt == VM_Type.DoubleType) { return JBC_dreturn; - } - else { + } else { VM._assert(false); return -1; } } } + /** * Is this method a class initializer? */ @Uninterruptible - public final boolean isClassInitializer() { - return getName() == VM_ClassLoader.StandardClassInitializerMethodName; + public final boolean isClassInitializer() { + return getName() == VM_ClassLoader.StandardClassInitializerMethodName; } /** * Is this method an object initializer? */ @Uninterruptible - public final boolean isObjectInitializer() { - return getName() == VM_ClassLoader.StandardObjectInitializerMethodName; + public final boolean isObjectInitializer() { + return getName() == VM_ClassLoader.StandardObjectInitializerMethodName; } /** * Is this method a compiler-generated object initializer helper? */ @Uninterruptible - public final boolean isObjectInitializerHelper() { - return getName() == VM_ClassLoader.StandardObjectInitializerHelperMethodName; + public final boolean isObjectInitializerHelper() { + return getName() == VM_ClassLoader.StandardObjectInitializerHelperMethodName; } /** * Type of this method's return value. */ @Uninterruptible - public final VM_TypeReference getReturnType() { + public final VM_TypeReference getReturnType() { return memRef.asMethodReference().getReturnType(); } /** - * Type of this method's parameters. - * Note: does *not* include implicit "this" parameter, if any. + * Type of this method's parameters. Note: does *not* include implicit "this" + * parameter, if any. */ @Uninterruptible - public final VM_TypeReference[] getParameterTypes() { + public final VM_TypeReference[] getParameterTypes() { return memRef.asMethodReference().getParameterTypes(); } /** - * Space required by this method for its parameters, in words. - * Note: does *not* include implicit "this" parameter, if any. + * Space required by this method for its parameters, in words. Note: does + * *not* include implicit "this" parameter, if any. */ @Uninterruptible - public final int getParameterWords() { + public final int getParameterWords() { return memRef.asMethodReference().getParameterWords(); } @@ -351,15 +373,16 @@ } /** - * Get the current compiled method for this method. - * Will return null if there is no current compiled method! - * - * We make this method Unpreemptible to avoid a race-condition - * in VM_Reflection.invoke. + * Get the current compiled method for this method. Will return null if there + * is no current compiled method! + * + * We make this method Unpreemptible to avoid a race-condition in + * VM_Reflection.invoke. + * * @return compiled method - */ + */ @Unpreemptible - public final synchronized VM_CompiledMethod getCurrentCompiledMethod() { + public final synchronized VM_CompiledMethod getCurrentCompiledMethod() { return currentCompiledMethod; } @@ -367,7 +390,7 @@ * Declared as statically dispatched? */ @Uninterruptible - public final boolean isStatic() { + public final boolean isStatic() { return (modifiers & ACC_STATIC) != 0; } @@ -375,7 +398,7 @@ * Declared as non-overridable by subclasses? */ @Uninterruptible - public final boolean isFinal() { + public final boolean isFinal() { return (modifiers & ACC_FINAL) != 0; } @@ -383,7 +406,7 @@ * Guarded by monitorenter/monitorexit? */ @Uninterruptible - public final boolean isSynchronized() { + public final boolean isSynchronized() { return (modifiers & ACC_SYNCHRONIZED) != 0; } @@ -391,7 +414,7 @@ * Not implemented in java? */ @Uninterruptible - public final boolean isNative() { + public final boolean isNative() { return (modifiers & ACC_NATIVE) != 0; } @@ -399,14 +422,15 @@ * Not implemented in Java and use C not JNI calling convention */ public final boolean isSysCall() { - return isNative() && isStatic() && isAnnotationDeclared(VM_TypeReference.SysCall); + return isNative() && isStatic() + && isAnnotationDeclared(VM_TypeReference.SysCall); } - + /** * Implemented in subclass? */ @Uninterruptible - public final boolean isAbstract() { + public final boolean isAbstract() { return (modifiers & ACC_ABSTRACT) != 0; } @@ -418,46 +442,58 @@ } /** - * Exceptions thrown by this method - - * something like { "java/lang/IOException", "java/lang/EOFException" } + * Exceptions thrown by this method - something like { + * "java/lang/IOException", "java/lang/EOFException" } + * * @return info (null --> method doesn't throw any exceptions) */ @Uninterruptible - public final VM_TypeReference[] getExceptionTypes() { + public final VM_TypeReference[] getExceptionTypes() { return exceptionTypes; } /** - * Is this method interruptible? - * In other words, should the compiler insert yieldpoints - * in method prologue, epilogue, and backwards branches. - * Also, only methods that are Interruptible have stackoverflow checks - * in the method prologue (since there is no mechanism for handling a stackoverflow - * that doesn't violate the uninterruptiblity of the method). - * To determine if a method is interruptible, the following conditions - * are checked (<em>in order</em>): + * Is this method interruptible? In other words, should the compiler insert + * yieldpoints in method prologue, epilogue, and backwards branches. Also, + * only methods that are Interruptible have stackoverflow checks in the method + * prologue (since there is no mechanism for handling a stackoverflow that + * doesn't violate the uninterruptiblity of the method). To determine if a + * method is interruptible, the following conditions are checked (<em>in order</em>): * <ul> * <li> If it is a <clinit> or <init> method then it is interruptible. - * <li> If is the synthetic 'this' method used by jikes to - * factor out default initializers for <init> methods then it is interruptible. - * <li> If it is annotated with <CODE>Interruptible</CODE> it is interruptible. - * <li> If it is annotated with <CODE>Preemptible</CODE> it is interruptible. - * <li> If it is annotated with <CODE>Uninterruptible</CODE> it is not interruptible. - * <li> If it is annotated with <CODE>UninterruptibleNoWarn</CODE> it is not interruptible. - * <li> If it is annotated with <CODE>Unpreemptible</CODE> it is not interruptible. + * <li> If is the synthetic 'this' method used by jikes to factor out default + * initializers for <init> methods then it is interruptible. + * <li> If it is annotated with <CODE>Interruptible</CODE> it is + * interruptible. + * <li> If it is annotated with <CODE>Preemptible</CODE> it is + * interruptible. + * <li> If it is annotated with <CODE>Uninterruptible</CODE> it is not + * interruptible. + * <li> If it is annotated with <CODE>UninterruptibleNoWarn</CODE> it is not + * interruptible. + * <li> If it is annotated with <CODE>Unpreemptible</CODE> it is not + * interruptible. * <li> If its declaring class is annotated with <CODE>Uninterruptible</CODE> - * or <CODE>Unpreemptible</CODE> it is not interruptible. + * or <CODE>Unpreemptible</CODE> it is not interruptible. * </ul> */ public final boolean isInterruptible() { - if (isClassInitializer() || isObjectInitializer()) return true; - if (isObjectInitializerHelper()) return true; - if (hasInterruptibleAnnotation()) return true; - if (hasPreemptibleAnnotation()) return true; - if (hasUninterruptibleNoWarnAnnotation()) return false; - if (hasUninterruptibleAnnotation()) return false; - if (hasUnpreemptibleAnnotation()) return false; - if (getDeclaringClass().hasUnpreemptibleAnnotation()) return false; + if (isClassInitializer() || isObjectInitializer()) + return true; + if (isObjectInitializerHelper()) + return true; + if (hasInterruptibleAnnotation()) + return true; + if (hasPreemptibleAnnotation()) + return true; + if (hasUninterruptibleNoWarnAnnotation()) + return false; + if (hasUninterruptibleAnnotation()) + return false; + if (hasUnpreemptibleAnnotation()) + return false; + if (getDeclaringClass().hasUnpreemptibleAnnotation()) + return false; return !getDeclaringClass().hasUninterruptibleAnnotation(); } @@ -465,13 +501,20 @@ * Is the method Unpreemptible? See the comment in {@link #isInterruptible} */ public final boolean isUnpreemptible() { - if (isClassInitializer() || isObjectInitializer()) return false; - if (isObjectInitializerHelper()) return false; - if (hasInterruptibleAnnotation()) return false; - if (hasPreemptibleAnnotation()) return false; - if (hasUninterruptibleAnnotation()) return false; - if (hasUninterruptibleNoWarnAnnotation()) return false; - if (hasUnpreemptibleAnnotation()) return true; + if (isClassInitializer() || isObjectInitializer()) + return false; + if (isObjectInitializerHelper()) + return false; + if (hasInterruptibleAnnotation()) + return false; + if (hasPreemptibleAnnotation()) + return false; + if (hasUninterruptibleAnnotation()) + return false; + if (hasUninterruptibleNoWarnAnnotation()) + return false; + if (hasUnpreemptibleAnnotation()) + return true; return getDeclaringClass().hasUnpreemptibleAnnotation(); } @@ -479,20 +522,27 @@ * Is the method Uninterruptible? See the comment in {@link #isInterruptible} */ public final boolean isUninterruptible() { - if (isClassInitializer() || isObjectInitializer()) return false; - if (isObjectInitializerHelper()) return false; - if (hasInterruptibleAnnotation()) return false; - if (hasPreemptibleAnnotation()) return false; - if (hasUnpreemptibleAnnotation()) return false; - if (hasUninterruptibleAnnotation()) return true; - if (hasUninterruptibleNoWarnAnnotation()) return true; + if (isClassInitializer() || isObjectInitializer()) + return false; + if (isObjectInitializerHelper()) + return false; + if (hasInterruptibleAnnotation()) + return false; + if (hasPreemptibleAnnotation()) + return false; + if (hasUnpreemptibleAnnotation()) + return false; + if (hasUninterruptibleAnnotation()) + return true; + if (hasUninterruptibleNoWarnAnnotation()) + return true; return getDeclaringClass().hasUninterruptibleAnnotation(); } /** - * Has this method been marked as forbidden to inline? - * ie., it is marked with the <CODE>NoInline</CODE> annotation or - * the <CODE>NoOptCompile</CODE> annotation? + * Has this method been marked as forbidden to inline? ie., it is marked with + * the <CODE>NoInline</CODE> annotation or the <CODE>NoOptCompile</CODE> + * annotation? */ public final boolean hasNoInlinePragma() { return (hasNoInlineAnnotation() || hasNoOptCompileAnnotation()); @@ -502,70 +552,81 @@ * @return true if the method may write to a given field */ public boolean mayWrite(VM_Field field) { - return true; // be conservative. native methods can write to anything + return true; // be conservative. native methods can write to anything } /** - * @return true if the method is the implementation of a runtime service - * that is called "under the covers" from the generated code and thus is not subject to - * inlining via the normal mechanisms. + * @return true if the method is the implementation of a runtime service that + * is called "under the covers" from the generated code and thus is + * not subject to inlining via the normal mechanisms. */ public boolean isRuntimeServiceMethod() { - return false; // only VM_NormalMethods can be runtime service impls in Jikes RVM and they override this method + return false; // only VM_NormalMethods can be runtime service impls in Jikes + // RVM and they override this method } - //------------------------------------------------------------------// - // Section 2. // - // The following are available after the declaring class has been // - // "resolved". // - //------------------------------------------------------------------// + // ------------------------------------------------------------------// + // Section 2. // + // The following are available after the declaring class has been // + // "resolved". // + // ------------------------------------------------------------------// /** - * Get the code array that corresponds to the entry point (prologue) for the method. + * Get the code array that corresponds to the entry point (prologue) for the + * method. */ public final synchronized VM_CodeArray getCurrentEntryCodeArray() { VM_Class declaringClass = getDeclaringClass(); - if (VM.VerifyAssertions) VM._assert(declaringClass.isResolved()); + if (VM.VerifyAssertions) + VM._assert(declaringClass.isResolved()); if (isCompiled()) { return currentCompiledMethod.getEntryCodeArray(); } else if (!VM.writingBootImage || isNative()) { if (!isStatic() && !isObjectInitializer() && !isPrivate()) { // A non-private virtual method. - if (declaringClass.isJavaLangObjectType() || - declaringClass.getSuperClass().findVirtualMethod(getName(), getDescriptor()) == null) { - // The root method of a virtual method family can use the lazy method invoker directly. - return VM_Entrypoints.lazyMethodInvokerMethod.getCurrentEntryCodeArray(); + if (declaringClass.isJavaLangObjectType() + || declaringClass.getSuperClass().findVirtualMethod(getName(), + getDescriptor()) == null) { + // The root method of a virtual method family can use the lazy method + // invoker directly. + return VM_Entrypoints.lazyMethodInvokerMethod + .getCurrentEntryCodeArray(); } else { - // All other virtual methods in the family must generate unique stubs to - // ensure correct operation of the method test (guarded inlining of virtual calls). + // All other virtual methods in the family must generate unique stubs + // to + // ensure correct operation of the method test (guarded inlining of + // virtual calls). return VM_LazyCompilationTrampolineGenerator.getTrampoline(); } } else { // We'll never do a method test against this method. // Therefore we can use the lazy method invoker directly. - return VM_Entrypoints.lazyMethodInvokerMethod.getCurrentEntryCodeArray(); + return VM_Entrypoints.lazyMethodInvokerMethod + .getCurrentEntryCodeArray(); } } else { - compile(); + compile(); return currentCompiledMethod.getEntryCodeArray(); } } /** - * Generate machine code for this method if valid - * machine code doesn't already exist. - * Return the resulting VM_CompiledMethod object. + * Generate machine code for this method if valid machine code doesn't already + * exist. Return the resulting VM_CompiledMethod object. */ public final synchronized void compile() { - if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isResolved()); - if (isCompiled()) return; + if (VM.VerifyAssertions) + VM._assert(getDeclaringClass().isResolved()); + if (isCompiled()) + return; - if (VM.TraceClassLoading && VM.runningVM) VM.sysWrite("VM_Method: (begin) compiling " + this + "\n"); + if (VM.TraceClassLoading && VM.runningVM) + VM.sysWrite("VM_Method: (begin) compiling " + this + "\n"); VM_CompiledMethod cm = genCode(); // Ensure that cm wasn't invalidated while it was being compiled. - synchronized(cm) { + synchronized (cm) { if (cm.isInvalid()) { VM_CompiledMethods.setCompiledMethodObsolete(cm); } else { @@ -573,34 +634,40 @@ } } - if (VM.TraceClassLoading && VM.runningVM) VM.sysWrite("VM_Method: (end) compiling " + this + "\n"); + if (VM.TraceClassLoading && VM.runningVM) + VM.sysWrite("VM_Method: (end) compiling " + this + "\n"); } protected abstract VM_CompiledMethod genCode(); - //----------------------------------------------------------------// - // Section 3. // - // The following are available after the declaring class has been // - // "instantiated". // - //----------------------------------------------------------------// + // ----------------------------------------------------------------// + // Section 3. // + // The following are available after the declaring class has been // + // "instantiated". // + // ----------------------------------------------------------------// /** - * Change machine code that will be used by future executions of this method + * Change machine code that will be used by future executions of this method * (ie. optimized <-> non-optimized) - * @param compiledMethod new machine code - * Side effect: updates jtoc or method dispatch tables - * ("type information blocks") - * for this class and its subclasses - */ - public synchronized void replaceCompiledMethod(VM_CompiledMethod compiledMethod) { - if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isInstantiated()); - // If we're replacing with a non-null compiledMethod, ensure that is still valid! + * + * @param compiledMethod + * new machine code Side effect: updates jtoc or method dispatch + * tables ("type information blocks") for this class and its + * subclasses + */ + public synchronized void replaceCompiledMethod( + VM_CompiledMethod compiledMethod) { + if (VM.VerifyAssertions) + VM._assert(getDeclaringClass().isInstantiated()); + // If we're replacing with a non-null compiledMethod, ensure that is still + // valid! if (compiledMethod != null) { - synchronized(compiledMethod) { - if (compiledMethod.isInvalid()) return; + synchronized (compiledMethod) { + if (compiledMethod.isInvalid()) + return; } } - + // Grab version that is being replaced VM_CompiledMethod oldCompiledMethod = currentCompiledMethod; currentCompiledMethod = compiledMethod; @@ -610,7 +677,7 @@ getDeclaringClass().updateMethod(this); // Replace constant-ified virtual method in JTOC if necessary - if(jtocOffset.toInt() != -1) { + if (jtocOffset.toInt() != -1) { VM_Statics.setSlotContents(jtocOffset, getCurrentEntryCodeArray()); } @@ -621,10 +688,11 @@ } /** - * If CM is the current compiled code for this, then invaldiate it. + * If CM is the current compiled code for this, then invaldiate it. */ public final synchronized void invalidateCompiledMethod(VM_CompiledMethod cm) { - if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isInstantiated()); + if (VM.VerifyAssertions) + VM._assert(getDeclaringClass().isInstantiated()); if (currentCompiledMethod == cm) { replaceCompiledMethod(null); } @@ -634,8 +702,9 @@ * Find or create a jtoc offset for this method */ public final synchronized Offset findOrCreateJtocOffset() { - if (VM.VerifyAssertions) VM._assert(!isStatic() && !isObjectInitializer()); - if(jtocOffset.EQ(Offset.zero())) { + if (VM.VerifyAssertions) + VM._assert(!isStatic() && !isObjectInitializer()); + if (jtocOffset.EQ(Offset.zero())) { jtocOffset = VM_Statics.allocateReferenceSlot(); VM_Statics.setSlotContents(jtocOffset, getCurrentEntryCodeArray()); } Modified: ext/org/jikesrvm/classloader/VM_NormalMethod.java =================================================================== --- ext/org/jikesrvm/classloader/VM_NormalMethod.java 2007-03-31 14:04:36 UTC (rev 16) +++ ext/org/jikesrvm/classloader/VM_NormalMethod.java 2007-03-31 22:03:22 UTC (rev 17) @@ -17,80 +17,103 @@ /** * A method of a java class that has bytecodes. - * + * * @author Bowen Alpern * @author Stephen Fink * @author Dave Grove * @author Derek Lieber * @modified Ian Rogers */ -public class VM_NormalMethod - extends VM_Method - implements VM_BytecodeConstants -{ +public class VM_NormalMethod extends VM_Method implements VM_BytecodeConstants { - /* As we read the bytecodes for the method, we compute - * a simple summary of some interesting properties of the method. - * Because we do this for every method, we require the summarization to - * be fast and the computed summary to be very space efficient. + /* + * As we read the bytecodes for the method, we compute a simple summary of + * some interesting properties of the method. Because we do this for every + * method, we require the summarization to be fast and the computed summary to + * be very space efficient. * - * The following constants encode the estimated relative cost in - * machine instructions when a particular class of bytecode is compiled - * by the optimizing compiler. The estimates approximate the typical - * optimization the compiler is able to perform. - * This information is used to estimate how big a method will be when - * it is inlined. + * The following constants encode the estimated relative cost in machine + * instructions when a particular class of bytecode is compiled by the + * optimizing compiler. The estimates approximate the typical optimization the + * compiler is able to perform. This information is used to estimate how big a + * method will be when it is inlined. */ public static final int SIMPLE_OPERATION_COST = 1; + public static final int LONG_OPERATION_COST = 2; + public static final int ARRAY_LOAD_COST = 2; + public static final int ARRAY_STORE_COST = 2; + public static final int JSR_COST = 5; + public static final int CALL_COST = 6; + // Bias to inlining methods with magic // most magics are quite cheap (0-1 instructions) public static final int MAGIC_COST = 0; + // News are actually more expensive than calls // but bias to inline methods that allocate - // objects becuase we expect better downstream optimization of + // objects becuase we expect better downstream optimization of // the caller due to class analysis // and propagation of nonNullness public static final int ALLOCATION_COST = 4; + // Approximations, assuming some CSE/PRE of object model computations - public static final int CLASS_CHECK_COST = 2*SIMPLE_OPERATION_COST; - public static final int STORE_CHECK_COST = 4*SIMPLE_OPERATION_COST; + public static final int CLASS_CHECK_COST = 2 * SIMPLE_OPERATION_COST; + + public static final int STORE_CHECK_COST = 4 * SIMPLE_OPERATION_COST; + // Just a call. public static final int THROW_COST = CALL_COST; + // Really a bunch of operations plus a call, but undercharge because // we don't have worry about this causing an exponential growth of call chain - // and we probably want to inline synchronization + // and we probably want to inline synchronization // (to get a chance to optimize it). - public static final int SYNCH_COST = 4*SIMPLE_OPERATION_COST; - // The additional cost of a switch isn't that large, since if the - // switch has more than a few cases the method will be too big to inline + public static final int SYNCH_COST = 4 * SIMPLE_OPERATION_COST; + + // The additional cost of a switch isn't that large, since if the + // switch has more than a few cases the method will be too big to inline // anyways. public static final int SWITCH_COST = CALL_COST; // Definition of flag bits - protected static final char HAS_MAGIC = 0x8000; - protected static final char HAS_SYNCH = 0x4000; + protected static final char HAS_MAGIC = 0x8000; + + protected static final char HAS_SYNCH = 0x4000; + protected static final char HAS_ALLOCATION = 0x2000; - protected static final char HAS_THROW = 0x1000; - protected static final char HAS_INVOKE = 0x0800; + + protected static final char HAS_THROW = 0x1000; + + protected static final char HAS_INVOKE = 0x0800; + protected static final char HAS_FIELD_READ = 0x0400; - protected static final char HAS_FIELD_WRITE= 0x0200; + + protected static final char HAS_FIELD_WRITE = 0x0200; + protected static final char HAS_ARRAY_READ = 0x0100; - protected static final char HAS_ARRAY_WRITE= 0x0080; - protected static final char HAS_JSR = 0x0040; - protected static final char HAS_COND_BRANCH= 0x0020; - protected static final char HAS_SWITCH = 0x0010; - protected static final char HAS_BACK_BRANCH= 0x0008; - protected static final char IS_RS_METHOD = 0x0004; - + + protected static final char HAS_ARRAY_WRITE = 0x0080; + + protected static final char HAS_JSR = 0x0040; + + protected static final char HAS_COND_BRANCH = 0x0020; + + protected static final char HAS_SWITCH = 0x0010; + + protected static final char HAS_BACK_BRANCH = 0x0008; + + protected static final char IS_RS_METHOD = 0x0004; + /** * storage for bytecode summary flags */ protected char summaryFlags; + /** * storage for bytecode summary size */ @@ -99,68 +122,83 @@ /** * words needed for local variables (including parameters) */ - private final short localWords; + private final short localWords; /** - * words needed for operand stack (high water mark) - * TODO: OSR redesign; add subclass of NormalMethod for OSR method - * and then make this field final in NormalMethod. + * words needed for operand stack (high water mark) TODO: OSR redesign; add + * subclass of NormalMethod for OSR method and then make this field final in + * NormalMethod. */ - private short operandWords; + private short operandWords; /** * bytecodes for this method (null --> none) */ - public final byte[] bytecodes; + public final byte[] bytecodes; /** * try/catch/finally blocks for this method (null --> none) */ - private final VM_ExceptionHandlerMap exceptionHandlerMap; + private final VM_ExceptionHandlerMap exceptionHandlerMap; /** - * pc to source-line info (null --> none) - * Each entry contains both the line number (upper 16 bits) - * and corresponding start PC (lower 16 bits). + * pc to source-line info (null --> none) Each entry contains both the line + * number (upper 16 bits) and corresponding start PC (lower 16 bits). */ - private final int[] lineNumberMap; + private final int[] lineNumberMap; // Extra fields for on-stack replacement - // TODO: rework the system so we don't waste space for this on the VM_Method object + //... [truncated message content] |
From: <mic...@us...> - 2007-04-02 12:41:04
|
Revision: 20 http://svn.sourceforge.net/pearcolator/?rev=20&view=rev Author: michael_baer Date: 2007-04-02 05:41:02 -0700 (Mon, 02 Apr 2007) Log Message: ----------- Replaced VM._assert with DBT._assert Modified Paths: -------------- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java src/org/binarytranslator/generic/decoder/DecoderUtils.java Added Paths: ----------- src/org/binarytranslator/DBT.java src/org/binarytranslator/arch/arm/decoder/ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java Removed Paths: ------------- ext/org/jikesrvm/VM_RuntimeCompiler.java Deleted: ext/org/jikesrvm/VM_RuntimeCompiler.java =================================================================== --- ext/org/jikesrvm/VM_RuntimeCompiler.java 2007-04-02 12:11:23 UTC (rev 19) +++ ext/org/jikesrvm/VM_RuntimeCompiler.java 2007-04-02 12:41:02 UTC (rev 20) @@ -1,775 +0,0 @@ -/* - * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net). - * The Jikes RVM project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright IBM Corp. 2001, 2005 - */ -package org.jikesrvm; - -import org.jikesrvm.classloader.*; -import org.jikesrvm.opt.*; -import org.jikesrvm.adaptive.*; -import org.jikesrvm.ArchitectureSpecific.VM_JNICompiler; -import org.jikesrvm.runtime.VM_Time; -import org.jikesrvm.scheduler.VM_Thread; - -/** - * Harness to select which compiler to dynamically - * compile a method in first invocation. - * - * A place to put code common to all runtime compilers. - * This includes instrumentation code to get equivalent data for - * each of the runtime compilers. - * <p> - * We collect the following data for each compiler - * <ol> - * <li> - * total number of methods complied by the compiler - * <li> - * total compilation time in milliseconds. - * <li> - * total number of bytes of bytecodes compiled by the compiler - * (under the assumption that there is no padding in the bytecode - * array and thus VM_Method.getBytecodes().length is the number bytes - * of bytecode for a method) - * <li> - * total number of machine code insructions generated by the compiler - * (under the assumption that there is no (excessive) padding in the - * machine code array and thus VM_CompiledMethod.numberOfInsturctions() - * is a close enough approximation of the number of machinecodes generated) - * </ol> - * Note that even if 3. & 4. are inflated due to padding, the numbers will - * still be an accurate measure of the space costs of the compile-only - * approach. - * - * @author Matthew Arnold - * @author Dave Grove - * @author Michael Hind - */ -public class VM_RuntimeCompiler implements VM_Constants, - VM_Callbacks.ExitMonitor { - - // Use these to encode the compiler for record() - public static final byte JNI_COMPILER = 0; - public static final byte BASELINE_COMPILER = 1; - public static final byte OPT_COMPILER = 2; - - // Data accumulators - private static final String[] name = {"JNI\t","Base\t","Opt\t"}; // Output names - private static int[] totalMethods = {0,0,0}; - private static double[] totalCompTime = {0,0,0}; - private static int[] totalBCLength = {0,0,0}; - private static int[] totalMCLength = {0,0,0}; - - // running sum of the natural logs of the rates, - // used for geometric mean, the product of rates is too big for doubles - // so we use the principle of logs to help us - // We compute e ** ((log a + log b + ... + log n) / n ) - private static double[] totalLogOfRates = {0,0,0}; - - // We can't record values until Math.log is loaded, so we miss the first few - private static int[] totalLogValueMethods = {0,0,0}; - - private static String[] earlyOptArgs = new String[0]; - - // is the opt compiler usable? - protected static boolean compilerEnabled; - - // is opt compiler currently in use? - // This flag is used to detect/avoid recursive opt compilation. - // (ie when opt compilation causes a method to be compiled). - // We also make all public entrypoints static synchronized methods - // because the opt compiler is not reentrant. - // When we actually fix defect 2912, we'll have to implement a different - // scheme that can distinguish between recursive opt compilation by the same - // thread (always bad) and parallel opt compilation (currently bad, future ok). - // NOTE: This code can be quite subtle, so please be absolutely sure - // you know what you're doing before modifying it!!! - protected static boolean compilationInProgress; - - // One time check to optionally preload and compile a specified class - protected static boolean preloadChecked = false; - - // Cache objects needed to cons up compilation plans - // TODO: cutting link to opt compiler by declaring type as object. - public static Object /* OPT_Options */ options; - public static Object /* OPT_OptimizationPlanElement[] */ optimizationPlan; - - /** - * To be called when the VM is about to exit. - * @param value the exit value - */ - public void notifyExit(int value) { - report(false); - } - - /** - * This method records the time and sizes (bytecode and machine code) for - * a compilation. - * @param compiler the compiler used - * @param method the resulting VM_Method - * @param compiledMethod the resulting compiled method - */ - public static void record(byte compiler, - VM_NormalMethod method, - VM_CompiledMethod compiledMethod) { - - recordCompilation(compiler, method.getBytecodeLength(), - compiledMethod.numberOfInstructions(), - compiledMethod.getCompilationTime()); - - if (VM.BuildForAdaptiveSystem) { - if (VM_AOSLogging.booted()) { - VM_AOSLogging.recordUpdatedCompilationRates(compiler, - method, - method.getBytecodeLength(), - totalBCLength[compiler], - compiledMethod.numberOfInstructions(), - totalMCLength[compiler], - compiledMethod.getCompilationTime(), - totalCompTime[compiler], - totalLogOfRates[compiler], - totalLogValueMethods[compiler], - totalMethods[compiler]); - } - } - } - - /** - * This method records the time and sizes (bytecode and machine code) for - * a compilation - * @param compiler the compiler used - * @param method the resulting VM_Method - * @param compiledMethod the resulting compiled method - */ - public static void record(byte compiler, - VM_NativeMethod method, - VM_CompiledMethod compiledMethod) { - - - recordCompilation(compiler, - 0, // don't have any bytecode info, its native - compiledMethod.numberOfInstructions(), - compiledMethod.getCompilationTime()); - } - - /** - * This method does the actual recording - * @param compiler the compiler used - * @param BCLength the number of bytecodes in method source - * @param MCLength the length of the generated machine code - * @param compTime the compilation time in ms - */ - private static void recordCompilation(byte compiler, - int BCLength, - int MCLength, - double compTime) { - - totalMethods[compiler]++; - totalMCLength[compiler] += MCLength; - totalCompTime[compiler] += compTime; - - // Comp rate not useful for JNI compiler because there is no bytecode! - if (compiler != JNI_COMPILER) { - totalBCLength[compiler] += BCLength; - double rate = BCLength / compTime; - - // need to be fully booted before calling log - if (VM.fullyBooted) { - // we want the geometric mean, but the product of rates is too big - // for doubles, so we use the principle of logs to help us - // We compute e ** ((log a + log b + ... + log n) / n ) - totalLogOfRates[compiler] += Math.log(rate); - totalLogValueMethods[compiler]++; - } - } - } - - /** - * This method produces a summary report of compilation activities - * @param explain Explains the metrics used in the report - */ - public static void report (boolean explain) { - VM.sysWrite("\n\t\tCompilation Subsystem Report\n"); - VM.sysWrite("Comp\t#Meths\tTime\tbcb/ms\tmcb/bcb\tMCKB\tBCKB\n"); - for (int i=0; i<=name.length-1; i++) { - if (totalMethods[i]>0) { - VM.sysWrite(name[i]); - // Number of methods - VM.sysWrite(totalMethods[i]); - VM.sysWrite("\t"); - // Compilation time - VM.sysWrite(totalCompTime[i]); - VM.sysWrite("\t"); - - if (i == JNI_COMPILER) { - VM.sysWrite("NA"); - } else { - // Bytecode bytes per millisecond, - // use unweighted geomean - VM.sysWrite(Math.exp(totalLogOfRates[i] / totalLogValueMethods[i]), 2); - } - VM.sysWrite("\t"); - // Ratio of machine code bytes to bytecode bytes - if (i != JNI_COMPILER) { - VM.sysWrite((double)(totalMCLength[i] << ArchitectureSpecific.VM_RegisterConstants.LG_INSTRUCTION_WIDTH)/(double)totalBCLength[i], 2); - } else { - VM.sysWrite("NA"); - } - VM.sysWrite("\t"); - // Generated machine code Kbytes - VM.sysWrite((double)(totalMCLength[i] << ArchitectureSpecific.VM_RegisterConstants.LG_INSTRUCTION_WIDTH)/1024, 1); - VM.sysWrite("\t"); - // Compiled bytecode Kbytes - if (i != JNI_COMPILER) { - VM.sysWrite((double)totalBCLength[i]/1024, 1); - } else { - VM.sysWrite("NA"); - } - VM.sysWrite("\n"); - } - } - if (explain) { - // Generate an explanation of the metrics reported - VM.sysWrite("\t\t\tExplanation of Metrics\n"); - VM.sysWrite("#Meths:\t\tTotal number of methods compiled by the compiler\n"); - VM.sysWrite("Time:\t\tTotal compilation time in milliseconds\n"); - VM.sysWrite("bcb/ms:\t\tNumber of bytecode bytes complied per millisecond\n"); - VM.sysWrite("mcb/bcb:\tRatio of machine code bytes to bytecode bytes\n"); - VM.sysWrite("MCKB:\t\tTotal number of machine code bytes generated in kilobytes\n"); - VM.sysWrite("BCKB:\t\tTotal number of bytecode bytes compiled in kilobytes\n"); - } - - VM_BaselineCompiler.generateBaselineCompilerSubsystemReport(explain); - - if (VM.BuildForAdaptiveSystem) { - // Get the opt's report - VM_TypeReference theTypeRef = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom.findOrCreateAsciiAtom("Lorg/jikesrvm/opt/OPT_OptimizationPlanner;")); - VM_Type theType = theTypeRef.peekResolvedType(); - if (theType != null && theType.asClass().isInitialized()) { - OPT_OptimizationPlanner.generateOptimizingCompilerSubsystemReport(explain); - } else { - VM.sysWrite("\n\tNot generating Optimizing Compiler SubSystem Report because \n"); - VM.sysWrite("\tthe opt compiler was never invoked.\n\n"); - } - } - } - - /** - * Return the current estimate of basline-compiler rate, in bcb/msec - */ - public static double getBaselineRate() { - return Math.exp(totalLogOfRates[BASELINE_COMPILER] / totalLogValueMethods[BASELINE_COMPILER]); - } - - /** - * This method will compile the passed method using the baseline compiler. - * @param method the method to compile - */ - public static VM_CompiledMethod baselineCompile(VM_NormalMethod method) { - VM_Callbacks.notifyMethodCompile(method, VM_CompiledMethod.BASELINE); - long start = 0; - if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { - start = VM_Thread.getCurrentThread().accumulateCycles(); - } - - VM_CompiledMethod cm = VM_BaselineCompiler.compile(method); - - if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { - long end = VM_Thread.getCurrentThread().accumulateCycles(); - double compileTime = VM_Time.cyclesToMillis(end - start); - cm.setCompilationTime(compileTime); - record(BASELINE_COMPILER, method, cm); - } - - return cm; - } - - /** - * Process command line argument destined for the opt compiler - */ - public static void processOptCommandLineArg(String prefix, String arg) { - if (VM.BuildForAdaptiveSystem) { - if (compilerEnabled) { - if (((OPT_Options)options).processAsOption(prefix, arg)) { - // update the optimization plan to reflect the new command line argument - optimizationPlan = OPT_OptimizationPlanner.createOptimizationPlan((OPT_Options)options); - } else { - VM.sysWrite("Unrecognized opt compiler argument \""+arg+"\""); - VM.sysExit(VM.EXIT_STATUS_BOGUS_COMMAND_LINE_ARG); - } - } else { - String[] tmp = new String[earlyOptArgs.length+2]; - for (int i=0; i<earlyOptArgs.length; i++) { - tmp[i] = earlyOptArgs[i]; - } - earlyOptArgs = tmp; - earlyOptArgs[earlyOptArgs.length-2] = prefix; - earlyOptArgs[earlyOptArgs.length-1] = arg; - } - } else { - if (VM.VerifyAssertions) VM._assert(NOT_REACHED); - } - } - - /** - * attempt to compile the passed method with the OPT_Compiler. - * Don't handle OPT_OptimizingCompilerExceptions - * (leave it up to caller to decide what to do) - * Precondition: compilationInProgress "lock" has been acquired - * @param method the method to compile - * @param plan the plan to use for compiling the method - */ - private static VM_CompiledMethod optCompile(VM_NormalMethod method, - OPT_CompilationPlan plan) - throws OPT_OptimizingCompilerException { - if (VM.BuildForOptCompiler) { - if (VM.VerifyAssertions) { - VM._assert(compilationInProgress, "Failed to acquire compilationInProgress \"lock\""); - } - - VM_Callbacks.notifyMethodCompile(method, VM_CompiledMethod.JNI); - long start = 0; - if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { - start = VM_Thread.getCurrentThread().accumulateCycles(); - } - - VM_CompiledMethod cm = OPT_Compiler.compile(plan); - - if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { - long end = VM_Thread.getCurrentThread().accumulateCycles(); - double compileTime = VM_Time.cyclesToMillis(end - start); - cm.setCompilationTime(compileTime); - record(OPT_COMPILER, method, cm); - } - - return cm; - } else { - if (VM.VerifyAssertions) VM._assert(false); - return null; - } - } - - - // These methods are safe to invoke from VM_RuntimeCompiler.compile - - /** - * This method tries to compile the passed method with the OPT_Compiler, - * using the default compilation plan. If - * this fails we will use the quicker compiler (baseline for now) - * The following is carefully crafted to avoid (infinte) recursive opt - * compilation for all combinations of bootimages & lazy/eager compilation. - * Be absolutely sure you know what you're doing before changing it !!! - * @param method the method to compile - */ - public static synchronized VM_CompiledMethod optCompileWithFallBack(VM_NormalMethod method) { - if (VM.BuildForOptCompiler) { - if (compilationInProgress) { - return fallback(method); - } else { - try { - compilationInProgress = true; - OPT_CompilationPlan plan = new OPT_CompilationPlan(method, (OPT_OptimizationPlanElement[])optimizationPlan, null, (OPT_Options)options); - return optCompileWithFallBackInternal(method, plan); - } finally { - compilationInProgress = false; - } - } - } else { - if (VM.VerifyAssertions) VM._assert(false); - return null; - } - } - - /** - * This method tries to compile the passed method with the OPT_Compiler - * with the passed compilation plan. If - * this fails we will use the quicker compiler (baseline for now) - * The following is carefully crafted to avoid (infinte) recursive opt - * compilation for all combinations of bootimages & lazy/eager compilation. - * Be absolutely sure you know what you're doing before changing it !!! - * @param method the method to compile - * @param plan the compilation plan to use for the compile - */ - public static synchronized VM_CompiledMethod optCompileWithFallBack(VM_NormalMethod method, - OPT_CompilationPlan plan) { - if (VM.BuildForOptCompiler) { - if (compilationInProgress) { - return fallback(method); - } else { - try { - compilationInProgress = true; - return optCompileWithFallBackInternal(method, plan); - } finally { - compilationInProgress = false; - } - } - } else { - if (VM.VerifyAssertions) VM._assert(false); - return null; - } - } - - /** - * This real method that performs the opt compilation. - * @param method the method to compile - * @param plan the compilation plan to use - */ - private static VM_CompiledMethod optCompileWithFallBackInternal(VM_NormalMethod method, - OPT_CompilationPlan plan) { - if (VM.BuildForOptCompiler) { - if (method.hasNoOptCompileAnnotation()) return fallback(method); - try { - return optCompile(method, plan); - } catch (OPT_OptimizingCompilerException e) { - String msg = "VM_RuntimeCompiler: can't optimize \"" + method + "\" (error was: " + e + "): reverting to baseline compiler\n"; - if (e.isFatal && VM.ErrorsFatal) { - e.printStackTrace(); - VM.sysFail(msg); - } else { - boolean printMsg = true; - if (e instanceof OPT_MagicNotImplementedException) { - printMsg = !((OPT_MagicNotImplementedException)e).isExpected; - } - if (printMsg) VM.sysWrite(msg); - } - return fallback(method); - } - } else { - if (VM.VerifyAssertions) VM._assert(false); - return null; - } - } - - - /* recompile the specialized method with OPT_Compiler. */ - public static VM_CompiledMethod recompileWithOptOnStackSpecialization(OPT_CompilationPlan plan) { - if (VM.BuildForOptCompiler) { - if (VM.VerifyAssertions) { VM._assert(plan.method.isForOsrSpecialization());} - if (compilationInProgress) { - return null; - } - - try { - compilationInProgress = true; - - // the compiler will check if isForOsrSpecialization of the method - VM_CompiledMethod cm = optCompile(plan.method, plan); - - // we donot replace the compiledMethod of original method, - // because it is temporary method - return cm; - } catch (OPT_OptimizingCompilerException e) { - e.printStackTrace(); - String msg = "Optimizing compiler " - +"(via recompileWithOptOnStackSpecialization): " - +"can't optimize \"" + plan.method + "\" (error was: " + e + ")\n"; - - if (e.isFatal && VM.ErrorsFatal) { - VM.sysFail(msg); - } else { - VM.sysWrite(msg); - } - return null; - } finally { - compilationInProgress = false; - } - } else { - if (VM.VerifyAssertions) VM._assert(false); - return null; - } - } - - /** - * This method tries to compile the passed method with the OPT_Compiler. - * It will install the new compiled method in the VM, if sucessful. - * NOTE: the recompile method should never be invoked via - * VM_RuntimeCompiler.compile; - * it does not have sufficient guards against recursive recompilation. - * @param plan the compilation plan to use - * @return the CMID of the new method if successful, -1 if the - * recompilation failed. - * - **/ - public static synchronized int recompileWithOpt(OPT_CompilationPlan plan) { - if (VM.BuildForOptCompiler) { - if (compilationInProgress) { - return -1; - } else { - try { - compilationInProgress = true; - VM_CompiledMethod cm = optCompile(plan.method, plan); - try { - plan.method.replaceCompiledMethod(cm); - } catch (Throwable e) { - String msg = "Failure in VM_Method.replaceCompiledMethod (via recompileWithOpt): while replacing \"" + plan.method + "\" (error was: " + e + ")\n"; - if (VM.ErrorsFatal) { - e.printStackTrace(); - VM.sysFail(msg); - } else { - VM.sysWrite(msg); - } - return -1; - } - return cm.getId(); - } catch (OPT_OptimizingCompilerException e) { - String msg = "Optimizing compiler (via recompileWithOpt): can't optimize \"" + plan.method + "\" (error was: " + e + ")\n"; - if (e.isFatal && VM.ErrorsFatal) { - e.printStackTrace(); - VM.sysFail(msg); - } else { - // VM.sysWrite(msg); - } - return -1; - } finally { - compilationInProgress = false; - } - } - } else { - if (VM.VerifyAssertions) VM._assert(false); - return -1; - } - } - - /** - * A wrapper method for those callers who don't want to make - * optimization plans - * @param method the method to recompile - */ - public static int recompileWithOpt(VM_NormalMethod method) { - if (VM.BuildForOptCompiler) { - OPT_CompilationPlan plan = new OPT_CompilationPlan(method, - (OPT_OptimizationPlanElement[])optimizationPlan, - null, - (OPT_Options)options); - return recompileWithOpt(plan); - } else { - if (VM.VerifyAssertions) VM._assert(false); - return -1; - } - } - - /** - * This method uses the default compiler (baseline) to compile a method - * It is typically called when a more aggressive compilation fails. - * This method is safe to invoke from VM_RuntimeCompiler.compile - */ - protected static VM_CompiledMethod fallback(VM_NormalMethod method) { - // call the inherited method "baselineCompile" - return baselineCompile(method); - } - - public static void boot() { - if (VM.MeasureCompilation) { - VM_Callbacks.addExitMonitor(new VM_RuntimeCompiler()); - } - if (VM.BuildForAdaptiveSystem) { - options = new OPT_Options(); - optimizationPlan = OPT_OptimizationPlanner.createOptimizationPlan((OPT_Options)options); - if (VM.MeasureCompilation) { - OPT_OptimizationPlanner.initializeMeasureCompilation(); - } - - OPT_Compiler.init((OPT_Options)options); - - VM_PreCompile.init(); - // when we reach here the OPT compiler is enabled. - compilerEnabled = true; - - for (int i=0; i<earlyOptArgs.length; i+=2) { - processOptCommandLineArg(earlyOptArgs[i], earlyOptArgs[i+1]); - } - } - } - - public static void processCommandLineArg(String prefix, String arg) { - if (VM.BuildForAdaptiveSystem) { - if (VM_Controller.options !=null && VM_Controller.options.optIRC()) { - processOptCommandLineArg(prefix, arg); - } else { - VM_BaselineCompiler.processCommandLineArg(prefix, arg); - } - } else { - VM_BaselineCompiler.processCommandLineArg(prefix, arg); - } - } - - /** - * Compile a Java method when it is first invoked. - * @param method the method to compile - * @return its compiled method. - */ - public static VM_CompiledMethod compile(VM_NormalMethod method) { - if (VM.BuildForAdaptiveSystem) { - VM_CompiledMethod cm; - if (!VM_Controller.enabled) { - // System still early in boot process; compile with baseline compiler - cm = baselineCompile(method); - VM_ControllerMemory.incrementNumBase(); - } else { - if (!preloadChecked) { - preloadChecked = true; // prevent subsequent calls - // N.B. This will use irc options - if (VM_BaselineCompiler.options.PRELOAD_CLASS != null) { - compilationInProgress = true; // use baseline during preload - // Other than when boot options are requested (processed during preloadSpecialClass - // It is hard to communicate options for these special compilations. Use the - // default options and at least pick up the verbose if requested for base/irc - OPT_Options tmpoptions = (OPT_Options)((OPT_Options)options).clone(); - tmpoptions.PRELOAD_CLASS = VM_BaselineCompiler.options.PRELOAD_CLASS; - tmpoptions.PRELOAD_AS_BOOT = VM_BaselineCompiler.options.PRELOAD_AS_BOOT; - if (VM_BaselineCompiler.options.PRINT_METHOD) { - tmpoptions.PRINT_METHOD = true; - } else { - tmpoptions = (OPT_Options)options; - } - OPT_Compiler.preloadSpecialClass(tmpoptions); - compilationInProgress = false; - } - } - if (VM_Controller.options.optIRC() || method.optCompileOnly()) { - if (// will only run once: don't bother optimizing - method.isClassInitializer() || - // exception in progress. can't use opt compiler: - // it uses exceptions and runtime doesn't support - // multiple pending (undelivered) exceptions [--DL] - VM_Thread.getCurrentThread().hardwareExceptionRegisters.inuse) { - // compile with baseline compiler - cm = baselineCompile(method); - VM_ControllerMemory.incrementNumBase(); - } else { // compile with opt compiler - VM_AOSInstrumentationPlan instrumentationPlan = - new VM_AOSInstrumentationPlan(VM_Controller.options, method); - OPT_CompilationPlan compPlan = - new OPT_CompilationPlan(method, (OPT_OptimizationPlanElement[])optimizationPlan, - instrumentationPlan, (OPT_Options)options); - if(!method.optCompileOnly()) { - cm = optCompileWithFallBack(method, compPlan); - } - else { - compilationInProgress = true; - try { - cm = optCompile(method, compPlan); - } catch (OPT_OptimizingCompilerException e) { - String msg = "Optimizing compiler " - +"(on method that can only be optimizing compiler compiled): " - +"can't optimize \"" + method + "\""; - throw new Error(msg, e); - } finally { - compilationInProgress = false; - } - } - } - } else { - if ((VM_Controller.options.BACKGROUND_RECOMPILATION - && (!VM_Controller.options.ENABLE_REPLAY_COMPILE) - && (!VM_Controller.options.ENABLE_PRECOMPILE)) - ) { - // must be an inital compilation: compile with baseline compiler - // or if recompilation with OSR. - cm = baselineCompile(method); - VM_ControllerMemory.incrementNumBase(); - } else { - if (VM_CompilerAdviceAttribute.hasAdvice()) { - VM_CompilerAdviceAttribute attr = - VM_CompilerAdviceAttribute.getCompilerAdviceInfo(method); - if (attr.getCompiler() != VM_CompiledMethod.OPT) { - cm=fallback(method); - VM_AOSLogging.recordCompileTime(cm, 0.0); - return cm; - } - int newCMID = -2; - OPT_CompilationPlan compPlan; - if (VM_Controller.options.counters()) { - // for invocation counter, we only use one optimization level - compPlan = VM_InvocationCounts.createCompilationPlan(method); - } else { - // for now there is not two options for sampling, so - // we don't have to use: if (VM_Controller.options.sampling()) - compPlan = VM_Controller.recompilationStrategy.createCompilationPlan(method, attr.getOptLevel(), null); - } - VM_AOSLogging.recompilationStarted(compPlan); - newCMID = recompileWithOpt(compPlan); - cm = newCMID == -1 ? null : VM_CompiledMethods.getCompiledMethod(newCMID); - if (newCMID == -1) { - VM_AOSLogging.recompilationAborted(compPlan); - } else if (newCMID > 0) { - VM_AOSLogging.recompilationCompleted(compPlan); - } - if (cm == null) { // if recompilation is aborted - cm = baselineCompile(method); - VM_ControllerMemory.incrementNumBase(); - } - } else { - // check to see if there is a compilation plan for this method. - VM_ControllerPlan plan = VM_ControllerMemory.findLatestPlan(method); - if (plan == null || plan.getStatus() != VM_ControllerPlan.IN_PROGRESS) { - // initial compilation or some other funny state: compile with baseline compiler - cm = baselineCompile(method); - VM_ControllerMemory.incrementNumBase(); - } else { - cm = plan.doRecompile(); - if (cm == null) { - // opt compilation aborted for some reason. - cm = baselineCompile(method); - } - } - } - } - } - } - if ((VM_Controller.options.ENABLE_ADVICE_GENERATION) - && (cm.getCompilerType() == VM_CompiledMethod.BASELINE) - && VM_Controller.enabled) { - VM_AOSGenerator.baseCompilationCompleted(cm); - } - VM_AOSLogging.recordCompileTime(cm, 0.0); - return cm; - } else { - return baselineCompile(method); - } - } - - /** - * Compile the stub for a native method when it is first invoked. - * @param method the method to compile - * @return its compiled method. - */ - public static VM_CompiledMethod compile(VM_NativeMethod method) { - VM_Callbacks.notifyMethodCompile(method, VM_CompiledMethod.JNI); - long start = 0; - if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { - start = VM_Thread.getCurrentThread().accumulateCycles(); - } - - VM_CompiledMethod cm = VM_JNICompiler.compile(method); - if (VM.verboseJNI) { - VM.sysWriteln("[Dynamic-linking native method " + - method.getDeclaringClass() + "." + method.getName() + - " "+method.getDescriptor()); - } - - if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { - long end = VM_Thread.getCurrentThread().accumulateCycles(); - double compileTime = VM_Time.cyclesToMillis(end - start); - cm.setCompilationTime(compileTime); - record(JNI_COMPILER, method, cm); - } - - return cm; - } - - /** - * returns the string version of compiler number, using the naming scheme - * in this file - * @param compiler the compiler of interest - * @return the string version of compiler number - */ - public static String getCompilerName(byte compiler) { - return name[compiler]; - } - -} Added: src/org/binarytranslator/DBT.java =================================================================== --- src/org/binarytranslator/DBT.java (rev 0) +++ src/org/binarytranslator/DBT.java 2007-04-02 12:41:02 UTC (rev 20) @@ -0,0 +1,33 @@ +package org.binarytranslator; + +import org.jikesrvm.VM; + +public final class DBT { + public static final boolean VerifyAssertions = true; + + public static void _assert(boolean cond) { + + if (!VerifyAssertions) + return; + + if (VM.VerifyAssertions) + VM._assert(cond); + else + { + if (!cond) { + //assertion failed, see if we can get some info on where the assertion occured + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + + if (trace.length > 0) { + StackTraceElement source = trace[trace.length-1]; + System.err.println("Assertion failed in: " + source.getFileName() + "(" + source.getLineNumber() + ")"); + } + else { + System.err.println("Assertion failed. No stack trace on assertion source available."); + } + + System.exit(-1); + } + } + } +} Added: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-04-02 12:41:02 UTC (rev 20) @@ -0,0 +1,185 @@ +package org.binarytranslator.arch.arm.decoder; + +import java.util.ArrayList; + +import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.generic.decoder.DecoderUtils; +import org.binarytranslator.generic.decoder.Laziness; +import org.jikesrvm.classloader.VM_Atom; +import org.jikesrvm.classloader.VM_FieldReference; +import org.jikesrvm.classloader.VM_MemberReference; +import org.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.compilers.opt.ir.*; + +public class ARM2IR extends DecoderUtils implements OPT_HIRGenerator { + + /** Mapping of ARM registers to HIR registers */ + protected OPT_Register regMap[] = new OPT_Register[16]; + + /** Set to true for each register that is in use during the current trace */ + protected boolean regUsed[] = new boolean[16]; + + /** Type reference to the ARM process space */ + private static final VM_TypeReference psTref; + + /** A field reference to the ARM registers class within the PS */ + private static final VM_FieldReference registersFref; + + /** A type reference to the ARM registers class */ + private static final VM_TypeReference registersTref; + + /** A field reference to the ARM registers array within the ARM_Registers class */ + private static final VM_FieldReference registers_regs_Fref; + + /** A type reference to the ARM registers array within the ARM_Registers class */ + private static final VM_TypeReference registers_regs_Tref; + + /** A register holding a reference to ps.registers */ + private OPT_Register ps_registers; + + /** A register holding a reference to ps.registers.regs */ + private OPT_Register ps_registers_regs; + + + static { + psTref = VM_TypeReference.findOrCreate(ARM_ProcessSpace.class); + + registersFref = VM_MemberReference + .findOrCreate( + psTref, + VM_Atom.findOrCreateAsciiAtom("registers"), + VM_Atom + .findOrCreateAsciiAtom("Lorg/binarytranslator/arch/arm/os/process/ARM_Registers;")) + .asFieldReference(); + + if (DBT.VerifyAssertions) DBT._assert(registersFref != null); + + registersTref = registersFref.getFieldContentsType(); + + if (DBT.VerifyAssertions) DBT._assert(registersTref != null); + + registers_regs_Fref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("regs"), + VM_Atom.findOrCreateAsciiAtom("[I")).asFieldReference(); + + if (DBT.VerifyAssertions) DBT._assert(registers_regs_Fref != null); + + registers_regs_Tref = registers_regs_Fref.getFieldContentsType(); + + if (DBT.VerifyAssertions) DBT._assert(registers_regs_Tref != null); + } + + + public ARM2IR(OPT_GenerationContext context) { + super(context); + } + + @Override + protected Laziness createInitialLaziness() { + return new ARM_Laziness(); + } + + @Override + protected void fillAllRegisters() { + + OPT_RegisterOperand ps_registersOp; + + if (ps_registers != null) { + ps_registersOp = gc.temps.makeTemp(registersTref); + ps_registers = ps_registersOp.register; + appendInstructionToCurrentBlock(GetField.create(GETFIELD, ps_registersOp, + gc.makeLocal(1, psTref), new OPT_AddressConstantOperand(registersFref + .peekResolvedField().getOffset()), new OPT_LocationOperand( + registersFref), new OPT_TrueGuardOperand())); + } + else { + ps_registersOp = new OPT_RegisterOperand(ps_registers, registersTref); + } + + // Get the array of general purpose registers + OPT_RegisterOperand ps_registers_regsOp; + if (ps_registers_regs == null) { + + ps_registers_regsOp = gc.temps.makeTemp(registers_regs_Tref); + appendInstructionToCurrentBlock(GetField.create(GETFIELD, + ps_registers_regsOp, ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(registers_regs_Fref.peekResolvedField() + .getOffset()), new OPT_LocationOperand(registers_regs_Fref), + new OPT_TrueGuardOperand())); + ps_registers_regs = ps_registers_regsOp.register; + } else { + ps_registers_regsOp = new OPT_RegisterOperand(ps_registers_regs, registers_regs_Tref); + } + + // Fill general purpose registers + for (int i = 0; i < regMap.length; i++) { + OPT_RegisterOperand regOp; + if (regMap[i] == null) { + regOp = makeTemp(VM_TypeReference.Int); + regMap[i] = regOp.register; + } else { + regOp = new OPT_RegisterOperand(regMap[i], VM_TypeReference.Int); + } + appendInstructionToCurrentBlock(ALoad.create(INT_ALOAD, regOp, + ps_registers_regsOp.copyRO(), new OPT_IntConstantOperand(i), + new OPT_LocationOperand(VM_TypeReference.Int), + new OPT_TrueGuardOperand())); + } + } + + public OPT_RegisterOperand getRegister(int r) { + regUsed[r] = true; + return new OPT_RegisterOperand(regMap[r], VM_TypeReference.Int); + } + + @Override + protected OPT_Register[] getUnusedRegisters() { + + ArrayList<OPT_Register> unusedRegisters = new ArrayList<OPT_Register>(); + + for (int i = 0; i < regUsed.length; i++) + if (!regUsed[i]) { + unusedRegisters.add(regMap[i]); + } + + return unusedRegisters.toArray(new OPT_Register[unusedRegisters.size()]); + } + + @Override + protected void report(String str) { + System.out.println("ARM2IR: " + str); + } + + @Override + public void resolveLaziness(Laziness laziness) { + //NO-OP, as we're not using laziness at the moment + } + + @Override + protected void spillAllRegisters() { + + // spill general purpose registers + OPT_RegisterOperand ps_registers_regsOp = new OPT_RegisterOperand( + ps_registers_regs, registers_regs_Tref); + for (int i = 0; i < regMap.length; i++) { + // We can save spills if the trace has no syscalls and the register was + // never used + if ((DBT_Options.singleInstrTranslation == false) + || (regUsed[i] == true)) { + appendInstructionToCurrentBlock(AStore.create(INT_ASTORE, + new OPT_RegisterOperand(regMap[i], VM_TypeReference.Int), + ps_registers_regsOp.copyRO(), new OPT_IntConstantOperand(i), + new OPT_LocationOperand(VM_TypeReference.Int), + new OPT_TrueGuardOperand())); + } + } + } + + @Override + protected int translateInstruction(Laziness lazy, int pc) { + return ARM_InstructionDecoder.translateInstruction(this, + (ARM_ProcessSpace) ps, (ARM_Laziness) lazy, pc); + } +} Added: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-02 12:41:02 UTC (rev 20) @@ -0,0 +1,163 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.DBT; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.generic.decoder.InstructionDecoder; +import org.jikesrvm.compilers.opt.ir.*; + +public class ARM_InstructionDecoder extends InstructionDecoder { + + abstract static class BasicDecoder implements OPT_Operators { + /** Return the value of a single bit. Note that the bit is 0-based.*/ + public static final boolean getBit(int word, int bit) { + if (DBT.VerifyAssertions) DBT._assert(bit >= 0 && bit <= 31); + return (word & (1 << bit)) != 0; + } + + /** Transfer a subsequence of bits within (word) into an integer. Note that all bits are 0-based. */ + public static final int getBits(int word, int from, int to) { + if (DBT.VerifyAssertions) DBT._assert(from < to && from >= 0 && to <= 31); + return (word & ((1 << (to+1)) - 1)) >> from; + } + + protected abstract int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr); + } + + /** Translates LDR and STR instructions */ + static class LDR_STR_Decoder extends BasicDecoder { + + @Override + protected int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { + boolean immediateOperand = getBit(instr, 25); + boolean preIndex = getBit(instr, 24); + boolean positiveOffset = getBit(instr, 23); + boolean transferByte = getBit(instr, 22); + boolean writeBack = getBit(instr, 21); + boolean loadOperation = getBit(instr, 20); + int offset = getBits(instr, 0, 11); + + int baseRegister = getBits(instr, 16, 19); + int destRegister = getBits(instr, 12, 15); + + System.out.println("Decoding LDR/STR with: "); + System.out.println("Imm: " + immediateOperand); + System.out.println("Pre Index: " + preIndex); + System.out.println("Offset: " + (positiveOffset ? "+" : "-") + offset); + System.out.println("Base: " + baseRegister); + System.out.println("Dest: " + destRegister); + System.out.println("Load Operation: " + loadOperation); + System.out.println("Write back: " + writeBack); + + //we are only handling a limitied subset of this instruction + if (DBT.VerifyAssertions) DBT._assert(immediateOperand == false && transferByte == false && writeBack == false && preIndex == true); + + //resolve correspoding memory address for this operation + OPT_Operand memoryAddr; + + //take the ARM pipeline into account when storing relative to the pc + if (baseRegister == 15) { + if (positiveOffset) + memoryAddr = new OPT_IntConstantOperand(pc + 8 + offset); + else + memoryAddr = new OPT_IntConstantOperand(pc + 8 - offset); + } + else { + OPT_Operand Rs = arm2ir.getRegister(baseRegister); + memoryAddr = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, (OPT_RegisterOperand)memoryAddr, Rs, new OPT_IntConstantOperand(offset))); + } + + //resolve dest register + OPT_RegisterOperand Rd = arm2ir.getRegister(destRegister); + + if (loadOperation) { + //load a word + ps.memory.translateLoad32(memoryAddr, Rd); + } + else { + //store a word + ps.memory.translateStore32(memoryAddr, Rd); + } + + return pc+4; + } + } + + abstract static class DataProcessingOperation_Decoder extends BasicDecoder { + + protected int Rd; + protected int Rs; + protected boolean setConditionCodes; + + protected boolean hasImmediate; + protected int immediate; + + @Override + protected final int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { + hasImmediate = getBit(instr, 25); + setConditionCodes = getBit(instr, 20); + Rd = getBits(instr, 12, 15); + Rs = getBits(instr, 16, 19); + + //we're only handling a subset of the possible instruction options + if (DBT.VerifyAssertions) DBT._assert(Rd != 15 && Rs != 15 && hasImmediate == true); + + if (hasImmediate) + immediate = getBits(instr, 0, 7) << getBits(instr, 8, 11); + + System.out.println("Decoding Data Processing Instruction with: "); + System.out.println("Rs: " + Rs); + System.out.println("Rd: " + Rd); + System.out.println("Op Code: " + getBits(instr, 21, 24)); + System.out.println("Set Condition Codes: " + setConditionCodes); + + if (hasImmediate) + System.out.println("Immediate: " + immediate); + + translateActualOpcode(arm2ir, ps, lazy, pc, instr); + + if (setConditionCodes && Rd != 15) { + throw new UnsupportedOperationException("Setting conditions codes is not yet supported"); + } + + return pc+4; + } + + protected abstract void translateActualOpcode(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr); + } + + static class ADD_Decoder extends DataProcessingOperation_Decoder { + + @Override + protected void translateActualOpcode(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, arm2ir.getRegister(Rd), arm2ir.getRegister(Rs), new OPT_IntConstantOperand(immediate))); + } + } + + static class BranchDecoder extends BasicDecoder { + + @Override + protected int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { + boolean branchAndLink = getBit(instr, 24); + int offset = getBits(instr, 0, 23); + + if (DBT.VerifyAssertions) DBT._assert(branchAndLink == false); + + return pc + 8 + offset; + } + } + + public static int translateInstruction(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc) { + int instr = ps.memory.loadInstruction32(pc); + + System.out.println("Translating Instruction:" + instr); + BasicDecoder decoder = null; + + if (BasicDecoder.getBits(instr, 26, 27) == 1) { + decoder = new LDR_STR_Decoder(); + } + + return decoder.translate(arm2ir, ps, lazy, pc, instr); + } +} Added: src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java 2007-04-02 12:41:02 UTC (rev 20) @@ -0,0 +1,25 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.generic.decoder.Laziness; + +public class ARM_Laziness extends Laziness { + + @Override + public Object clone() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean equivalent(Laziness other) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Key makeKey(int pc) { + // TODO Auto-generated method stub + return null; + } + +} Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-04-02 12:11:23 UTC (rev 19) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-04-02 12:41:02 UTC (rev 20) @@ -11,12 +11,12 @@ // DBT classes import java.util.ArrayList; +import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; import org.binarytranslator.generic.decoder.DecoderUtils; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; -import org.jikesrvm.VM; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_FieldReference; import org.jikesrvm.classloader.VM_MemberReference; @@ -296,8 +296,8 @@ * the number of the register to fill. */ private void fillGPRegister(int r) { - if (VM.VerifyAssertions) - VM._assert(r < 32); + if (DBT.VerifyAssertions) + DBT._assert(r < 32); OPT_RegisterOperand result; if (intRegMap[r] == null) { @@ -320,10 +320,10 @@ * the number of the register to spill. */ private void spillGPRegister(int r) { - if (VM.VerifyAssertions) - VM._assert(r < 32); - if (VM.VerifyAssertions) - VM._assert(intRegMap[r] != null); + if (DBT.VerifyAssertions) + DBT._assert(r < 32); + if (DBT.VerifyAssertions) + DBT._assert(intRegMap[r] != null); OPT_RegisterOperand regOp = new OPT_RegisterOperand(intRegMap[r], VM_TypeReference.Int); @@ -342,8 +342,8 @@ * the number of the register to fill. */ private void fillFPRegister(int r) { - if (VM.VerifyAssertions) - VM._assert(r < 32); + if (DBT.VerifyAssertions) + DBT._assert(r < 32); OPT_RegisterOperand result; if (fpRegMap[r] == null) { @@ -367,11 +367,9 @@ * the number of the register to spill. */ private void spillFPRegister(int r) { - if (VM.VerifyAssertions) - VM._assert(r < 32); - if (VM.VerifyAssertions) - VM._assert(fpRegMap[r] != null); - + if (DBT.VerifyAssertions) + DBT._assert(r < 32 && fpRegMap[r] != null); + OPT_RegisterOperand regOp = new OPT_RegisterOperand(fpRegMap[r], VM_TypeReference.Double); @@ -735,8 +733,9 @@ * the number of the PPC GP register */ public OPT_RegisterOperand getGPRegister(int r) { - if (VM.VerifyAssertions) - VM._assert(r < 32); + if (DBT.VerifyAssertions) + DBT._assert(r < 32); + intRegInUseMap[r] = true; return new OPT_RegisterOperand(intRegMap[r], VM_TypeReference.Int); } @@ -749,8 +748,8 @@ * the number of the PPC FP register */ public OPT_RegisterOperand getFPRegister(int r) { - if (VM.VerifyAssertions) - VM._assert(r < 32); + if (DBT.VerifyAssertions) + DBT._assert(r < 32); fpRegInUseMap[r] = true; return new OPT_RegisterOperand(fpRegMap[r], VM_TypeReference.Double); } Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-02 12:11:23 UTC (rev 19) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-02 12:41:02 UTC (rev 20) @@ -8,13 +8,13 @@ */ package org.binarytranslator.arch.ppc.decoder; +import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; import org.binarytranslator.generic.branch.BranchLogic; import org.binarytranslator.generic.decoder.InstructionDecoder; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; -import org.jikesrvm.VM; import org.jikesrvm.compilers.opt.ir.Binary; import org.jikesrvm.compilers.opt.ir.BooleanCmp; import org.jikesrvm.compilers.opt.ir.BooleanCmp2; @@ -685,8 +685,8 @@ protected static void plantBranchToBlockDependentOnCondition(PPC2IR ppc2ir, OPT_BasicBlock targetBlock, PPC_Laziness lazy, int BI, boolean cond_true, boolean likely) { - if (VM.VerifyAssertions) - VM._assert((BI >= 0) && (BI < 32)); + if (DBT.VerifyAssertions) + DBT._assert((BI >= 0) && (BI < 32)); // Calculate the condition register field being tested int crf = BI >> 2; @@ -3898,8 +3898,8 @@ protected int translateXL_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int crfD00, int crfS00, int zero, int secondaryOpcode, int zero2) { - if (VM.VerifyAssertions) - VM._assert((secondaryOpcode == 0) && (zero == 0) && (zero2 == 0)); + if (DBT.VerifyAssertions) + DBT._assert((secondaryOpcode == 0) && (zero == 0) && (zero2 == 0)); int crfD = crfD00 >> 2; int crfS = crfS00 >> 2; @@ -3986,8 +3986,8 @@ protected int translateXL_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int BO, int BI, int zero, int secondaryOpcode, int lk) { - if (VM.VerifyAssertions) - VM._assert((secondaryOpcode == 16) && (zero == 0)); + if (DBT.VerifyAssertions) + DBT._assert((secondaryOpcode == 16) && (zero == 0)); // Translation process: // decode BO and optionally plant any of: @@ -4082,8 +4082,8 @@ protected int translateXL_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int crbD, int crbA, int crbB, int secondaryOpcode, int zero) { - if (VM.VerifyAssertions) - VM._assert((secondaryOpcode == 33) && (zero == 0)); + if (DBT.VerifyAssertions) + DBT._assert((secondaryOpcode == 33) && (zero == 0)); // Resolve laziness as this instruction encodes lots of // nonsensical states for the condition register :-( @@ -4262,8 +4262,8 @@ protected int translateXL_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int crbD, int crbA, int crbB, int secondaryOpcode, int zero) { - if (VM.VerifyAssertions) - VM._assert((secondaryOpcode == 193) && (zero == 0)); + if (DBT.VerifyAssertions) + DBT._assert((secondaryOpcode == 193) && (zero == 0)); // Resolve laziness as this instruction encodes lots of // nonsensical states for the condition register :-( @@ -4371,8 +4371,8 @@ protected int translateXL_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int crbD, int crbA, int crbB, int secondaryOpcode, int zero) { - if (VM.VerifyAssertions) - VM._assert((secondaryOpcode == 289) && (zero == 0)); + if (DBT.VerifyAssertions) + DBT._assert((secondaryOpcode == 289) && (zero == 0)); // Resolve laziness as this instruction encodes lots of // nonsensical states for the condition register :-( @@ -4494,8 +4494,8 @@ protected int translateXL_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int crbD, int crbA, int crbB, int secondaryOpcode, int zero) { - if (VM.VerifyAssertions) - VM._assert((secondaryOpcode == 449) && (zero == 0)); + if (DBT.VerifyAssertions) + DBT._assert((secondaryOpcode == 449) && (zero == 0)); // Resolve laziness as this instruction encodes lots of // nonsensical states for the condition register :-( @@ -4647,8 +4647,8 @@ protected int translateXL_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int BO, int BI, int zero, int secondaryOpcode, int lk) { - if (VM.VerifyAssertions) - VM._assert((secondaryOpcode == 528) && (zero == 0)); + if (DBT.VerifyAssertions) + DBT._assert((secondaryOpcode == 528) && (zero == 0)); // Translation process: // decode BO and optionally plant any of: @@ -5045,8 +5045,8 @@ protected int translateXO_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int rD, int rA, int rB, int OE, int secondaryOpcode, int Rc) { - if (VM.VerifyAssertions) - VM._assert(rB == 0); + if (DBT.VerifyAssertions) + DBT._assert(rB == 0); // Perform negation ppc2ir.appendInstructionToCurrentBlock(Unary.create(INT_NEG, ppc2ir @@ -5214,8 +5214,8 @@ protected int translateXO_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int rD, int rA, int rB, int OE, int secondaryOpcode, int Rc) { - if (VM.VerifyAssertions) - VM._assert(rB == 0); + if (DBT.VerifyAssertions) + DBT._assert(rB == 0); // Get rA OPT_RegisterOperand reg_rA = ppc2ir.getGPRegister(rA); OPT_RegisterOperand reg_rD = ppc2ir.getGPRegister(rD); @@ -5274,8 +5274,8 @@ protected int translateXO_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int rD, int rA, int rB, int OE, int secondaryOpcode, int Rc) { - if (VM.VerifyAssertions) - VM._assert(rB == 0); + if (DBT.VerifyAssertions) + DBT._assert(rB == 0); // Get rA & rD OPT_RegisterOperand reg_rA = ppc2ir.getGPRegister(rA); OPT_RegisterOperand reg_rD = ppc2ir.getGPRegister(rD); @@ -5359,8 +5359,8 @@ int inst, int opcode, int rD, int rA, int rB, int OE, int secondaryOpcode, int Rc) { - if (VM.VerifyAssertions) - VM._assert(rB == 0); + if (DBT.VerifyAssertions) + DBT._assert(rB == 0); // Get rA & rD OPT_RegisterOperand reg_rA = ppc2ir.getGPRegister(rA); OPT_RegisterOperand reg_rD = ppc2ir.getGPRegister(rD); @@ -6646,8 +6646,8 @@ */ protected int translateX_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int crfD0L, int rA, int rB, int zero, int zero2) { - if (VM.VerifyAssertions) - VM._assert((zero == zero2) && (zero2 == 0)); + if (DBT.VerifyAssertions) + DBT._assert((zero == zero2) && (zero2 == 0)); int crfD = crfD0L >>> 2; setCRfield(ppc2ir, lazy, crfD, ppc2ir.getGPRegister(rA), ppc2ir @@ -6805,8 +6805,8 @@ protected int translateX_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int rD, int zero1, int zero2, int secodaryOpcode, int zero3) { - if (VM.VerifyAssertions) - VM._assert((zero1 == zero2) && (zero2 == zero3) && (zero3 == 0)); + if (DBT.VerifyAssertions) + DBT._assert((zero1 == zero2) && (zero2 == zero3) && (zero3 == 0)); ppc2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, ppc2ir .getGPRegister(rD), ppc2ir.getCRRegister())); @@ -11228,8 +11228,8 @@ */ protected int translateSC_FORM(PPC2IR ppc2ir, PPC_Laziness lazy, int pc, int inst, int opcode, int zero1, int zero2, int zero3, int one, int zero4) { - if (VM.VerifyAssertions) - VM._assert((zero1 == zero2) && (zero2 == zero3) && (zero3 == zero4) + if (DBT.VerifyAssertions) + DBT._assert((zero1 == zero2) && (zero2 == zero3) && (zero3 == zero4) && (zero4 == 0) && (one == 1)); ppc2ir.plantSystemCall(lazy, pc); return pc + 4; @@ -11733,8 +11733,8 @@ .makeJumpTarget())); ppc2ir.getCurrentBlock().deleteNormalOut(); ppc2ir.getCurrentBlock().insertOut(targetBlock); - if (VM.VerifyAssertions) - VM._assert(ppc2ir.getCurrentBlock().getNumberOfNormalOut() == 1); + if (DBT.VerifyAssertions) + DBT._assert(ppc2ir.getCurrentBlock().getNumberOfNormalOut() == 1); } else { OPT_Instruction gotoInstr = Goto.create(GOTO, null); ppc2ir.appendInstructionToCurrentBlock(gotoInstr); Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java 2007-04-02 12:11:23 UTC (rev 19) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java 2007-04-02 12:41:02 UTC (rev 20) @@ -1,8 +1,8 @@ package org.binarytranslator.arch.x86.os.process.linux; +import org.binarytranslator.DBT; import org.binarytranslator.arch.x86.os.process.X86_Registers; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; -import org.jikesrvm.VM; public class X86_LinuxSyscallArgumentIterator implements Linu... [truncated message content] |
From: <cap...@us...> - 2007-04-06 11:51:36
|
Revision: 23 http://svn.sourceforge.net/pearcolator/?rev=23&view=rev Author: captain5050 Date: 2007-04-06 04:51:35 -0700 (Fri, 06 Apr 2007) Log Message: ----------- Fix a few build and runtime issues Modified Paths: -------------- src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_Trace.java src/org/binarytranslator/vmInterface/DynamicCodeRunner.java Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-04-03 14:11:34 UTC (rev 22) +++ src/org/binarytranslator/Main.java 2007-04-06 11:51:35 UTC (rev 23) @@ -62,6 +62,7 @@ // Check we have a file to load if (args.length < 1) { usage(); + throw new Error("Error program ran without arguments"); } else { // Set up and load the process space try { Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-03 14:11:34 UTC (rev 22) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-06 11:51:35 UTC (rev 23) @@ -1,7 +1,6 @@ package org.binarytranslator.arch.arm.os.process; import java.io.IOException; - import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; @@ -11,6 +10,7 @@ import org.binarytranslator.generic.os.process.ProcessSpace; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; +import org.vmmagic.pragma.Uninterruptible; public abstract class ARM_ProcessSpace extends ProcessSpace { @@ -94,6 +94,7 @@ /** * Return as an integer the current instruction's address */ + @Uninterruptible public int getCurrentInstructionAddress() { return registers.read(ARM_Registers.PC); } Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-03 14:11:34 UTC (rev 22) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-06 11:51:35 UTC (rev 23) @@ -22,6 +22,7 @@ import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; +import org.vmmagic.pragma.Uninterruptible; /** * Capture the running of a PowerPC process @@ -162,6 +163,7 @@ /** * Return as an integer the current instruction's address */ + @Uninterruptible public int getCurrentInstructionAddress() { return pc; } Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-03 14:11:34 UTC (rev 22) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-06 11:51:35 UTC (rev 23) @@ -21,6 +21,7 @@ import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; import org.binarytranslator.generic.os.loader.Loader; +import org.vmmagic.pragma.Uninterruptible; /** * Encapsulate the parts of an X86 process that are common across operating systems @@ -172,6 +173,7 @@ /** * Return as an integer the current instruction's address */ + @Uninterruptible public int getCurrentInstructionAddress() { return registers.eip; } Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-03 14:11:34 UTC (rev 22) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-06 11:51:35 UTC (rev 23) @@ -24,7 +24,7 @@ /** * System calls object for handling system calls generated by this process */ - LinuxSystemCalls syscalls; + final LinuxSystemCalls syscalls; /** * Allows uniform access to the arguments of a system call. We cache this object for reuse. @@ -45,8 +45,8 @@ * Constructor */ public X86_LinuxProcessSpace(Loader loader) { + syscallArgs = new X86_LinuxSyscallArgumentIterator(this); syscalls = new X86_LinuxSystemCalls(this); - syscallArgs = new X86_LinuxSyscallArgumentIterator(this); } /** Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-03 14:11:34 UTC (rev 22) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-06 11:51:35 UTC (rev 23) @@ -61,7 +61,7 @@ /** * List of (RandomAccessFile(s)) files currently open */ - private ArrayList files; + private ArrayList<Object> files; /** * Convert integer file descriptor into Java RandomAccessFile */ @@ -109,7 +109,7 @@ for(int i=0; i < MAX_SYSCALLS; i++) { systemCallTable[i] = USC; } - files = new ArrayList(); + files = new ArrayList<Object>(); files.add(System.in); files.add(System.out); files.add(System.err); @@ -447,7 +447,7 @@ } abstract class ParameterizedSystemCall extends SystemCall { - protected LinuxSystemCallGenerator.CallArgumentIterator arguments; + protected final LinuxSystemCallGenerator.CallArgumentIterator arguments; public ParameterizedSystemCall() { arguments = src.getSysCallArguments(); Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-03 14:11:34 UTC (rev 22) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-06 11:51:35 UTC (rev 23) @@ -29,7 +29,9 @@ import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; +import org.vmmagic.pragma.Uninterruptible; + /** * A process space encapsulates a running process. This superclass contains non * operating and architecture specific details of the process. @@ -348,6 +350,7 @@ /** * Return as an integer the current instruction's address */ + @Uninterruptible public abstract int getCurrentInstructionAddress(); /** Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-03 14:11:34 UTC (rev 22) +++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-06 11:51:35 UTC (rev 23) @@ -205,6 +205,7 @@ /** * Map bytecode index to java source line number */ + @Uninterruptible public int getLineNumberForBCIndex(int bci) { return bci; } Modified: src/org/binarytranslator/vmInterface/DynamicCodeRunner.java =================================================================== --- src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-04-03 14:11:34 UTC (rev 22) +++ src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-04-06 11:51:35 UTC (rev 23) @@ -23,7 +23,7 @@ * compiled using the PPC emulator. Uninterruptible is used to prevent garbage * collection errors with the dynamic bridge code. */ -@Uninterruptible +//@Uninterruptible @DynamicBridge public class DynamicCodeRunner { /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-11 13:39:18
|
Revision: 24 http://svn.sourceforge.net/pearcolator/?rev=24&view=rev Author: michael_baer Date: 2007-04-11 06:39:17 -0700 (Wed, 11 Apr 2007) Log Message: ----------- Centrally parsing command line options in DBT_Options. Stopped passing argument arrays into the classes, but instead retrieving it from DBT_Options. Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/fault/BadInstructionException.java src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java src/org/binarytranslator/generic/os/loader/Loader.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/generic/os/loader/image/ImageLoader.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/DBT_Options.java 2007-04-11 13:39:17 UTC (rev 24) @@ -8,6 +8,9 @@ */ package org.binarytranslator; +import java.util.HashMap; +import java.util.Map.Entry; + /** * Options for controlling the emulator */ @@ -25,6 +28,12 @@ public final static boolean unimplementedSystemCallsFatal = true; // -oO Translation settings Oo- + + /** The file that is currently being executed. */ + public static String executableFile; + + /** Arguments given to the executable.*/ + public static String[] executableArguments = null; /** * The initial optimisation level @@ -154,47 +163,132 @@ * The group ID for the user running the command */ public final static int GID = 100; - + + /** Stores the arguments given to the DBT by the user. These are NOT the arguments given to the executable. */ + private final static HashMap<String, String> dbtArguments = new HashMap<String, String>(); + /** - * Process a command line option - * - * @arg the command line argument starting "-X:dbt:" + * Read and parse the command line arguments. */ - public static void processArgument(String arg) { - if (arg.startsWith("-X:dbt:debugInstr=true")) { - debugInstr = true; - } else if (arg.startsWith("-X:dbt:debugRuntime=true")) { - debugRuntime = true; - } else if (arg.startsWith("-X:dbt:debugSyscall=true")) { - debugSyscall = true; - } else if (arg.startsWith("-X:dbt:debugSyscallMore=true")) { - debugSyscallMore = true; - } else if (arg.startsWith("-X:dbt:globalBranchLevel=")) { - globalBranchLevel = Integer.parseInt(arg.substring(25)); - } else if (arg.startsWith("-X:dbt:initialOptLevel=")) { - initialOptLevel = Integer.parseInt(arg.substring(23)); - } else if (arg.startsWith("-X:dbt:instrOpt0=")) { - instrOpt0 = Integer.parseInt(arg.substring(17)); - } else if (arg.startsWith("-X:dbt:instrOpt1=")) { - instrOpt1 = Integer.parseInt(arg.substring(17)); - } else if (arg.startsWith("-X:dbt:instrOpt2=")) { - instrOpt2 = Integer.parseInt(arg.substring(17)); - } else if (arg.startsWith("-X:dbt:singleInstrTranslation=true")) { - singleInstrTranslation = true; - } else if (arg.startsWith("-X:dbt:resolveBranchesAtOnce=true")) { - resolveBranchesAtOnce = true; - } else if (arg.startsWith("-X:dbt:resolveBranchesAtOnce=false")) { - resolveBranchesAtOnce = false; - } else if (arg.startsWith("-X:dbt:resolveProceduresBeforeBranches=true")) { - resolveProceduresBeforeBranches = true; - } else if (arg.startsWith("-X:dbt:resolveProceduresBeforeBranches=false")) { - resolveProceduresBeforeBranches = false; - } else if (arg.startsWith("-X:dbt:gdbStub=true")) { - gdbStub = true; - } else if (arg.startsWith("-X:dbt:gdbStubPort=")) { - gdbStubPort = Integer.parseInt(arg.substring(19)); + public static void parseArguments(String[] args) { + parseArgumentsToHashmap(args); + + for (Entry<String, String> argument : dbtArguments.entrySet()) { + String arg = argument.getKey(); + String value = argument.getValue(); + + try { + parseSingleArgument(arg, value); + } + catch (NumberFormatException e) { + throw new Error("Argument " + arg + " is not a valid integer."); + } + } + } + + /** + * Parses a single argument into the options class. + */ + private static void parseSingleArgument(String arg, String value) { + + if (arg.equalsIgnoreCase("-X:dbt:debugInstr")) { + debugInstr = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:debugRuntime")) { + debugRuntime = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscall")) { + debugSyscall = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscallMore")) { + debugSyscallMore = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:globalBranchLevel")) { + globalBranchLevel = Integer.parseInt(value); + } else if (arg.equalsIgnoreCase("-X:dbt:initialOptLevel")) { + initialOptLevel = Integer.parseInt(value); + } else if (arg.equalsIgnoreCase("-X:dbt:instrOpt0")) { + instrOpt0 = Integer.parseInt(value); + } else if (arg.equalsIgnoreCase("-X:dbt:instrOpt1")) { + instrOpt1 = Integer.parseInt(value); + } else if (arg.equalsIgnoreCase("-X:dbt:instrOpt2")) { + instrOpt2 = Integer.parseInt(value); + } else if (arg.equalsIgnoreCase("-X:dbt:singleInstrTranslation")) { + singleInstrTranslation = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:resolveBranchesAtOnce")) { + resolveBranchesAtOnce = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:resolveBranchesAtOnce")) { + resolveBranchesAtOnce = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:resolveProceduresBeforeBranches")) { + resolveProceduresBeforeBranches = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:resolveProceduresBeforeBranches")) { + resolveProceduresBeforeBranches = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:gdbStub")) { + gdbStub = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:gdbStubPort")) { + gdbStubPort = Integer.parseInt(value); } else { - throw new Error("DBT Options: Unrecongised emulator option " + arg); + throw new Error("DBT Options: Unknown emulator option " + arg); } } + + /** + * Takes an array of arguments and parses them as key=value pairs into the hashmap arguments. + */ + private static void parseArgumentsToHashmap(String[] args) { + + String key = null; + String value; + int next = 0; + + try { + //are there further arguments? + if (next == args.length) { + return; + } + + key = args[next++].trim(); + + if (!key.startsWith("-")) { + //this is not an argument to the DBT, so it must the file we're trying to execute. + executableFile = key; + + //the remaining arguments may be passed to the executable + executableArguments = new String[args.length - next]; + for (int i = next; i < args.length; i++) + executableArguments[i] = args[next + i]; + + return; + } + + //did the user give an argument without spaces in it? + int pos = key.indexOf('='); + if (pos != -1) { + value = key.substring(pos + 1); + key = key.substring(0, pos); + } + else { + + //extract the argument's value + do { + value = args[next++].trim(); + + if (value.startsWith("=")) + { + if (value.length() > 1) + value = value.substring(1); + else + value = ""; + } + } + while ( value.length() == 0 ); + } + + //store the argument's key and value + if (dbtArguments.containsKey(key)) { + throw new Error(String.format("Parameter %s already defined", key)); + } + + dbtArguments.put(key, value); + } + catch (Exception e) { + throw new Error("Invalid argument format for argument " + key); + } + } } Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/Main.java 2007-04-11 13:39:17 UTC (rev 24) @@ -18,20 +18,7 @@ * */ public class Main { - /* - * Variables required for an instance of the emulator - */ - /** - * A process space encapsulating the execution of a process - */ - ProcessSpace ps; - - /* - * Utility functions - */ - - /** * Debug information * * @param s @@ -47,62 +34,44 @@ /** * Usage */ - public static void usage() { + public static void showUsage() { System.out .println("org.binarytranslator.Main [-X:dbt:...] <program> <args...>"); } /** - * Constructor - should only be run from main - * - * @param args - * command line arguments. args[0] is the program to load. - */ - private Main(String[] args) { - // Check we have a file to load - if (args.length < 1) { - usage(); - throw new Error("Error program ran without arguments"); - } else { - // Set up and load the process space - try { - report("Loading " + args[0]); - Loader loader = Loader.getLoader(args[0]); - ps = loader.readBinary(args); - } catch (java.io.IOException e) { - usage(); - throw new Error("Error accessing file: " + args[0], e); - } - report("Sucessfully created process"); - } - } - - /** * Main method * * @param args * command line arguments (see usage()) */ public static void main(String[] args) { + + if (args.length < 1) { + showUsage(); + return; + } + // Process any arguments for the emulator - for (int i = 0; i < args.length; i++) { - if (args[i].startsWith("-X:dbt:")) { - DBT_Options.processArgument(args[i]); - } else { - if (i != 0) { - String new_args[] = new String[args.length - i]; - for (int j = 0; j < (args.length - i); j++) { - new_args[j] = args[i + j]; - } - args = new_args; - } - break; - } + try { + DBT_Options.parseArguments(args); + } catch (Exception e) { + System.err.println("Error while parsing command line arguments."); + System.err.println(e.getMessage()); } - Main runtime = new Main(args); - for (int i = 0; i < args.length; i++) { - report("Argument " + i + ": " + args[i]); + + ProcessSpace ps; + + try { + report("Loading " + DBT_Options.executableFile); + Loader loader = Loader.getLoader(DBT_Options.executableFile); + ps = loader.readBinary(DBT_Options.executableFile); + } + catch (java.io.IOException e) { + throw new Error("Error accessing file: " + args[0], e); } - runtime.ps.run(); + + report("Sucessfully created process."); + ps.run(); } } Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-11 13:39:17 UTC (rev 24) @@ -28,7 +28,7 @@ } @Override - public void initialise(Loader loader, int pc, int brk, String[] args) { + public void initialise(Loader loader, int pc, int brk) { registers.write(ARM_Registers.PC, pc); } Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-11 13:39:17 UTC (rev 24) @@ -45,7 +45,7 @@ } @Override - public void initialise(Loader loader, int pc, int brk, String[] args) { + public void initialise(Loader loader, int pc, int brk) { registers.write(ARM_Registers.PC, pc); this.brk = brk; @@ -69,8 +69,7 @@ LinuxStackInitializer.AuxiliaryVectorType.AT_SECURE, 0, LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0 }; - LinuxStackInitializer.stackInit(memory, STACK_TOP, args, - getEnvironmentVariables(), auxVector); + LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector); } public int getBrk() { Modified: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-11 13:39:17 UTC (rev 24) @@ -65,16 +65,16 @@ * @param args * command line arguments */ - public void initialise(Loader loader, int pc, int brk, String args[]) { + public void initialise(Loader loader, int pc, int brk) { this.pc = pc; this.brk = brk; - this.r1 = initialiseStack(loader, pc, args); + this.r1 = initialiseStack(loader, pc); } /** * Initialise the stack */ - private int initialiseStack(Loader loader, int pc, String args[]) { + private int initialiseStack(Loader loader, int pc) { int[] auxVector = { LinuxStackInitializer.AuxiliaryVectorType.AT_IGNOREPPC, LinuxStackInitializer.AuxiliaryVectorType.AT_IGNOREPPC, @@ -118,7 +118,7 @@ * binaries. */ - return LinuxStackInitializer.stackInit(memory, STACK_TOP, args, + return LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector); } Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-11 13:39:17 UTC (rev 24) @@ -56,16 +56,16 @@ * @param brk the initial value for the top of BSS * @param args command line arguments */ - public void initialise(Loader loader, int pc, int brk, String args[]) { + public void initialise(Loader loader, int pc, int brk) { registers.eip = pc; this.brk = brk; - registers.writeGP32(X86_Registers.ESP, initialiseStack(loader, pc, args)); + registers.writeGP32(X86_Registers.ESP, initialiseStack(loader, pc)); } /** * Initialise the stack */ - private int initialiseStack(Loader loader, int pc, String args[]) { + private int initialiseStack(Loader loader, int pc) { int[] auxVector = {LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, 0xffffe400, LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO_EHDR, 0xffffe000, LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x78bfbff, @@ -86,7 +86,7 @@ //LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, LinuxStackInitializer.AuxiliaryVectorType.STACK_TOP - getPlatformString().length, LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0}; - return LinuxStackInitializer.stackInit(memory, STACK_TOP, args, getEnvironmentVariables(), auxVector); + return LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector); } /** Modified: src/org/binarytranslator/generic/fault/BadInstructionException.java =================================================================== --- src/org/binarytranslator/generic/fault/BadInstructionException.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/generic/fault/BadInstructionException.java 2007-04-11 13:39:17 UTC (rev 24) @@ -11,7 +11,21 @@ import org.binarytranslator.generic.os.process.ProcessSpace; public class BadInstructionException extends Exception { + + private final int pc; + private final ProcessSpace ps; + public BadInstructionException(int pc, ProcessSpace ps) { super("Bad instruction encountered at 0x" + Integer.toHexString(pc)); + this.pc = pc; + this.ps = ps; } + + public int getInstructionAddress() { + return pc; + } + + public ProcessSpace getProcessSpace() { + return ps; + } } Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java 2007-04-11 13:39:17 UTC (rev 24) @@ -10,6 +10,7 @@ import java.io.UnsupportedEncodingException; +import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.memory.MemoryMapException; @@ -274,7 +275,11 @@ * @param the auxiliary vector, including the terminating AT_NULL (two zeroes). * @return the bottom of the stack in memory */ - public static int stackInit(Memory memory, int stackTop, String[] argv, String[] env, int[] auxVector) { + public static int stackInit(Memory memory, int stackTop, String[] env, int[] auxVector) { + + //grab the vector of command line options that are to be delivered to the linux program + String[] argv = DBT_Options.executableArguments; + // --- // First create the information block by concatenating all strings // together, then compute pointers to values in the information Modified: src/org/binarytranslator/generic/os/loader/Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/Loader.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/generic/os/loader/Loader.java 2007-04-11 13:39:17 UTC (rev 24) @@ -20,9 +20,6 @@ * appropriate sub-class loader is chosen to actually load the binary. */ public abstract class Loader { - /* - * Utility functions - */ /** * Debug information @@ -45,11 +42,11 @@ * Create a process space, load the binary into it and initialise the stack, * etc. * - * @param args - * command line arguments + * @param filename + * The file, which is to be loaded and executed. * @return the process space to start executing */ - abstract public ProcessSpace readBinary(String[] args) throws IOException; + abstract public ProcessSpace readBinary(String filename) throws IOException; /** * Return the application binary interface (ABI) supported by this file Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-11 13:39:17 UTC (rev 24) @@ -116,13 +116,13 @@ /** * Main entry point that loads the binary - * @param args command line arguments including the program file name + * @param filename the program file name * @return process space containing loaded binary */ - public ProcessSpace readBinary(String[] args) throws IOException + public ProcessSpace readBinary(String filename) throws IOException { - report("Opening File: " + args[0]); - RandomAccessFile rFile = new RandomAccessFile(args[0], "r"); + report("Opening File: " + filename); + RandomAccessFile rFile = new RandomAccessFile(filename, "r"); elfHeader = new ELF_Header(rFile); //NB also sets up reader report("ELF header read successfully"); @@ -149,7 +149,7 @@ "entry = 0x" + Integer.toHexString(elfHeader.getEntryPoint()) + " brk = 0x" + Integer.toHexString(brk) ); - ps.initialise(this, elfHeader.getEntryPoint(), brk, args); + ps.initialise(this, elfHeader.getEntryPoint(), brk); return ps; } Modified: src/org/binarytranslator/generic/os/loader/image/ImageLoader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/image/ImageLoader.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/generic/os/loader/image/ImageLoader.java 2007-04-11 13:39:17 UTC (rev 24) @@ -82,10 +82,12 @@ } } - public ProcessSpace readBinary(String[] args) throws IOException { + /** + */ + public ProcessSpace readBinary(String filename) throws IOException { - report("Reading: " + args[0]); - RandomAccessFile file = new RandomAccessFile(args[0], "r"); + report("Reading: " + filename); + RandomAccessFile file = new RandomAccessFile(filename, "r"); if (!readAndCheckID(file)) throw new IOException("File does not contain the expected EXT_IMG ID string."); @@ -118,7 +120,7 @@ return null; } - ps.initialise(this, 0, -1, args); + ps.initialise(this, 0, -1); return ps; } Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-06 11:51:35 UTC (rev 23) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-11 13:39:17 UTC (rev 24) @@ -293,10 +293,8 @@ * the entry point * @param brk * the initial value for the top of BSS - * @param args - * command line arguments */ - public abstract void initialise(Loader loader, int pc, int brk, String args[]); + public abstract void initialise(Loader loader, int pc, int brk); /** * Constructor This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-13 18:27:36
|
Revision: 47 http://svn.sourceforge.net/pearcolator/?rev=47&view=rev Author: michael_baer Date: 2007-04-13 11:27:36 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Moved management of translated caches from the process space to the DynamicTranslationController. Modified Paths: -------------- src/org/binarytranslator/generic/execution/DynamicTranslationController.java src/org/binarytranslator/generic/execution/GdbController.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_Trace.java Modified: src/org/binarytranslator/generic/execution/DynamicTranslationController.java =================================================================== --- src/org/binarytranslator/generic/execution/DynamicTranslationController.java 2007-04-13 17:54:29 UTC (rev 46) +++ src/org/binarytranslator/generic/execution/DynamicTranslationController.java 2007-04-13 18:27:36 UTC (rev 47) @@ -1,7 +1,11 @@ package org.binarytranslator.generic.execution; +import java.util.Hashtable; + +import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.vmInterface.DBT_Trace; import org.binarytranslator.vmInterface.DynamicCodeRunner; import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; @@ -12,8 +16,13 @@ */ public class DynamicTranslationController extends ExecutionController { + /** Caches pre-translated code and uses the starting address of the code on the subject machine as a key*/ + private final Hashtable<Integer, DBT_Trace> codeHash; + public DynamicTranslationController(ProcessSpace ps) { super(ps); + + codeHash = new Hashtable<Integer, DBT_Trace>(); } @Override @@ -21,18 +30,66 @@ // The current block of compiled code. VM_CodeArray code; - try { - // interpretFrom(); // Interpreter - experimental while (ps.finished == false) { // Get the compiled code - code = ps.getCodeForPC(ps.getCurrentInstructionAddress()); + code = getCodeForPC(ps.getCurrentInstructionAddress()); + // Run the compiled code. ps.setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, ps)); } } catch (BadInstructionException e) { System.out.println(e.toString()); } + } + + /** + * Returns an array of code starting at the given program counter. + * @param pc + * The program counter at which the code is supposed to start. + * @return + * An executable VM_CodeArray, which contains a trace starting at the given address. + */ + private VM_CodeArray getCodeForPC(int pc) { + DBT_Trace trace = codeHash.get(pc); + + if (trace == null) { + trace = translateCode(pc); + } + + return trace.getCurrentCompiledMethod().getEntryCodeArray(); } + /** + * Translates a piece of code starting at the given program counter value. + * + * @param pc + * The memory address of the first instruction that is translated + * into the code array. + * @return An code array containing target system assembly language, which has + * been translated from the subject executable. + */ + private DBT_Trace translateCode(int pc) { + + synchronized (ps) { + DBT_Trace trace = new DBT_Trace(ps, pc); + + if (DBT_Options.debugRuntime) { + report("Translating code for 0x" + Integer.toHexString(trace.pc)); + } + + // compile the given trace + trace.compile(); + + // store the compiled code in code hash + codeHash.put(trace.pc, trace); + + return trace; + } + } + + /** Outputs a debug message */ + private void report(String msg) { + System.out.println("Dynamic Translation Controller: " + msg); + } } Modified: src/org/binarytranslator/generic/execution/GdbController.java =================================================================== --- src/org/binarytranslator/generic/execution/GdbController.java 2007-04-13 17:54:29 UTC (rev 46) +++ src/org/binarytranslator/generic/execution/GdbController.java 2007-04-13 18:27:36 UTC (rev 47) @@ -181,6 +181,7 @@ /** * Main run loop */ + @Override public void run() { try { while (socket.isConnected()) { Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-13 17:54:29 UTC (rev 46) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-13 18:27:36 UTC (rev 47) @@ -10,7 +10,6 @@ import java.io.IOException; import java.io.RandomAccessFile; -import java.util.Hashtable; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; @@ -21,22 +20,15 @@ import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.os.loader.Loader; -import org.binarytranslator.vmInterface.DBT_Trace; -import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; -import org.jikesrvm.compilers.common.VM_CompiledMethod; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.vmmagic.pragma.Uninterruptible; - /** * A process space encapsulates a running process. This superclass contains non * operating and architecture specific details of the process. */ public abstract class ProcessSpace { - /* - * Runtime information - */ /** * A record of branches to guide translation @@ -44,29 +36,16 @@ public final BranchLogic branchInfo; /** - * A hashtable containing translated traces of code - */ - protected final Hashtable<Integer, VM_CodeArray> codeHash = new Hashtable<Integer, VM_CodeArray>(); - - /** * Has a system call been called to terminate the process */ public boolean finished = false; - /* - * Interface to memory - */ - /** * The memory for the process. As this is user mode code, it is a virtual * address space */ public Memory memory; - /* - * Utility functions - */ - /** * Debug information * @@ -80,10 +59,6 @@ } } - /* - * Methods - */ - /** * Create an optimizing compiler HIR code generator suitable for a particular * architecture @@ -121,7 +96,7 @@ } return result; } - + /** * Create a segment * @@ -202,43 +177,8 @@ } /** - * Constructor + * Record a branch instruction */ - public ProcessSpace(String[] args) throws IOException { - branchInfo = new BranchLogic(); - } - - /** - * Replace the compiled code for a trace (called by the adaptive system) - */ - public synchronized void replaceCompiledTrace(VM_CompiledMethod cm, - DBT_Trace trace) { - VM_CodeArray code = cm.getEntryCodeArray(); - codeHash.put(trace.pc, code); - } - - public synchronized VM_CodeArray getCodeForPC(int pc) { - VM_CodeArray code = (VM_CodeArray) codeHash.get(pc); - if (code == null) { - code = translateCode(new DBT_Trace(this, pc)); - } - return code; - } - - private VM_CodeArray translateCode(DBT_Trace trace) { - if (DBT_Options.debugRuntime) { - report("Translating code for 0x" + Integer.toHexString(trace.pc)); - } - trace.compile(); - VM_CompiledMethod cm = trace.getCurrentCompiledMethod(); - replaceCompiledTrace(cm, trace); - return cm.getEntryCodeArray(); - } - - /* - * - * /** Record a branch instruction - */ public void recordUncaughtBranch(int location, int destination, int code) { branchInfo.registerBranch(location, destination, code); } Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-13 17:54:29 UTC (rev 46) +++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-13 18:27:36 UTC (rev 47) @@ -18,6 +18,7 @@ import org.jikesrvm.classloader.VM_MemberReference; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_BytecodeStream; +import org.jikesrvm.runtime.VM_Magic; import org.jikesrvm.runtime.VM_Statics; import org.jikesrvm.runtime.VM_DynamicLink; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; @@ -190,7 +191,6 @@ */ public final synchronized void replaceCompiledMethod( VM_CompiledMethod compiledMethod) { - ps.replaceCompiledTrace(compiledMethod, this); // Grab version that is being replaced VM_CompiledMethod oldCompiledMethod = currentCompiledMethod; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-14 09:58:33
|
Revision: 51 http://svn.sourceforge.net/pearcolator/?rev=51&view=rev Author: michael_baer Date: 2007-04-14 02:58:24 -0700 (Sat, 14 Apr 2007) Log Message: ----------- Protected DecoderUtils.numberOfInstructions Introduced usage of generic ArrayList in PPC2IR Modified Paths: -------------- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/generic/decoder/DecoderUtils.java Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-04-14 09:55:45 UTC (rev 50) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-04-14 09:58:24 UTC (rev 51) @@ -962,7 +962,7 @@ * Return an array of unused registers */ protected OPT_Register[] getUnusedRegisters() { - ArrayList unusedRegisterList = new ArrayList(); + ArrayList<OPT_Register> unusedRegisterList = new ArrayList<OPT_Register>(); for (int i = 0; i < 32; i++) { if (intRegInUseMap[i] == false) { unusedRegisterList.add(intRegMap[i]); Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-14 09:55:45 UTC (rev 50) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-14 09:58:24 UTC (rev 51) @@ -268,7 +268,7 @@ if (DBT_Options.debugInstr) { System.out.println(lazy.makeKey(pc) + PPC_Disassembler.disasm(instr, pc) - + " " + ppc2ir.getCurrentBlock() + " " + ppc2ir.numberOfInstructions); + + " " + ppc2ir.getCurrentBlock() + " " + ppc2ir.getNumInstructions()); } int primaryOpcode = bits(instr, 0, 5); Modified: src/org/binarytranslator/generic/decoder/DecoderUtils.java =================================================================== --- src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-14 09:55:45 UTC (rev 50) +++ src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-14 09:58:24 UTC (rev 51) @@ -29,7 +29,30 @@ import org.jikesrvm.classloader.VM_MethodReference; import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.OPT_Constants; -import org.jikesrvm.compilers.opt.ir.*; +import org.jikesrvm.compilers.opt.ir.Athrow; +import org.jikesrvm.compilers.opt.ir.BBend; +import org.jikesrvm.compilers.opt.ir.Call; +import org.jikesrvm.compilers.opt.ir.Goto; +import org.jikesrvm.compilers.opt.ir.IfCmp; +import org.jikesrvm.compilers.opt.ir.LookupSwitch; +import org.jikesrvm.compilers.opt.ir.Move; +import org.jikesrvm.compilers.opt.ir.New; +import org.jikesrvm.compilers.opt.ir.OPT_AddressConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_BasicBlock; +import org.jikesrvm.compilers.opt.ir.OPT_BranchOperand; +import org.jikesrvm.compilers.opt.ir.OPT_BranchProfileOperand; +import org.jikesrvm.compilers.opt.ir.OPT_ConditionOperand; +import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; +import org.jikesrvm.compilers.opt.ir.OPT_Instruction; +import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_MethodOperand; +import org.jikesrvm.compilers.opt.ir.OPT_Operand; +import org.jikesrvm.compilers.opt.ir.OPT_Operator; +import org.jikesrvm.compilers.opt.ir.OPT_Operators; +import org.jikesrvm.compilers.opt.ir.OPT_Register; +import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TrueGuardOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TypeOperand; /** * A collection of common tools used by decoders. The public entry point for the @@ -107,12 +130,10 @@ .resolveInvokeSpecial(); } - // -oO Global IR Oo- - /** * Number of translated instructions */ - public int numberOfInstructions; + private int numberOfInstructions; /** * The process space object used by the running PPC binary. @@ -237,8 +258,6 @@ */ protected abstract void report(String str); - // -oO Important entry points Oo- - /** * Constructor * @@ -284,6 +303,11 @@ unresolvedLookupSwitchForSwitches_Laziness = new ArrayList<Laziness>(); unresolvedLookupSwitchForSwitches_WasCall = new ArrayList<Boolean>(); } + + /** Returns the number of previously translated instructions within this trace. */ + public int getNumInstructions() { + return numberOfInstructions; + } /** * This is the main loop to generate the HIR. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-14 13:55:40
|
Revision: 55 http://svn.sourceforge.net/pearcolator/?rev=55&view=rev Author: michael_baer Date: 2007-04-14 06:55:41 -0700 (Sat, 14 Apr 2007) Log Message: ----------- Initial version of an ARM disassembler. Fixed a few bugs in ARM_InstructionDecoders. Introduced named enumerations for ARM condition codes and data processing opcodes. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/generic/decoder/DisassembledInstruction.java Added: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-14 13:55:41 UTC (rev 55) @@ -0,0 +1,409 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Instruction; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.BlockDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Branch; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.BranchExchange; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorDataProcessing; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorRegisterTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CountLeadingZeros; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.DataProcessing; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.IntMultiply; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.LongMultiply; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.MoveFromStatusRegister; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.MoveToStatusRegister; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.OperandWrapper; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.SingleDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.SoftwareInterrupt; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Swap; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Instruction.Condition; +import org.binarytranslator.generic.decoder.DisassembledInstruction; +import org.binarytranslator.generic.os.process.ProcessSpace; + +/** + * This class transfers an ARM instruction into a human-readable assembly + * format. + * + * @author Michael Baer + * + */ +public final class ARM_Disassembler { + + /** + * Disassembles an ARM instruction by reading it from a ProcessSpace. + * + * @param pc + * The address of the ARM instruction within the process space's + * memory. + * @param ps + * The process space from which the instruction is read. + * @return A disassembled ARM instruction. + */ + public final static DisassembledInstruction disassemble(int address, + ProcessSpace ps) { + + int instr = ps.memory.loadInstruction32(address); + DisassemblingVisitor disassembler = new DisassemblingVisitor(address); + + return disassembler.result; + } + + /** + * Directly disassembles an ARM instruction. This method only has package + * visibility, because it is only used to provide the toString() functionality + * for the ARM instruction decoder. + * + * @param instruction + * The instruction that is to be decoded. + * @return A human-readable version of the given instruction. + */ + final static DisassembledInstruction disassemble( + ARM_InstructionDecoders.Instruction instruction) { + + DisassemblingVisitor disassembler = new DisassemblingVisitor(); + instruction.visit(disassembler); + + return disassembler.result; + } + + /** Represents a disassembled ARM instruction. */ + private final static class ARM_DisassembledInstruction implements + DisassembledInstruction { + + /** A readable version of the diassembled instruction. */ + private final String instruction; + + public ARM_DisassembledInstruction(String instruction) { + this.instruction = instruction; + } + + /** @see DisassembledInstruction#asString() */ + public String asString() { + return instruction; + } + + /** @see DisassembledInstruction#getSuccessor(int) */ + public int getSuccessor(int pc) { + return pc + 4; + } + } + + /** + * As this class has only static methods, there is no need to ever instantiate + * it. + */ + private ARM_Disassembler() { + } + + /** + * This class decodes an ARM instruction into an ARM_DisassembledInstruction. + * It used a visitor pattern to decode the proper instructions and should only + * be used by calling {@link Instruction#visit(ARM_InstructionVisitor)} method. The + * disassembled instruction is saved within the {@link #result} member. + * + * As this class is private (i.e. can only ever be instantiated by its + * superclass), it should only be accessed using the methods provided by the + * superclass. + * + * @author Michael Baer + */ + private static final class DisassemblingVisitor implements + ARM_InstructionVisitor { + + /** This field receives the disassembled instruction. */ + private ARM_DisassembledInstruction result; + + /** The address of the instruction which is currently decoded or -1, if that address is not known. */ + private int address; + + private DisassemblingVisitor() { + this.address = -1; + } + + private DisassemblingVisitor(int address) { + this.address = address; + } + + /** Wraps a decoded assembly statement within an {@link ARM_DisassembledInstruction} object and + * stores it as the result of this operation. */ + private void setResult(String assembly) { + result = new ARM_DisassembledInstruction(assembly); + } + + /** + * Extracts the condition field from an instruction and provides a + * human-readable assembly form of the condition. + * + * @param instr + * The instruction, whose condition field shall be read. + * @return A human readable form of this instructions condition. + */ + private String cond(Instruction instr) { + return instr.getCondition().name(); + } + + /** + * Decodes an operand stored within a {@link OperandWrapper} object and + * provides an human-readable, ARM assembly version of it. + * + * @param op + * The operand that is to be decoded. + * @return A readable version of the operand. + */ + private final String operand(OperandWrapper op) { + switch (op.getType()) { + case Immediate: + return String.format("#%x", op.getImmediate()); + + case ImmediateShiftedRegister: + return String.format("r%d %s #%d", op.getRegister(), op.getShiftType(), + op.getShiftAmount()); + + case PcRelative: + return String.format("#%x", op.getOffset() + address + 8); + + case Register: + return "r" + op.getRegister(); + + case RegisterShiftedRegister: + return String.format("r%d %s r%s", op.getRegister(), op.getShiftType(), + op.getShiftingRegister()); + + default: + throw new RuntimeException("Unexpected operand wrapper type: " + + op.getType()); + } + } + + public void visit(DataProcessing instr) { + String mnemonic = instr.getOpcode().name(); + mnemonic += cond(instr); + + if (instr.updateConditionCodes()) + mnemonic += 'S'; + + String optionalParam; + + // Filter instructions that only take one parameter + if (instr.getOpcode() != DataProcessing.Opcode.MOV + && instr.getOpcode() != DataProcessing.Opcode.MVN) { + + optionalParam = ", " + operand(instr.getOperand2()); + } else + optionalParam = ""; + + setResult(String.format("%s r%d, r%d %s", mnemonic, instr.getRd(), instr + .getRn(), optionalParam)); + } + + public void visit(SingleDataTransfer instr) { + String mnemonic = instr.isLoad() ? "LDR" : "STR"; + String address = "[r" + instr.getRn(); + + if (instr.preIndexing()) { + address += ", " + operand(instr.getOffset()) + "]"; + + if (instr.writeBack()) + address += '!'; + } else { + address += "], " + operand(instr.getOffset()); + } + mnemonic += cond(instr); + + switch (instr.getSize()) { + case Byte: + mnemonic += 'B'; + break; + + case HalfWord: + mnemonic += 'H'; + break; + + case Word: + break; + + default: + throw new RuntimeException( + "Unexpected transfer size for single data transfer: " + + instr.getSize()); + } + + if (instr.forceUserMode()) + mnemonic += 'T'; + + setResult(String.format("%s r%d, %s", mnemonic, instr.getRd(), address)); + } + + public void visit(IntMultiply instr) { + + String mnemonic; + String accumParam; + + if (instr.accumulate) { + mnemonic = "MLA"; + accumParam = ", r" + instr.getRn(); + } else { + mnemonic = "MUL"; + accumParam = ""; + } + + mnemonic += cond(instr); + + if (instr.updateConditionCodes()) + mnemonic += "S"; + + setResult(String.format("%s r%d, r%d, r%d%s", mnemonic, instr.getRd(), + instr.getRm(), instr.getRs(), accumParam)); + } + + public void visit(LongMultiply instr) { + String mnemonic = instr.isUnsigned() ? "U" : "S"; + + mnemonic += instr.accumulate() ? "MLAL" : "MULL"; + mnemonic += cond(instr); + + if (instr.updateConditionCodes()) + mnemonic += "S"; + + setResult(String.format("%s %s, %s, %s, %s", mnemonic, instr.getRdLow(), + instr.getRdHigh(), instr.getRm(), instr.getRs())); + } + + public void visit(Swap instr) { + + String mnemonic = instr.swapByte() ? "B" : ""; + setResult(String.format("SWP%s%s r%d, r%d, r%d", mnemonic, cond(instr), + instr.getRd(), instr.getRm(), instr.getRn())); + } + + public void visit(BlockDataTransfer instr) { + String mnemonic = instr.isLoad() ? "LDM" : "STM"; + String baseRegister = "r" + instr.getBaseRegister(); + + mnemonic += cond(instr); + mnemonic += instr.incrementBase() ? "I" : "D"; + mnemonic += instr.postIndexing() ? "A" : "B"; + + if (instr.writeBack()) + baseRegister += "!"; + + String registers = ""; + + for (int i = 0; i < 15; i++) + if (instr.transferRegister(i)) + registers += ", r" + i; + + registers = registers.substring(2); + + setResult(String.format("%s %s, {%s}%s", mnemonic, baseRegister, + registers, instr.forceUser() ? "^" : "")); + } + + public void visit(SoftwareInterrupt instr) { + + setResult(String.format("SWI%s #%x", cond(instr), instr + .getInterruptNumber())); + } + + public void visit(Branch instr) { + + String mnemonic = instr.link() ? "BL" : "B"; + setResult(String.format("%s%s #%x", mnemonic, cond(instr), instr + .getOffset() + + address)); + } + + public void visit(BranchExchange instr) { + + String mnemonic = instr.link ? "BLX" : "BX"; + setResult(String.format("%s%s #%x", mnemonic, cond(instr), operand(instr + .target()))); + } + + public void visit(CoprocessorDataTransfer instr) { + + String mnemonic = instr.isLoad() ? "LDC" : "STC"; + String cond = instr.getCondition() == Condition.NV ? "2" : cond(instr); + String largeTransfer = instr.largeTransfer() ? "L" : ""; + String address = "[r" + instr.getBaseRegister(); + + if (!instr.preIndexing() && !instr.writeBack()) { + // this is a special instruction form, where the offset is actually a + // coprocessor option + address += "], " + instr.getOption(); + } else { + + String offset = "#" + instr.getOffset(); + + if (!instr.preIndexing()) { + address += "], " + offset; + } else { + address += ", " + offset + "]"; + + if (instr.writeBack()) + address += "!"; + } + } + + setResult(String.format("%s%s%s p%d, cp_r%d, %s", mnemonic, cond, + largeTransfer, instr.getCoprocessorNumber(), + instr.getCoprocessorRd(), address)); + } + + public void visit(CoprocessorDataProcessing instr) { + + String mnemonic = instr.getCondition() == Condition.NV ? "CDP2" : "CDP" + + cond(instr); + setResult(String.format("%s p%d, %d, cp_r%d, cp_r%d, cp_r%d, %d", + mnemonic, instr.getCoprocessorNumber(), instr.getOpcode(), instr + .getCoprocessorRd(), instr.getCoprocessorRn(), instr + .getCoprocessorRm(), instr.getCoprocessorInfo())); + } + + public void visit(CoprocessorRegisterTransfer instr) { + String mnemonic = instr.isLoadFromCP() ? "MRC" : "MCR"; + String condition = instr.getCondition() == Condition.NV ? "2" : cond(instr); + String opcode2 = instr.getCoprocessorInfo() != 0 ? ", " + + instr.getCoprocessorInfo() : ""; + + setResult(String.format("%s%s p%d, %d, r%d, cp_r%d, cp_r%d%s", mnemonic, + condition, instr.getCoprocessorNumber(), instr.getOpcode(), instr + .getRd(), instr.getCoprocessorRn(), instr.getCoprocessorRm(), + opcode2)); + } + + public void visit(MoveFromStatusRegister instr) { + + String field = instr.transferSavedPSR() ? "SPSR" : "CPSR"; + setResult(String.format("MRS%s r%d, %s", cond(instr), instr.getRd(), + field)); + } + + public void visit(MoveToStatusRegister instr) { + + String fields = instr.transferSavedPSR() ? "SPSR_" : "CPSR_"; + + if (instr.transferControlField()) + fields += 'c'; + + if (instr.transferExtensionField()) + fields += 'x'; + + if (instr.transferStatusField()) + fields += 's'; + + if (instr.transferFlagField()) + fields += 'f'; + + setResult(String.format("MSR%s %s, %s", cond(instr), fields, + operand(instr.getSource()))); + } + + public void visit(CountLeadingZeros instr) { + + setResult(String.format("CLZ%s r%s r%s ", cond(instr), instr.getRd(), + instr.getRm())); + } + } +} Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-14 12:04:52 UTC (rev 54) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-14 13:55:41 UTC (rev 55) @@ -64,25 +64,35 @@ } /** A base class for all (conditional) ARM instructions. */ - private abstract static class Basic { + public abstract static class Instruction { + + public enum Condition { + EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV + } + /** @see #getCondition() */ - protected final byte condition; + protected final Condition condition; - public Basic(int instr) { - condition = (byte) getBits(instr, 28, 31); + private Instruction(int instr) { + condition = Condition.values()[(byte) getBits(instr, 28, 31)]; } /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ - public final byte getCondition() { + public final Condition getCondition() { return condition; } + @Override + public String toString() { + return ARM_Disassembler.disassemble(this).asString(); + } + /** All instruction classes are meant to implement the visitor pattern. This is the pattern's visit method. */ public abstract void visit(ARM_InstructionVisitor visitor); } /** Base class for most instructions that use two registers. */ - private abstract static class TwoRegistersTemplate extends Basic { + private abstract static class TwoRegistersTemplate extends Instruction { /** @see #getRn() */ protected final byte Rn; @@ -165,7 +175,7 @@ } /** Base class for coprocessor instructions. */ - protected static abstract class CoprocessorTemplate extends Basic { + protected static abstract class CoprocessorTemplate extends Instruction { /** This is a register id, which can either refer to the CPU or the coprocessor, depending on the instruction. */ protected final byte Rd; @@ -196,6 +206,7 @@ /** Describes the type of the operand. */ public enum Type { Immediate, + PcRelative, Register, ImmediateShiftedRegister, RegisterShiftedRegister, @@ -203,11 +214,11 @@ /** Describes a type of shift, in case the operand is supposed to be shifted. */ public enum ShiftType { - LogicalLeft, - LogicalRight, - ArithmeticRight, - RotateRight, - RotateRightExtend + LSL, + LSR, + ASR, + ROR, + RRE } /** Creates an operand wrapper around a 12 bit immediate value. */ @@ -215,11 +226,16 @@ return new ImmediateOperand(immediate); } - /** Creates an operand wrapper that is a nromal register value. */ + /** Creates an operand wrapper that is a normal register value. */ public static OperandWrapper createRegister(byte register) { return new RegisterOperand(register); } + /** Creates an operand wrapper representing an offset to the pc.*/ + public static OperandWrapper createPcRelative(int offset) { + return new PcRelativeOperand(offset); + } + /** Creates an operand wrapper, that represents a register shifted by an immediate or a register, depending on the instruction. */ public static OperandWrapper decodeShiftedRegister(int instr) { ShiftType shift = ShiftType.values()[getBits(instr, 5, 6)]; @@ -236,7 +252,7 @@ if (immediate == 0) { //if we are shifting by zero, we might forget about the shift - if (shift == ShiftType.RotateRight) { + if (shift == ShiftType.ROR) { //However, if the shift type was RotateRight, then ARM meant do a RotateRightExtend by 1 return new RegisterShiftImmediateOperand(shiftedRegister, shift, (byte)1); } @@ -259,6 +275,11 @@ throw new RuntimeException("Invalid call on an operand wrapper."); } + /** Returns an offset that is to be applied to a register. */ + public int getOffset() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + /** Returns the number of the register, which forms the 2nd operand. Only applicable if {@link #hasImmediate()} is false.*/ public byte getRegister() { throw new RuntimeException("Invalid call on an operand wrapper."); @@ -300,6 +321,30 @@ } } + protected static class PcRelativeOperand extends OperandWrapper { + + protected final int offset; + + protected PcRelativeOperand(int offset) { + this.offset = offset; + } + + @Override + public byte getRegister() { + return 15; + } + + @Override + public int getOffset() { + return offset; + } + + @Override + public Type getType() { + return Type.PcRelative; + } + } + /** Represents a register operand. */ protected static class RegisterOperand extends OperandWrapper { @@ -387,12 +432,19 @@ /** Represents a Data Processing instruction. */ public static class DataProcessing extends TwoRegistersTemplate { + + /** A list of possible DataProcessing operations. The list is orded in ascendingly, with the + * first opcode corresponding to opcode 0 (zero) in the opcode field of an ARM data processing + * instruction. */ + public enum Opcode { + AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, TST, TEQ, CMP, CMN, ORR, MOV, BIC, MVN + } /** @see #hasSetConditionCodes() */ protected final boolean updateConditionCodes; /** @see #getOpcode() */ - protected final byte opcode; + protected final Opcode opcode; /** @see #getOperand2() */ protected final OperandWrapper operand2; @@ -401,7 +453,7 @@ super(instr); updateConditionCodes = getBit(instr, 20); - opcode = (byte) getBits(instr, 21, 24); + opcode = Opcode.values()[(byte) getBits(instr, 21, 24)]; if (getBit(instr, 25)) operand2 = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); @@ -410,7 +462,7 @@ } /** Returns the opcode, that specifies the data processing operation, which is to be performed. */ - public final byte getOpcode() { + public final Opcode getOpcode() { return opcode; } @@ -448,6 +500,9 @@ /** @see #signExtend() */ protected final boolean signExtend; + + /** @see #forceUserMode() */ + protected final boolean forceUserMode; /** @see #getSize() */ protected final TransferSize size; @@ -473,6 +528,8 @@ //this is an unsigned byte or word transfer signExtend = false; + forceUserMode = !preIndexing && writeBack; + if (getBit(instr, 22)) size = TransferSize.Byte; else @@ -491,6 +548,7 @@ size = TransferSize.Byte; signExtend = getBit(instr, 6); + forceUserMode = false; if (getBit(instr, 22)) { //immediate offset @@ -506,6 +564,11 @@ } } + /** Returns true, if this memory access shall be treated as if it had been done in user mode. */ + public final boolean forceUserMode() { + return forceUserMode; + } + /** Returns true, if the loaded/stored value shall be signed-extended.*/ public final boolean signExtend() { return signExtend; @@ -552,6 +615,8 @@ protected IntMultiply(int instr) { super(instr); + + if (DBT.VerifyAssertions) DBT._assert(accumulate || Rn == 0); } @Override @@ -616,10 +681,10 @@ } /** Represents a LDM/STM instruction. */ - public static class BlockDataTransfer extends Basic { + public static class BlockDataTransfer extends Instruction { - /** @see #preIndexing() */ - protected final boolean preIndexing; + /** @see #postIndexing() */ + protected final boolean postIndexing; /** @see #incrementBase() */ protected final boolean incrementBase; @@ -642,7 +707,7 @@ public BlockDataTransfer(int instr) { super(instr); - preIndexing = getBit(instr, 24); + postIndexing = getBit(instr, 24); incrementBase = getBit(instr, 23); forceUser = getBit(instr, 22); writeBack = getBit(instr, 21); @@ -659,9 +724,9 @@ return getBit(registerList, r); } - /** True if the base register shall be changed before each single transfer, otherwise changed it after each transfer. */ - public final boolean preIndexing() { - return preIndexing; + /** True if the base register shall be changed after each single transfer, otherwise changed it before each transfer. */ + public final boolean postIndexing() { + return postIndexing; } /** True if the base register shall be incremented, false if it should be decremented. */ @@ -696,7 +761,7 @@ } /** Represents a SWI instruction*/ - public static class SoftwareInterrupt extends Basic { + public static class SoftwareInterrupt extends Instruction { /** @see #getInterruptNumber() */ protected final int interruptNumber; @@ -718,9 +783,9 @@ } /** Represents a branch instruction. */ - public static class Branch extends Basic { + public static class Branch extends Instruction { - /** @see #isBranchAndLink() */ + /** @see #link() */ protected final boolean link; /** @see #getOffset() */ @@ -733,7 +798,7 @@ } /** Should the current PC be put into the lr? */ - public final boolean isBranchAndLink() { + public final boolean link() { return link; } @@ -749,9 +814,9 @@ } /** Represents a BX instruction set */ - public static class BranchExchange extends Basic { + public static class BranchExchange extends Instruction { - /** @see #getRn() */ + /** @see #target() */ protected final OperandWrapper target; /** @see #link() */ @@ -765,13 +830,13 @@ link = true; //sign extend jump target - int jumpTarget = signExtend(instr & 0xFFF, 24); + int jumpTarget = signExtend(instr & 0xFFF, 24) << 2; //are we addressing a half-byte? if (getBit(instr, 24)) jumpTarget += 2; - target = OperandWrapper.createImmediate(jumpTarget); + target = OperandWrapper.createPcRelative(jumpTarget); } else { link = getBit(instr, 5); @@ -783,6 +848,11 @@ public final boolean link() { return link; } + + /** Returns the address to which this instruction will branch. */ + public final OperandWrapper target() { + return target; + } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -816,10 +886,15 @@ writeBack = getBit(instr, 21); isLoad = getBit(instr, 20); - if (getBit(instr, 23)) - offset = (instr & 0xFF) << 2; - else - offset = - ((instr & 0xFF) << 2); + if (!writeBack && !preIndexing) { + offset = instr & 0xFF; + } + else { + if (getBit(instr, 23)) + offset = (instr & 0xFF) << 2; + else + offset = - ((instr & 0xFF) << 2); + } } /** Returns the number of the register, which contains the base address for this data transfer.*/ @@ -828,7 +903,7 @@ } /** Returns the transfer register on the coprocessor. */ - public final byte getCoprocessorRegister() { + public final byte getCoprocessorRd() { return Rd; } @@ -842,6 +917,13 @@ return offset; } + /** In certain circumstances, the instruction might include an option to the coprocessor that is stored instead of the offset. */ + public final int getOption() { + if (DBT.VerifyAssertions) DBT._assert(!writeBack && !preIndexing); + + return offset; + } + /** True if the changed base register shall be persisted after this instruction. */ public final boolean writeBack() { return writeBack; @@ -975,7 +1057,7 @@ } /** Represents a MRS instruction. */ - public static class MoveFromStatusRegister extends Basic { + public static class MoveFromStatusRegister extends Instruction { /** @see #getRd() */ protected final byte Rd; @@ -1007,7 +1089,7 @@ } /** Represents a MSR instruction. */ - public static class MoveToStatusRegister extends Basic { + public static class MoveToStatusRegister extends Instruction { /** @see #transferControlField() */ protected final boolean transferControl; @@ -1024,7 +1106,7 @@ /** @see #transferSavedPSR() */ protected final boolean transferSavedPSR; - /** @see #getSourceOperand() */ + /** @see #getSource() */ protected final OperandWrapper sourceOperand; public MoveToStatusRegister(int instr) { @@ -1069,7 +1151,7 @@ } /** Returns the operand, which is to be transfered into the status register. */ - public final OperandWrapper getSourceOperand() { + public final OperandWrapper getSource() { return sourceOperand; } @@ -1080,7 +1162,7 @@ } /** Represents a CLZ instruction. */ - public static class CountLeadingZeros extends Basic { + public static class CountLeadingZeros extends Instruction { /** @see #getRm() */ protected final byte Rm; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-14 12:04:52 UTC (rev 54) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-14 13:55:41 UTC (rev 55) @@ -5,19 +5,19 @@ /** An interface that supports iterating over ARM instructions using the visitor pattern. */ public interface ARM_InstructionVisitor { - void visit(DataProcessing processing); - void visit(SingleDataTransfer transfer); - void visit(IntMultiply multiply); - void visit(LongMultiply multiply); - void visit(Swap swap); - void visit(BlockDataTransfer transfer); - void visit(SoftwareInterrupt interrupt); - void visit(Branch branch); - void visit(BranchExchange exchange); - void visit(CoprocessorDataTransfer transfer); - void visit(CoprocessorDataProcessing processing); - void visit(CoprocessorRegisterTransfer transfer); - void visit(MoveFromStatusRegister register); - void visit(MoveToStatusRegister register); - void visit(CountLeadingZeros zeros); + void visit(DataProcessing instr); + void visit(SingleDataTransfer instr); + void visit(IntMultiply instr); + void visit(LongMultiply instr); + void visit(Swap instr); + void visit(BlockDataTransfer instr); + void visit(SoftwareInterrupt instr); + void visit(Branch instr); + void visit(BranchExchange instr); + void visit(CoprocessorDataTransfer instr); + void visit(CoprocessorDataProcessing instr); + void visit(CoprocessorRegisterTransfer instr); + void visit(MoveFromStatusRegister instr); + void visit(MoveToStatusRegister instr); + void visit(CountLeadingZeros instr); } Added: src/org/binarytranslator/generic/decoder/DisassembledInstruction.java =================================================================== --- src/org/binarytranslator/generic/decoder/DisassembledInstruction.java (rev 0) +++ src/org/binarytranslator/generic/decoder/DisassembledInstruction.java 2007-04-14 13:55:41 UTC (rev 55) @@ -0,0 +1,33 @@ +package org.binarytranslator.generic.decoder; + +/** + * Represents a disassembled instruction. + * + * @author Michael Baer + */ +public interface DisassembledInstruction { + /** + * 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. + */ + public String asString(); +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-16 21:28:29
|
Revision: 59 http://svn.sourceforge.net/pearcolator/?rev=59&view=rev Author: captain5050 Date: 2007-04-16 14:28:29 -0700 (Mon, 16 Apr 2007) Log Message: ----------- Fix planting of bad instructions. Handle TLS ELF sections Modified Paths: -------------- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/vmInterface/DBT_Trace.java Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-16 21:25:39 UTC (rev 58) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-16 21:28:29 UTC (rev 59) @@ -12,6 +12,7 @@ import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; import org.binarytranslator.generic.decoder.InstructionDecoder; +import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; @@ -750,7 +751,7 @@ public int translate(X862IR translationHelper, ProcessSpace ps, X86_Laziness lazy, int pc) { TODO(); - return -1; + return 0xEBADC0DE; } /** @@ -763,9 +764,12 @@ */ public static int translateInstruction(X862IR translationHelper, ProcessSpace ps, X86_Laziness lazy, int pc) { + System.err.println("Translating "+pc); X86_InstructionDecoder decoder = getDecoder(ps, pc); if (DBT_Options.debugInstr) { + System.err.println("Disassembling "+pc); System.err.println(decoder.disassemble(ps, pc)); + System.err.println("After disassembling "+pc); } return decoder.translate(translationHelper, ps, lazy, pc); } @@ -796,6 +800,29 @@ * A decoder that faults with a bad instruction exception */ class X86_BadInstructionDecoder extends X86_InstructionDecoder { + /** + * Get the decoder with upto four or five(X86_64) prefix decoders but + * currently no opcode or operands + */ + protected X86_InstructionDecoder getDecoder(ProcessSpace ps, int pc, + int offset, X86_Group1PrefixDecoder prefix1, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + return this; + } + /** + * Translate a single instruction + * @param translationHelper the object containing the translation sequence + * @param ps the process space of the translation + * @param pc the address of the instruction to translate + * @return the address of the next instruction or -1 if this instruction has + * branched to the end of the trace + */ + public int translate(X862IR translationHelper, ProcessSpace ps, + X86_Laziness lazy, int pc) { + translationHelper.plantThrowBadInstruction(lazy, pc); + return -1; + } } /** Modified: src/org/binarytranslator/generic/decoder/DecoderUtils.java =================================================================== --- src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-16 21:25:39 UTC (rev 58) +++ src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-16 21:28:29 UTC (rev 59) @@ -117,9 +117,9 @@ BadInstructionException.class).asClass(); VM_MethodReference badInstrKlassInitMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate(badInstrKlass.getTypeRef(), VM_Atom - .findOrCreateAsciiAtom("<init>"), VM_Atom - .findOrCreateAsciiAtom("(I" + psTref.getName() + ")V")); + .findOrCreate(badInstrKlass.getTypeRef(), + VM_Atom.findOrCreateAsciiAtom("<init>"), + VM_Atom.findOrCreateAsciiAtom("(ILorg/binarytranslator/generic/os/process/ProcessSpace;)V")); badInstrKlassInitMethod = badInstrKlassInitMethRef.resolveInvokeSpecial(); VM_MethodReference recordUncaughtBranchMethRef = (VM_MethodReference) VM_MemberReference @@ -1218,62 +1218,57 @@ * the program counter of the bad instruction */ public void plantThrowBadInstruction(Laziness lazy, int pc) { - // There's a bug with this, so for now I'm just commenting it out :-( -- IAR - setReturnValueResolveLazinessAndBranchToFinish(lazy, - new OPT_IntConstantOperand(0xEBADC0DE)); - if (false) { - // Need to make sure that the PPC_ProcessSpace registers have - // the correct values before call to doSysCall(). - resolveLaziness(lazy); - spillAllRegisters(); + // Need to make sure that the PPC_ProcessSpace registers have + // the correct values before call to doSysCall(). + resolveLaziness(lazy); + spillAllRegisters(); - OPT_Operator newOperator; - OPT_TypeOperand typeOperand = new OPT_TypeOperand(badInstrKlass); - VM_TypeReference eTref = badInstrKlass.getTypeRef(); + OPT_Operator newOperator; + OPT_TypeOperand typeOperand = new OPT_TypeOperand(badInstrKlass); + VM_TypeReference eTref = badInstrKlass.getTypeRef(); - if (badInstrKlass.isInitialized() || badInstrKlass.isInBootImage()) { - newOperator = NEW; - } else { - newOperator = NEW_UNRESOLVED; - } + if (badInstrKlass.isInitialized() || badInstrKlass.isInBootImage()) { + newOperator = NEW; + } else { + newOperator = NEW_UNRESOLVED; + } - OPT_RegisterOperand eRef = gc.temps.makeTemp(eTref); + OPT_RegisterOperand eRef = gc.temps.makeTemp(eTref); - OPT_Instruction n = New.create(newOperator, eRef, typeOperand); - n.position = gc.inlineSequence; - n.bcIndex = DBT_Trace.BAD_INSTRUCTION_NEW; + OPT_Instruction n = New.create(newOperator, eRef, typeOperand); + n.position = gc.inlineSequence; + n.bcIndex = DBT_Trace.BAD_INSTRUCTION_NEW; - OPT_Operand psRef = gc.makeLocal(1, psTref); + appendInstructionToCurrentBlock(n); - OPT_Instruction c = Call.create(CALL, null, null, null, null, 3); + OPT_Operand psRef = gc.makeLocal(1, psTref); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL( - badInstrKlassInitMethod.getMemberRef().asMethodReference(), - badInstrKlassInitMethod); - Call.setParam(c, 0, eRef.copy()); // 'this' pointer in - // BadInstructionException.init - Call.setParam(c, 1, new OPT_IntConstantOperand(pc)); - Call.setParam(c, 2, psRef); - Call.setGuard(c, new OPT_TrueGuardOperand()); - Call.setMethod(c, methOp); - Call.setAddress(c, new OPT_AddressConstantOperand(badInstrKlassInitMethod - .getOffset())); - c.position = gc.inlineSequence; - c.bcIndex = DBT_Trace.BAD_INSTRUCTION_INIT; + OPT_Instruction c = Call.create(CALL, null, null, null, null, 3); - OPT_Instruction t = Athrow.create(ATHROW, eRef.copyRO()); - t.position = gc.inlineSequence; - t.bcIndex = DBT_Trace.BAD_INSTRUCTION_THROW; + OPT_MethodOperand methOp = OPT_MethodOperand.SPECIAL( + badInstrKlassInitMethod.getMemberRef().asMethodReference(), + badInstrKlassInitMethod); + Call.setParam(c, 0, eRef.copy()); // 'this' pointer in + // BadInstructionException.init + Call.setParam(c, 1, new OPT_IntConstantOperand(pc)); + Call.setParam(c, 2, psRef); + Call.setGuard(c, new OPT_TrueGuardOperand()); + Call.setMethod(c, methOp); + Call.setAddress(c, new OPT_AddressConstantOperand(badInstrKlassInitMethod + .getOffset())); + c.position = gc.inlineSequence; + c.bcIndex = DBT_Trace.BAD_INSTRUCTION_INIT; - appendInstructionToCurrentBlock(n); + appendInstructionToCurrentBlock(c); - appendInstructionToCurrentBlock(c); + OPT_Instruction t = Athrow.create(ATHROW, eRef.copyRO()); + t.position = gc.inlineSequence; + t.bcIndex = DBT_Trace.BAD_INSTRUCTION_THROW; - appendInstructionToCurrentBlock(t); + appendInstructionToCurrentBlock(t); - setReturnValueResolveLazinessAndBranchToFinish(lazy, - new OPT_IntConstantOperand(0xEBADC0DE)); - } + setReturnValueResolveLazinessAndBranchToFinish(lazy, + new OPT_IntConstantOperand(0xEBADC0DE)); } // -oO Trace helping methods Oo- Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-04-16 21:25:39 UTC (rev 58) +++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-04-16 21:28:29 UTC (rev 59) @@ -8,6 +8,7 @@ */ package org.binarytranslator.generic.memory; +import org.binarytranslator.DBT; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_Trace; import org.binarytranslator.vmInterface.TranslationHelper; @@ -436,8 +437,9 @@ case DBT_Trace.MEMORY_LOAD32: return load32.getMemberRef().asMethodReference(); default: - throw new Error("Error linking method at " + callAddress - + " for memory model " + this.getClass()); + DBT.write(callAddress); + DBT.fail("Trying to dynamic link inside a DBT trace for an unknown dynamic link location"); + return null; } } } Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-16 21:25:39 UTC (rev 58) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-16 21:28:29 UTC (rev 59) @@ -44,7 +44,7 @@ * Debug information * @param s string of debug information */ - private static void report(String s){ + private static void report(String s) { if (DBT_Options.debugLoader) { System.out.print("ELF Loader:"); System.out.println(s); @@ -63,10 +63,12 @@ * Do we need to byte swap multi-byte values? */ private final boolean needsBswap; + /** * File to read from */ RandomAccessFile rFile; + /** * Constructor * @param rFile file to read from @@ -76,19 +78,23 @@ this.rFile = rFile; this.needsBswap = needsBswap; } + /** * Byte swap a 32-bit integer */ - private static int bswap (int x) { - return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | (x >>> 24); + private static int bswap(int x) { + return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) + | (x >>> 24); } + /** * Byte swap a 16-bit integer */ - private static short bswap (short x) { - short result = (short)(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); + private static short bswap(short x) { + short result = (short) (((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); return result; } + /** * Read a 32bit int value */ @@ -96,6 +102,7 @@ int result = rFile.readInt(); return needsBswap ? bswap(result) : result; } + /** * Read a 16bit short value */ @@ -103,6 +110,7 @@ short result = rFile.readShort(); return needsBswap ? bswap(result) : result; } + /** * Seek to location from beginning of file */ @@ -120,12 +128,11 @@ * @param filename the program file name * @return process space containing loaded binary */ - public ProcessSpace readBinary(String filename) throws IOException - { + public ProcessSpace readBinary(String filename) throws IOException { report("Opening File: " + filename); RandomAccessFile rFile = new RandomAccessFile(filename, "r"); - elfHeader = new ELF_Header(rFile); //NB also sets up reader + elfHeader = new ELF_Header(rFile); // NB also sets up reader report("ELF header read successfully"); ProcessSpace ps = ProcessSpace.createProcessSpaceFromBinary(this); @@ -135,52 +142,50 @@ segmentHeaders = readHeaders(); report("Creating program segments"); - for(int i=0; i < segmentHeaders.length; i++){ + for (int i = 0; i < segmentHeaders.length; i++) { report("Creating: " + segmentHeaders[i]); segmentHeaders[i].create(ps); } int brk; - if(segmentHeaders.length > 1) { + if (segmentHeaders.length > 1) { brk = segmentHeaders[1].getEnd(); } else { - brk = segmentHeaders[0].getEnd(); + brk = segmentHeaders[0].getEnd(); } - report("Initialising the process space: "+ - "entry = 0x" + Integer.toHexString(elfHeader.getEntryPoint()) + - " brk = 0x" + Integer.toHexString(brk) - ); + report("Initialising the process space: " + "entry = 0x" + + Integer.toHexString(elfHeader.getEntryPoint()) + " brk = 0x" + + Integer.toHexString(brk)); ps.initialise(this, elfHeader.getEntryPoint(), brk); return ps; } - + /** - * Determine if the id array corresponds with the initial part of an - * ELF binary + * Determine if the id array corresponds with the initial part of an ELF + * binary * @param filename Name of the file to check * @return whether this is an ELF binary */ public static boolean conforms(String filename) { - + RandomAccessFile rFile = null; report("Testing is file is ELF: " + filename); - + try { rFile = new RandomAccessFile(filename, "r"); byte[] id = new byte[4]; rFile.read(id); - - return (id[0] == 0x7f) && (id[1] == 'E') && (id[2] == 'L') && (id[3] == 'F'); - } - catch (Exception e) { + + return (id[0] == 0x7f) && (id[1] == 'E') && (id[2] == 'L') + && (id[3] == 'F'); + } catch (Exception e) { return false; - } - finally { + } finally { try { rFile.close(); + } catch (Exception e) { } - catch(Exception e) {} } } @@ -188,9 +193,10 @@ * Read and construct the program segment headers */ private ELF_ProgramSegmentHeader[] readHeaders() throws IOException { - ELF_ProgramSegmentHeader segmentHeaders[] = new ELF_ProgramSegmentHeader[elfHeader.getNumberOfProgramSegmentHeaders()]; + ELF_ProgramSegmentHeader segmentHeaders[] = new ELF_ProgramSegmentHeader[elfHeader + .getNumberOfProgramSegmentHeaders()]; reader.seek(elfHeader.getProgramSegmentHeaderOffset()); - for(int i=0; i < segmentHeaders.length; i++) { + for (int i = 0; i < segmentHeaders.length; i++) { segmentHeaders[i] = new ELF_ProgramSegmentHeader(); } return segmentHeaders; @@ -202,6 +208,7 @@ public String getABIString() { return elfHeader.getABIString(); } + /** * Return the architecture (ISA) supported by this file */ @@ -215,13 +222,14 @@ public boolean isX86_ISA() { return elfHeader.isX86_ISA(); } + /** * Is the ELF's machine field PowerPC */ public boolean isPPC_ISA() { return elfHeader.isPPC_ISA(); } - + /** * Is this binary for the ARM architecture? */ @@ -235,13 +243,14 @@ public boolean isSysV_ABI() { return elfHeader.isSysV_ABI(); } + /** * Does this file support the Linux ABI? */ public boolean isLinuxABI() { return elfHeader.isLinuxABI(); } - + /** * Does this file support the ARM ABI? * @return @@ -268,6 +277,7 @@ * Size of ELF identity structure */ private static final int EI_NIDENT = 16; + /** * Backing store for identity structure: * {0x7f,'E','L','F',class,data,version,padding..} @@ -277,24 +287,30 @@ /** * ELF Magic numbers locations in identity */ - private static final int EI_MAG0 = 0, EI_MAG1 = 1, EI_MAG2 = 2, EI_MAG3 = 3; + private static final int EI_MAG0 = 0, EI_MAG1 = 1, EI_MAG2 = 2, + EI_MAG3 = 3; + /** * ELF magic values indicating an ELF file */ - private static final byte ELFMAG0 = 0x7f, ELFMAG1 = 'E', ELFMAG2 = 'L', ELFMAG3 = 'F'; + private static final byte ELFMAG0 = 0x7f, ELFMAG1 = 'E', ELFMAG2 = 'L', + ELFMAG3 = 'F'; /** * Location of class data in identity structure */ private static final int EI_CLASS = 4; + /** * ELF file is invalid */ private static final byte ELFCLASSNONE = 0; + /** * ELF file contains 32bit data */ private static final byte ELFCLASS32 = 1; + /** * ELF file contains 64bit data */ @@ -304,30 +320,39 @@ * Location of data information in identity structure */ private static final int EI_DATA = 5; + /** * Invalid data encoding */ private static final byte ELFDATANONE = 0; + /** * LSB or little-endian encoding N.B. not the native Java format */ private static final byte ELFDATA2LSB = 1; + /** * MSB or big-endian encoding N.B. the native Java format */ private static final byte ELFDATA2MSB = 2; + /** * Is this ELF MSB encoded? */ boolean isMSB() throws IOException { switch (e_ident[EI_DATA]) { - case ELFDATA2LSB: return false; - case ELFDATA2MSB: return true; - default: throw new IOException("Unrecognized data encoding"); + case ELFDATA2LSB: + return false; + case ELFDATA2MSB: + return true; + default: + throw new IOException("Unrecognized data encoding"); } } + /** - * Location of version data - should be EV_CURRENT as defined by the ELF header + * Location of version data - should be EV_CURRENT as defined by the ELF + * header */ private static final int EI_VERSION = 6; @@ -335,104 +360,133 @@ * Location of OS ABI data */ private static final int EI_OSABI = 7; + /** * UNIX System V ABI. */ private static final byte ELFOSABI_SYSV = 0; + /** * HP-UX ABI */ private static final byte ELFOSABI_HPUX = 1; + /** * NetBSD ABI */ private static final byte ELFOSABI_NETBSD = 2; + /** * Linux ABI */ private static final byte ELFOSABI_LINUX = 3; + /** * Solaris ABI */ private static final byte ELFOSABI_SOLARIS = 6; + /** * AIX ABI */ private static final byte ELFOSABI_AIX = 7; + /** * IRIX ABI */ private static final byte ELFOSABI_IRIX = 8; + /** * FreeBSD ABI */ private static final byte ELFOSABI_FREEBSD = 9; + /** * TRU64 UNIX ABI */ private static final byte ELFOSABI_TRU64 = 10; + /** * Novell Modesto */ private static final byte ELFOSABI_MODESTO = 11; + /** * Open BSD */ private static final byte ELFOSABI_OPENBSD = 12; + /** * Open VMS */ private static final byte ELFOSABI_OPENVMS = 13; + /** * Hewlett-Packard Non-Stop Kernel */ private static final byte ELFOSABI_NSK = 14; - + /** - * ARM ABI, probably using the ARM AAPCS. + * ARM ABI, probably using the ARM AAPCS. */ private static final byte ELFOSABI_ARM = 97; - + /** * Return the application binary interface (ABI) supported by this file */ String getABIString() { - switch(e_ident[EI_OSABI]) { - case ELFOSABI_SYSV: return "SysV"; - case ELFOSABI_HPUX: return "HP-UX"; - case ELFOSABI_NETBSD: return "NetBSD"; - case ELFOSABI_LINUX: return "Linux"; - case ELFOSABI_SOLARIS: return "Solaris"; - case ELFOSABI_AIX: return "AIX"; - case ELFOSABI_IRIX: return "IRIX"; - case ELFOSABI_FREEBSD: return "FreeBSD"; - case ELFOSABI_TRU64: return "TRU64"; - case ELFOSABI_MODESTO: return "Novell Modesto"; - case ELFOSABI_OPENBSD: return "OpenBSD"; - case ELFOSABI_OPENVMS: return "OpenVMS"; - case ELFOSABI_NSK: return "Hewlett-Packard Non-Stop Kernel"; - case ELFOSABI_ARM: return "ARM ABI"; + switch (e_ident[EI_OSABI]) { + case ELFOSABI_SYSV: + return "SysV"; + case ELFOSABI_HPUX: + return "HP-UX"; + case ELFOSABI_NETBSD: + return "NetBSD"; + case ELFOSABI_LINUX: + return "Linux"; + case ELFOSABI_SOLARIS: + return "Solaris"; + case ELFOSABI_AIX: + return "AIX"; + case ELFOSABI_IRIX: + return "IRIX"; + case ELFOSABI_FREEBSD: + return "FreeBSD"; + case ELFOSABI_TRU64: + return "TRU64"; + case ELFOSABI_MODESTO: + return "Novell Modesto"; + case ELFOSABI_OPENBSD: + return "OpenBSD"; + case ELFOSABI_OPENVMS: + return "OpenVMS"; + case ELFOSABI_NSK: + return "Hewlett-Packard Non-Stop Kernel"; + case ELFOSABI_ARM: + return "ARM ABI"; default: return "Unknown ELF ABI: " + e_ident[EI_OSABI]; } } + /** * Does this file support the SysV ABI? */ boolean isSysV_ABI() { return e_ident[EI_OSABI] == ELFOSABI_SYSV; } + /** * Does this file support the Linux ABI? */ boolean isLinuxABI() { return e_ident[EI_OSABI] == ELFOSABI_LINUX; } - + boolean isARM_ABI() { return e_ident[EI_OSABI] == ELFOSABI_ARM; } - + /** * Location of OS ABI version data */ @@ -450,10 +504,8 @@ // Identification is in bytes and therefore is endian agnostic rFile.read(e_ident); // Check magic is correct - if ((ELFMAG0 != e_ident[EI_MAG0]) || - (ELFMAG1 != e_ident[EI_MAG1]) || - (ELFMAG2 != e_ident[EI_MAG2]) || - (ELFMAG3 != e_ident[EI_MAG3])) { + if ((ELFMAG0 != e_ident[EI_MAG0]) || (ELFMAG1 != e_ident[EI_MAG1]) + || (ELFMAG2 != e_ident[EI_MAG2]) || (ELFMAG3 != e_ident[EI_MAG3])) { throw new IOException("Bad ELF file magic: " + rFile); } } @@ -470,19 +522,21 @@ String getABIString() { return identity.getABIString(); } + /** * Does this file support the SysV ABI? */ boolean isSysV_ABI() { return identity.isSysV_ABI(); } + /** * Does this file support the Linux ABI? */ boolean isLinuxABI() { return identity.isLinuxABI(); } - + /** * Does this file support the ARM ABI? */ @@ -494,95 +548,117 @@ * Object file type */ private short e_type; + /** * No file type */ private static final short ET_NONE = 0; + /** * Relocatable file */ private static final short ET_REL = 1; + /** * Executable file */ private static final short ET_EXEC = 2; + /** * Shared object file */ private static final short ET_DYN = 3; + /** * Core file */ private static final short ET_CORE = 4; + /** * Number of defined types */ private static final short ET_NUM = 5; + /** * Start of OS reserved region */ - private static final short ET_LOOS = (short)0xfe00; + private static final short ET_LOOS = (short) 0xfe00; + /** * End of OS reserved region */ - private static final short ET_HIOS = (short)0xfeff; + private static final short ET_HIOS = (short) 0xfeff; + /** * Start of processor-specific reserved region */ - private static final short ET_LOPROC = (short)0xff00; + private static final short ET_LOPROC = (short) 0xff00; + /** * End of processor-specific reserved region */ - private static final short ET_HIPROC = (short)0xffff; + private static final short ET_HIPROC = (short) 0xffff; /** * The required architecture (machine) for the object file */ private short e_machine; + /** * No machine */ private static final short EM_NONE = 0; + /** * AT&T WE 32100 */ - private static final short EM_M32 = 1 ; + private static final short EM_M32 = 1; + /** * SPARC */ private static final short EM_SPARC = 2; + /** * Intel 80386 */ private static final short EM_386 = 3; + /** * Motoral 68000 */ private static final short EM_68K = 4; + /** * Motorola 88000 */ private static final short EM_88K = 5; - /** + + /** * Intel 80860 */ private static final short EM_860 = 7; - /** + + /** * MIPS RS3000 */ private static final short EM_MIPS = 8; + /** * PowerPC */ private static final short EM_PPC = 20; + /** * ARM */ private static final short EM_ARM = 40; + /** * Alpha */ private static final short EM_ALPHA = 41; + /** * Sparc V9 */ @@ -594,37 +670,50 @@ boolean isX86_ISA() { return e_machine == EM_386; } + /** * Is the ELF's machine field PowerPC */ boolean isPPC_ISA() { return e_machine == EM_PPC; } - + /** * Is the elf binary for an ARM architecture? */ boolean isARM_ISA() { return e_machine == EM_ARM; } - + /** * Return the architecture (ISA) supported by this file */ public String getArchitectureString() { - switch(e_machine) { - case EM_M32: return "AT&T WE 32100"; - case EM_SPARC: return "SPARC"; - case EM_386: return "Intel 80386"; - case EM_68K: return "Motorola 68000"; - case EM_88K: return "Motorola 88000"; - case EM_860: return "Intel 80860"; - case EM_MIPS: return "MIPS RS3000"; - case EM_PPC: return "PowerPC"; - case EM_ARM: return "ARM"; - case EM_ALPHA: return "Alpha"; - case EM_SPARCV9: return "SPARC V9"; - default: return "Unknown architecture " + e_machine; + switch (e_machine) { + case EM_M32: + return "AT&T WE 32100"; + case EM_SPARC: + return "SPARC"; + case EM_386: + return "Intel 80386"; + case EM_68K: + return "Motorola 68000"; + case EM_88K: + return "Motorola 88000"; + case EM_860: + return "Intel 80860"; + case EM_MIPS: + return "MIPS RS3000"; + case EM_PPC: + return "PowerPC"; + case EM_ARM: + return "ARM"; + case EM_ALPHA: + return "Alpha"; + case EM_SPARCV9: + return "SPARC V9"; + default: + return "Unknown architecture " + e_machine; } } @@ -632,20 +721,23 @@ * Object file version */ private int e_version; + /** * Invalid version */ private static final int EV_NONE = 0; + /** - * Current version + * Current version */ private static final int EV_CURRENT = 1; /** - * Entry point virtual address. The virtual address to which the - * system first transfers control, thus starting the process. + * Entry point virtual address. The virtual address to which the system + * first transfers control, thus starting the process. */ private int e_entry; + /** * Return the entry point of the binary */ @@ -657,6 +749,7 @@ * Program header table file offset */ private int e_phoff; + /** * What is the offset in the file of the program headers */ @@ -683,6 +776,7 @@ * Program header table entry size */ private short e_phentsize; + /** * What's the size of a program segment header? */ @@ -694,17 +788,19 @@ * Program header table entry count */ private short e_phnum; + /** * How many program segments are in this ELF binary? */ - int getNumberOfProgramSegmentHeaders(){ - return e_phnum; + int getNumberOfProgramSegmentHeaders() { + return e_phnum; } /** * Section header table entry size */ private short e_shentsize; + /** * Section header table entry count */ @@ -713,7 +809,7 @@ /** * Section header table index */ - private short e_shstrndx; + private short e_shstrndx; /** * Construct/read ELF header @@ -723,33 +819,31 @@ // Identification is in bytes and therefore is endian agnostic identity = new ELF_Identity(rFile); // Set up reader to handle endianness for the rest of the file - reader = new ELF_BinaryReader(rFile,!identity.isMSB()); + reader = new ELF_BinaryReader(rFile, !identity.isMSB()); // Read in rest of header - e_type = reader.readShort(); + e_type = reader.readShort(); e_machine = reader.readShort(); e_version = reader.readInt(); - e_entry = reader.readInt(); - e_phoff = reader.readInt(); - e_shoff = reader.readInt(); - e_flags = reader.readInt(); - e_ehsize = reader.readShort(); + e_entry = reader.readInt(); + e_phoff = reader.readInt(); + e_shoff = reader.readInt(); + e_flags = reader.readInt(); + e_ehsize = reader.readShort(); e_phentsize = reader.readShort(); - e_phnum = reader.readShort(); + e_phnum = reader.readShort(); e_shentsize = reader.readShort(); - e_shnum = reader.readShort(); - e_shstrndx = reader.readShort(); - } - catch(IOException e) { + e_shnum = reader.readShort(); + e_shstrndx = reader.readShort(); + } catch (IOException e) { throw new Error(e); } } } /** - * Header representing a segment in the process (e.g. stack, heap, - * code aka text) in the ELF file. These are known as program - * header's in the ELF literature, but they don't represent - * programs, rather separate segments. + * Header representing a segment in the process (e.g. stack, heap, code aka + * text) in the ELF file. These are known as program header's in the ELF + * literature, but they don't represent programs, rather separate segments. */ @SuppressWarnings("unused") class ELF_ProgramSegmentHeader { @@ -757,98 +851,120 @@ * Type of the segment */ private final int p_type; + /** * Null header, contains no data and can be ignored */ private static final int PT_NULL = 0; + /** * A loadable segment */ private static final int PT_LOAD = 1; + /** * Segment containing dynamic linking information */ private static final int PT_DYNAMIC = 2; + /** * A segment containing a string to invoke as interpreter for this file */ private static final int PT_INTERP = 3; + /** * A segment describing the location and size of auxiliary information */ private static final int PT_NOTE = 4; + /** * A reserved segment type with unspecified semantics */ private static final int PT_SHLIB = 5; + /** - * A segment describing the ELF's header, present once before any - * loadable segments + * A segment describing the ELF's header, present once before any loadable + * segments */ private static final int PT_PHDR = 6; + /** * Thread local storage (TLS) segment */ private static final int PT_TLS = 7; + /** * Number of defined types */ private static final int PT_NUM = 8; + /** * Start of OS reserved segment types */ private static final int PT_LOOS = 0x60000000; + /** * SUN unwind table segment */ private static final int PT_SUNW_UNWIND = 0x6464e550; + /** * GCC .eh_frame_hdr segment */ private static final int PT_GNU_EH_FRAME = 0x6474e550; + /** * Indicates stack executability */ private static final int PT_GNU_STACK = 0x6474e551; + /** * Read-only after relocation */ private static final int PT_GNU_RELRO = 0x6474e552; + /** * Start of SUN reserved segments */ private static final int PT_LOSUNW = 0x6ffffffa; + /** - * The array element has the same attributes as a PT_LOAD element - * and is used to describe a .SUNW_bss section. + * The array element has the same attributes as a PT_LOAD element and is + * used to describe a .SUNW_bss section. */ private static final int PT_SUNWBSS = 0x6ffffffa; + /** - * Describes a process stack. Only one PT_SUNWSTACK element can - * exist. Only access permissions, as defined in the p_flags - * field, are meaningful. + * Describes a process stack. Only one PT_SUNWSTACK element can exist. Only + * access permissions, as defined in the p_flags field, are meaningful. */ private static final int PT_SUNWSTACK = 0x6ffffffb; + /** * Reserved for internal use by dtrace */ private static final int PT_SUNWDTRACE = 0x6ffffffc; + /** * Specifies hardware capability requirements */ private static final int PT_SUNWCAP = 0x6ffffffd; + /** * End of SUN reserved segments */ private static final int PT_HISUNW = 0x6fffffff; + /** * End of OS reserved segment types */ private static final int PT_HIOS = 0x6fffffff; + /** * Start of processor reserved segment types */ private static final int PT_LOPROC = 0x70000000; + /** * End of processor reserved segment types */ @@ -865,7 +981,7 @@ private final int p_vaddr; /** - * Corresponding physical addressed used by some systems + * Corresponding physical addressed used by some systems */ private final int p_paddr; @@ -883,32 +999,37 @@ * Read/Write/Execute flags for segment in memory */ private final int p_flags; + /** * Executable flag */ private static final int PF_X = 0x1; + /** * Writable flag */ private static final int PF_W = 0x2; + /** * Readable flag */ private static final int PF_R = 0x4; + /** * OS specific reserved bits */ private static final int PF_MASKOS = 0x0ff00000; + /** * Processor specific reserved bits */ private static final int PF_MASKPROC = 0xf0000000; /** - * This member gives the value to which the segments are aligned in - * memory and in the file. Values 0 and 1 mean no alignment is - * required. Otherwise, p_align should be a positive, integral - * power of 2, and p_vaddr should equal p_offset, modulo p_align. + * This member gives the value to which the segments are aligned in memory + * and in the file. Values 0 and 1 mean no alignment is required. Otherwise, + * p_align should be a positive, integral power of 2, and p_vaddr should + * equal p_offset, modulo p_align. */ private final int p_align; @@ -927,65 +1048,59 @@ // Move file onto next program segment header offset reader.rFile.skipBytes(elfHeader.getProgramSegmentHeaderSize() - 32); } + /** * Load/create the program segment */ void create(ProcessSpace ps) { - switch(p_type) { + switch (p_type) { case PT_NULL: // Null header, contains no data and can be ignored break; case PT_LOAD: // A loadable segment try { - createSegment(ps.memory, - reader.rFile, - p_offset, p_vaddr, - p_filesz, p_memsz, - (p_flags & PF_R) != 0, (p_flags & PF_W) != 0, (p_flags & PF_X) != 0); - } - catch(MemoryMapException e) { + createSegment(ps.memory, reader.rFile, p_offset, p_vaddr, p_filesz, + p_memsz, (p_flags & PF_R) != 0, (p_flags & PF_W) != 0, + (p_flags & PF_X) != 0); + } catch (MemoryMapException e) { throw new Error("Error in creating: " + this, e); } break; - case PT_NOTE: // A segment describing the location and size of auxiliary information + case PT_NOTE: // A segment describing the location and size of auxiliary + // information // ignore break; case PT_GNU_STACK: // A segment describing the permissions for the stack // ignore break; - case PT_INTERP: // A segment containing a string to invoke as interpreter for this file + case PT_TLS: // A segment describing thread local storage + // ignore for now + break; + case PT_INTERP: // A segment containing a string to invoke as interpreter + // for this file case PT_DYNAMIC: // Segment containing dynamic linking information - case PT_SHLIB: // A reserved segment type with unspecified semantics - case PT_PHDR: // A segment describing the ELF's header; present once before any loadable segments + case PT_SHLIB: // A reserved segment type with unspecified semantics + case PT_PHDR: // A segment describing the ELF's header; present once + // before any loadable segments default: throw new Error("Segment type " + toString() + " not yet supported"); } } - + /** * Create a segment - * - * @param memory - * The memory into which the segment is to be mapped. - * @param file - * file to read segment data from if file size != 0 - * @param offset - * file offset - * @param address - * location of segment - * @param filesize - * size of segment in file - * @param memsize - * size of segment in memory - * @param read - * is segment readable - * @param write - * is segment writable - * @param exec - * is segment executable + * @param memory The memory into which the segment is to be mapped. + * @param file file to read segment data from if file size != 0 + * @param offset file offset + * @param address location of segment + * @param filesize size of segment in file + * @param memsize size of segment in memory + * @param read is segment readable + * @param write is segment writable + * @param exec is segment executable */ - public void createSegment(Memory memory, RandomAccessFile file, long offset, int address, - int filesize, int memsize, boolean read, boolean write, boolean exec) - throws MemoryMapException { + public void createSegment(Memory memory, RandomAccessFile file, + long offset, int address, int filesize, int memsize, boolean read, + boolean write, boolean exec) throws MemoryMapException { // Sanity check if (memsize < filesize) { throw new Error("Segment memory size (" + memsize @@ -1024,12 +1139,13 @@ } /** - * Round the give value up so that it is at the beginning of the - * next aligned region + * Round the give value up so that it is at the beginning of the next + * aligned region */ private int truncateToNextAlignment(int x) { return ((x + p_align - 1) / p_align) * p_align; } + /** * Get the end of the segment */ @@ -1041,20 +1157,23 @@ * String representation of header */ public String toString() { - switch(p_type) { + switch (p_type) { case PT_NULL: return "Null segment header (ignored)"; case PT_LOAD: - return - "Loadable segment (offset=0x" + Long.toHexString(p_offset) + - ", address=0x"+ Integer.toHexString(p_vaddr)+ - ", file size=" + p_filesz + - ", memory size=" + p_memsz + - ", permissions=" + - (((p_flags & PF_R) != 0) ? 'r' : '-') + - (((p_flags & PF_W) != 0) ? 'w' : '-') + - (((p_flags & PF_X) != 0) ? 'x' : '-') + - ")"; + return "Loadable segment (offset=0x" + Long.toHexString(p_offset) + + ", address=0x" + Integer.toHexString(p_vaddr) + ", file size=" + + p_filesz + ", memory size=" + p_memsz + ", permissions=" + + (((p_flags & PF_R) != 0) ? 'r' : '-') + + (((p_flags & PF_W) != 0) ? 'w' : '-') + + (((p_flags & PF_X) != 0) ? 'x' : '-') + ")"; + case PT_TLS: + return "TLS segment (offset=0x" + Long.toHexString(p_offset) + + ", address=0x" + Integer.toHexString(p_vaddr) + ", file size=" + + p_filesz + ", memory size=" + p_memsz + ", permissions=" + + (((p_flags & PF_R) != 0) ? 'r' : '-') + + (((p_flags & PF_W) != 0) ? 'w' : '-') + + (((p_flags & PF_X) != 0) ? 'x' : '-') + ")"; case PT_NOTE: return "Note: segment containing auxiliary information"; case PT_INTERP: @@ -1068,18 +1187,15 @@ case PT_GNU_STACK: return "GNU stack executability"; default: - if((p_type > PT_LOPROC) && (p_type <= PT_HIPROC)) { + if ((p_type > PT_LOPROC) && (p_type <= PT_HIPROC)) { return "Processor specific segment 0x" + Integer.toHexString(p_type); - } - else if ((p_type > PT_LOOS) && (p_type <= PT_HIOS)) { - if((p_type > PT_LOSUNW) && (p_type <= PT_HISUNW)){ - return "Sun OS specific segment 0x" + Integer.toHexString(p_type); + } else if ((p_type > PT_LOOS) && (p_type <= PT_HIOS)) { + if ((p_type > PT_LOSUNW) && (p_type <= PT_HISUNW)) { + return "Sun OS specific segment 0x" + Integer.toHexString(p_type); + } else { + return "OS specific segment 0x" + Integer.toHexString(p_type); } - else { - return "OS specific segment 0x" + Integer.toHexString(p_type); - } - } - else { + } else { return "Unknown segment: 0x" + Integer.toHexString(p_type); } } Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-16 21:25:39 UTC (rev 58) +++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-16 21:28:29 UTC (rev 59) @@ -235,7 +235,7 @@ break; case BAD_INSTRUCTION_INIT: dynamicLink.set(DecoderUtils.badInstrKlassInitMethod.getMemberRef() - .asMethodReference(), JBC_invokevirtual); + .asMethodReference(), JBC_invokespecial); break; case MEMORY_STORE8: case MEMORY_STORE16: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-17 18:11:38
|
Revision: 60 http://svn.sourceforge.net/pearcolator/?rev=60&view=rev Author: michael_baer Date: 2007-04-17 11:11:39 -0700 (Tue, 17 Apr 2007) Log Message: ----------- Temporarily saving progress made while implementing an initial ARM interpreter. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java src/org/binarytranslator/generic/decoder/DisassembledInstruction.java Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/generic/decoder/Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-17 18:11:39 UTC (rev 60) @@ -164,7 +164,10 @@ op.getShiftAmount()); case PcRelative: - return String.format("#%x", op.getOffset() + address + 8); + if (address != -1) + return String.format("#%x", op.getOffset() + address + 8); + else + return String.format("#<%x + pc>", op.getOffset()); case Register: return "r" + op.getRegister(); @@ -312,9 +315,11 @@ public void visit(Branch instr) { String mnemonic = instr.link() ? "BL" : "B"; - setResult(String.format("%s%s #%x", mnemonic, cond(instr), instr - .getOffset() - + address)); + + if (address != -1) + setResult(String.format("%s%s #%x", mnemonic, cond(instr), instr.getOffset() + address + 8)); + else + setResult(String.format("%s%s #<%x + pc>", mnemonic, cond(instr), instr.getOffset())); } public void visit(BranchExchange instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-17 18:11:39 UTC (rev 60) @@ -51,7 +51,7 @@ * An object representation of the decoded instruction. */ static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { - if (getBit(instruction, 27)) { + if (Utils.getBit(instruction, 27)) { return decode_1xx(instruction, factory); } else { @@ -59,29 +59,14 @@ } } - /** - * Checks if a bit is set within a word. - * @param word - * The word that is being examined. - * @param bit - * The number of the bit that is to be checked, starting from zero. - * @return - * True, if the given bit is set within the word, false otherwise. - */ - private static final boolean getBit(int word, int bit) { - if (DBT.VerifyAssertions) - DBT._assert(bit >= 0 && bit <= 31); - return (word & (1 << bit)) != 0; - } - private static <T> T decode_0xx(int instr, ARM_InstructionFactory<T> factory) { if ((instr & 0xF0000000) == 0xF0000000) { return factory.createUndefinedInstruction(instr); } - if (getBit(instr, 26)) { + if (Utils.getBit(instr, 26)) { //opcode: 01 - if (getBit(instr, 25) && getBit(instr, 4)) + if (Utils.getBit(instr, 25) && Utils.getBit(instr, 4)) return factory.createUndefinedInstruction(instr); else return factory.createSingleDataTransfer(instr); @@ -93,7 +78,7 @@ } private static <T> T decode_1xx(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 26)) { + if (Utils.getBit(instr, 26)) { //opcode: 11 return decode_11x( instr, factory); } @@ -104,14 +89,14 @@ } private static <T> T decode_00x(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 25)) + if (Utils.getBit(instr, 25)) return decode_001(instr, factory); else return decode_000(instr, factory); } private static <T> T decode_10x(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 25)) { + if (Utils.getBit(instr, 25)) { //opcode: 101 if ((instr & 0xF0000000) == 0xF0000000) return factory.createBranchExchange(instr); @@ -129,12 +114,12 @@ private static <T> T decode_000(int instr, ARM_InstructionFactory<T> factory) { //opcode: 000 - if (getBit(instr, 24) && !getBit(instr, 23) && !getBit(instr, 20)) { + if (Utils.getBit(instr, 24) && !Utils.getBit(instr, 23) && !Utils.getBit(instr, 20)) { //opcode: 00010xx0 - those are the new instructions, which the ARM ref. manual calls "misc. instructions" return decode_00010xx0(instr, factory); } else { - if (getBit(instr, 4) == false || getBit(instr, 7) == false) + if (Utils.getBit(instr, 4) == false || Utils.getBit(instr, 7) == false) return factory.createDataProcessing(instr); return decode_multiplies_extra_load_stores(instr, factory); @@ -143,11 +128,11 @@ private static <T> T decode_001(int instr, ARM_InstructionFactory<T> factory) { //opcode: 001 - if (!getBit(instr, 24) || getBit(instr, 23) || getBit(instr, 20)) { + if (!Utils.getBit(instr, 24) || Utils.getBit(instr, 23) || Utils.getBit(instr, 20)) { return factory.createDataProcessing(instr); } - if (getBit(instr, 21)) + if (Utils.getBit(instr, 21)) return factory.createMoveToStatusRegister(instr); else return factory.createUndefinedInstruction(instr); @@ -155,13 +140,13 @@ private static <T> T decode_11x(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 25) == false) { + if (Utils.getBit(instr, 25) == false) { //opcode: 110 return factory.createCoprocessorDataTransfer(instr); } //opcode: 111 - if (getBit(instr, 24)) { + if (Utils.getBit(instr, 24)) { //opcode: 1111 if ((instr & 0xF0000000) == 0xF0000000) return factory.createUndefinedInstruction(instr); @@ -170,7 +155,7 @@ } else { //opcode: 1110 - if (getBit(instr, 4)) { + if (Utils.getBit(instr, 4)) { return factory.createCoprocessorDataTransfer(instr); } else { @@ -185,7 +170,7 @@ */ private static <T> T decode_00010xx0(int instr, ARM_InstructionFactory<T> factory) { // - if (getBit(instr, 6) || getBit(instr, 7)) { + if (Utils.getBit(instr, 6) || Utils.getBit(instr, 7)) { //enhanced DSP multiplications, DSP add/subtracts and software breakpoints //we might want to support these in the future, so when in debug mode, catch if any program actually uses them if (DBT.VerifyAssertions) DBT._assert(false); @@ -193,14 +178,14 @@ } else { //bit 6 and 7 are clear - if (getBit(instr, 4)) { - if (getBit(instr, 22)) + if (Utils.getBit(instr, 4)) { + if (Utils.getBit(instr, 22)) return factory.createCountLeadingZeros(instr); else return factory.createBranchExchange(instr); } else { - if (getBit(instr, 21)) + if (Utils.getBit(instr, 21)) return factory.createMoveToStatusRegister(instr); else return factory.createMoveFromStatusRegister(instr); @@ -215,25 +200,25 @@ */ private static <T> T decode_multiplies_extra_load_stores(int instr, ARM_InstructionFactory<T> factory) { //Here, we already know that bits 4 and 7 are set, while bit 25-27 are clear - if (getBit(instr, 6)) { + if (Utils.getBit(instr, 6)) { //load/store signed half-word or two words - if (getBit(instr, 20)) + if (Utils.getBit(instr, 20)) return factory.createSingleDataTransfer(instr); else return factory.createUndefinedInstruction(instr); //two words immediate offset } else { - if (getBit(instr, 5)) { + if (Utils.getBit(instr, 5)) { //load/store half-word return factory.createSingleDataTransfer(instr); } else { //Multiply, multiply long or Swap - if (getBit(instr, 24)) { + if (Utils.getBit(instr, 24)) { return factory.createSwap(instr); } else { - if (getBit(instr, 23)) + if (Utils.getBit(instr, 23)) return factory.createLongMultiply(instr); else return factory.createIntMultiply(instr); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-17 18:11:39 UTC (rev 60) @@ -17,52 +17,6 @@ */ public class ARM_Instructions { - /** - * Checks if a bit is set within a word. - * @param word - * The word that is being examined. - * @param bit - * The number of the bit that is to be checked, starting from zero. - * @return - * True, if the given bit is set within the word, false otherwise. - */ - private static final boolean getBit(int word, int bit) { - if (DBT.VerifyAssertions) - DBT._assert(bit >= 0 && bit <= 31); - return (word & (1 << bit)) != 0; - } - - /** - * Extracts a subsequence of bits from a word. - * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. - * @param word - * The word that is to be examined. - * @param from - * The first bit (starting from 0) that is to be extracted. - * @param to - * The last bit (starting from 0) that is to be extracted from the word. - * @return - * A zero-based version of the bit sequence. - */ - private static final int getBits(int word, int from, int to) { - if (DBT.VerifyAssertions) - DBT._assert(from < to && from >= 0 && to <= 31); - return (word & ((1 << (to + 1)) - 1)) >> from; - } - - /** - * Sign extends a given value. - * @param value - * The value to sign extends. - * @param bitsUsed - * The number bits used within this values. - * @return - * A sign extended value. - */ - public static int signExtend(int value, int bitsUsed) { - return (value << (32 - bitsUsed)) >> (32 - bitsUsed); - } - /** A base class for all (conditional) ARM instructions. */ public abstract static class Instruction { @@ -74,7 +28,7 @@ protected final Condition condition; private Instruction(int instr) { - condition = Condition.values()[(byte) getBits(instr, 28, 31)]; + condition = Condition.values()[(byte) Utils.getBits(instr, 28, 31)]; } /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ @@ -103,8 +57,8 @@ public TwoRegistersTemplate(int instr) { super(instr); - Rd = (byte) getBits(instr, 12, 15); - Rn = (byte) getBits(instr, 16, 19); + Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); } /** Returns the number of the operation's destination register, starting from 0.*/ @@ -128,7 +82,7 @@ public ThreeRegistersTemplate(int instr) { super(instr); - Rm = (byte) getBits(instr, 0, 3); + Rm = (byte) Utils.getBits(instr, 0, 3); } /** Returns the number of the second operand register, starting from 0.*/ @@ -153,9 +107,9 @@ protected MultiplyTemplate(int instr) { super(instr); - updateConditionCodes = getBit(instr, 20); - accumulate = getBit(instr, 21); - Rs = (byte) getBits(instr, 8, 11); + updateConditionCodes = Utils.getBit(instr, 20); + accumulate = Utils.getBit(instr, 21); + Rs = (byte) Utils.getBits(instr, 8, 11); } /** Returns true, if the condition codes shall be updated by the result of this operation. */ @@ -189,9 +143,9 @@ public CoprocessorTemplate(int instr) { super(instr); - cpNum = (byte) getBits(instr, 8, 11); - Rd = (byte) getBits(instr, 12, 15); - Rn = (byte) getBits(instr, 16, 19); + cpNum = (byte) Utils.getBits(instr, 8, 11); + Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); } /** Returns the coprocessor that shall process this instruction */ @@ -238,32 +192,35 @@ /** Creates an operand wrapper, that represents a register shifted by an immediate or a register, depending on the instruction. */ public static OperandWrapper decodeShiftedRegister(int instr) { - ShiftType shift = ShiftType.values()[getBits(instr, 5, 6)]; + ShiftType shift = ShiftType.values()[Utils.getBits(instr, 5, 6)]; byte shiftedRegister = (byte) (instr & 0xF); - if (getBit(instr, 4)) { + if (Utils.getBit(instr, 4)) { //shift by a register - byte shiftingRegister = (byte)getBits(instr, 8, 11); + byte shiftingRegister = (byte)Utils.getBits(instr, 8, 11); return new RegisterShiftRegisterOperand(shiftedRegister, shift, shiftingRegister); } else { //shift by an immediate - byte immediate = (byte)getBits(instr, 7, 11); + byte immediate = (byte)Utils.getBits(instr, 7, 11); if (immediate == 0) { - //if we are shifting by zero, we might forget about the shift + + if (shift == ShiftType.LSL) { + //If we are shifting by zero with LSL, then this is supposed to denote a register operand + return new RegisterOperand(shiftedRegister); + } + if (shift == ShiftType.ROR) { //However, if the shift type was RotateRight, then ARM meant do a RotateRightExtend by 1 return new RegisterShiftImmediateOperand(shiftedRegister, shift, (byte)1); } - else { - //Otherwise, really forget about the shifting - return new RegisterOperand(shiftedRegister); - } + + //in all other cases, an immediate of zero denotes a shift by 32 + immediate = 32; } - else { - return new RegisterShiftImmediateOperand(shiftedRegister, shift, immediate); - } + + return new RegisterShiftImmediateOperand(shiftedRegister, shift, immediate); } } @@ -305,15 +262,20 @@ /** @see #getImmediate() */ protected final int immediate; - + protected ImmediateOperand(int immediate) { this.immediate = immediate; } - + @Override public int getImmediate() { return immediate; } + + @Override + public byte getShiftAmount() { + return 0; + } @Override public Type getType() { @@ -452,11 +414,11 @@ public DataProcessing(int instr) { super(instr); - updateConditionCodes = getBit(instr, 20); - opcode = Opcode.values()[(byte) getBits(instr, 21, 24)]; + updateConditionCodes = Utils.getBit(instr, 20); + opcode = Opcode.values()[(byte) Utils.getBits(instr, 21, 24)]; - if (getBit(instr, 25)) - operand2 = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); + if (Utils.getBit(instr, 25)) + operand2 = OperandWrapper.createImmediate(Integer.rotateRight(instr & 0xFF, Utils.getBits(instr, 8, 11) << 2)); else operand2 = OperandWrapper.decodeShiftedRegister(instr); } @@ -519,40 +481,40 @@ public SingleDataTransfer(int instr) { super(instr); - preIndexing = getBit(instr, 24); - positiveOffset = getBit(instr, 23); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); + preIndexing = Utils.getBit(instr, 24); + positiveOffset = Utils.getBit(instr, 23); + writeBack = Utils.getBit(instr, 21); + isLoad = Utils.getBit(instr, 20); - if (getBit(instr, 26)) { + if (Utils.getBit(instr, 26)) { //this is an unsigned byte or word transfer signExtend = false; forceUserMode = !preIndexing && writeBack; - if (getBit(instr, 22)) + if (Utils.getBit(instr, 22)) size = TransferSize.Byte; else size = TransferSize.Word; - if (getBit(instr, 25)) + if (Utils.getBit(instr, 25)) offset = OperandWrapper.createImmediate(instr & 0xFF); else offset = OperandWrapper.decodeShiftedRegister(instr); } else { //this is a byte or half-word transfer - if (getBit(instr, 5)) + if (Utils.getBit(instr, 5)) size = TransferSize.HalfWord; else size = TransferSize.Byte; - signExtend = getBit(instr, 6); + signExtend = Utils.getBit(instr, 6); forceUserMode = false; - if (getBit(instr, 22)) { + if (Utils.getBit(instr, 22)) { //immediate offset - offset = OperandWrapper.createImmediate((getBits(instr, 8, 11) << 4) | (instr & 0xF)); + offset = OperandWrapper.createImmediate((Utils.getBits(instr, 8, 11) << 4) | (instr & 0xF)); } else { //register offset @@ -616,7 +578,8 @@ protected IntMultiply(int instr) { super(instr); - if (DBT.VerifyAssertions) DBT._assert(accumulate || Rn == 0); + //check for instruction combinations that show undefined behaviour on ARM + if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); } @Override @@ -634,7 +597,10 @@ public LongMultiply(int instr) { super(instr); - unsigned = getBit(instr, 22); + unsigned = Utils.getBit(instr, 22); + + //check for instruction combinations that show undefined behaviour on ARM + if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); } /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ @@ -666,7 +632,7 @@ public Swap(int instr) { super(instr); - swapByte = getBit(instr, 22); + swapByte = Utils.getBit(instr, 22); } /** Returns true, if a byte shall be swapped or false, if an int (32 bit) shall be swapped. */ @@ -707,12 +673,12 @@ public BlockDataTransfer(int instr) { super(instr); - postIndexing = getBit(instr, 24); - incrementBase = getBit(instr, 23); - forceUser = getBit(instr, 22); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); - baseRegister = (byte) getBits(instr, 16, 19); + postIndexing = Utils.getBit(instr, 24); + incrementBase = Utils.getBit(instr, 23); + forceUser = Utils.getBit(instr, 22); + writeBack = Utils.getBit(instr, 21); + isLoad = Utils.getBit(instr, 20); + baseRegister = (byte) Utils.getBits(instr, 16, 19); registerList = instr; } @@ -721,7 +687,7 @@ if (DBT.VerifyAssertions) DBT._assert(r >= 0 && r < 16); - return getBit(registerList, r); + return Utils.getBit(registerList, r); } /** True if the base register shall be changed after each single transfer, otherwise changed it before each transfer. */ @@ -793,7 +759,7 @@ public Branch(int instr) { super(instr); - link = getBit(instr, 24); + link = Utils.getBit(instr, 24); offset = instr & 0xFFF; } @@ -823,23 +789,23 @@ protected final boolean link; public BranchExchange(int instr) { - super(getBit(instr, 27) ? 0xE0000000 : instr); + super(Utils.getBit(instr, 27) ? 0xE0000000 : instr); - if (getBit(instr, 27)) { + if (Utils.getBit(instr, 27)) { //this is the immediate version of a BLX link = true; //sign extend jump target - int jumpTarget = signExtend(instr & 0xFFF, 24) << 2; + int jumpTarget = Utils.signExtend(instr & 0xFFF, 24) << 2; //are we addressing a half-byte? - if (getBit(instr, 24)) + if (Utils.getBit(instr, 24)) jumpTarget += 2; target = OperandWrapper.createPcRelative(jumpTarget); } else { - link = getBit(instr, 5); + link = Utils.getBit(instr, 5); target = OperandWrapper.createRegister((byte) (instr & 0xF)); } } @@ -881,16 +847,16 @@ public CoprocessorDataTransfer(int instr) { super(instr); - preIndexing = getBit(instr, 24); - largeTransfer = getBit(instr, 22); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); + preIndexing = Utils.getBit(instr, 24); + largeTransfer = Utils.getBit(instr, 22); + writeBack = Utils.getBit(instr, 21); + isLoad = Utils.getBit(instr, 20); if (!writeBack && !preIndexing) { offset = instr & 0xFF; } else { - if (getBit(instr, 23)) + if (Utils.getBit(instr, 23)) offset = (instr & 0xFF) << 2; else offset = - ((instr & 0xFF) << 2); @@ -960,8 +926,8 @@ public CoprocessorDataProcessing(int instr) { super(instr); - opcode = (byte) getBits(instr, 20, 23); - cpInfo = (byte) getBits(instr, 5, 7); + opcode = (byte) Utils.getBits(instr, 20, 23); + cpInfo = (byte) Utils.getBits(instr, 5, 7); cpRm = (byte) (instr & 0xF); } @@ -1014,10 +980,10 @@ public CoprocessorRegisterTransfer(int instr) { super(instr); - opcode = (byte) getBits(instr, 21, 23); - cpInfo = (byte) getBits(instr, 5, 7); + opcode = (byte) Utils.getBits(instr, 21, 23); + cpInfo = (byte) Utils.getBits(instr, 5, 7); cpRm = (byte) (instr & 0xF); - isLoad = getBit(instr, 20); + isLoad = Utils.getBit(instr, 20); } /** Returns true if this operation is a load from a coprocessor or false if it is a store to coprocessor. */ @@ -1068,8 +1034,8 @@ public MoveFromStatusRegister(int instr) { super(instr); - Rd = (byte) getBits(instr, 12, 15); - transferSavedPSR = getBit(instr, 22); + Rd = (byte) Utils.getBits(instr, 12, 15); + transferSavedPSR = Utils.getBit(instr, 22); } /** Returns the number of the destination register. */ @@ -1112,15 +1078,15 @@ public MoveToStatusRegister(int instr) { super(instr); - transferControl = getBit(instr, 16); - transferExtension = getBit(instr, 17); - transferStatus = getBit(instr, 18); - transferFlags = getBit(instr, 19); + transferControl = Utils.getBit(instr, 16); + transferExtension = Utils.getBit(instr, 17); + transferStatus = Utils.getBit(instr, 18); + transferFlags = Utils.getBit(instr, 19); - transferSavedPSR = getBit(instr, 22); + transferSavedPSR = Utils.getBit(instr, 22); - if (getBit(instr, 25)) - sourceOperand = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); + if (Utils.getBit(instr, 25)) + sourceOperand = OperandWrapper.createImmediate((instr & 0xFF) << Utils.getBits(instr, 8, 11)); else sourceOperand = OperandWrapper.decodeShiftedRegister(instr); } @@ -1174,7 +1140,7 @@ super(instr); Rm = (byte) (instr & 0xF); - Rd = (byte) getBits(instr, 12, 15); + Rd = (byte) Utils.getBits(instr, 12, 15); } /** Returns the source register for this operation. */ Added: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-17 18:11:39 UTC (rev 60) @@ -0,0 +1,821 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder.ARM_InstructionFactory; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing.Opcode; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.decoder.Interpreter.Instruction; + +public class ARM_Interpreter { + + protected final ARM_ProcessSpace ps; + + protected final ARM_Registers regs; + + public ARM_Interpreter(ARM_ProcessSpace ps) { + this.ps = ps; + this.regs = ps.registers; + } + + private final class ConditionalDecorator implements Interpreter.Instruction { + + protected final Interpreter.Instruction conditionalInstruction; + + protected ConditionalDecorator(Interpreter.Instruction i) { + conditionalInstruction = i; + } + + public void execute() { + conditionalInstruction.execute(); + } + + public int getSuccessor(int pc) { + return -1; + } + } + + private abstract class DataProcessing extends ARM_Instructions.DataProcessing + implements Interpreter.Instruction { + + protected boolean shifterCarryOut; + + protected DataProcessing(int instr) { + super(instr); + } + + protected final int resolveShift(OperandWrapper operand) { + + int value = regs.get(operand.getRegister()); + byte shiftAmount; + + if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) + shiftAmount = operand.getShiftAmount(); + else { + shiftAmount = (byte) (regs.get(operand.getShiftingRegister()) & 0xF); + } + + switch (operand.getShiftType()) { + case ASR: + + if (shiftAmount > 32) + shiftAmount = 32; + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >>> shiftAmount; + } + + case LSL: + + if (shiftAmount > 32) + shiftAmount = 32; + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, 32 - shiftAmount); + return value << shiftAmount; + } + + case LSR: + + if (shiftAmount > 32) + shiftAmount = 32; + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >> shiftAmount; + } + + case ROR: + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, shiftAmount & 0x1F); + return Integer.rotateRight(value, shiftAmount); + } + + case RRE: + shifterCarryOut = (value & 0x1) != 0; + + if (regs.isCarrySet()) + return (value >> 1) | 0x80000000; + else + return value >> 1; + + default: + throw new RuntimeException("Unexpected shift type: " + + operand.getShiftType()); + } + } + + protected int resolveOperand2() { + int value; + + switch (operand2.getType()) { + case Immediate: + value = operand2.getImmediate(); + + if (operand2.getShiftAmount() == 0) + shifterCarryOut = regs.isCarrySet(); + else + shifterCarryOut = (value & 0x80000000) != 0; + + case Register: + shifterCarryOut = regs.isCarrySet(); + return regs.get(operand2.getRegister()); + + case RegisterShiftedRegister: + case ImmediateShiftedRegister: + return resolveShift(operand2); + + case PcRelative: + default: + throw new RuntimeException("Unexpected wrapped operand type: " + + operand2.getType()); + } + } + + + public abstract void execute(); + + protected final void setFlagsForResult(int result) { + + if (updateConditionCodes) { + if (Rd != 15) { + regs.setFlags(result < 0, result == 0, shifterCarryOut); + } else { + regs.restoreSPSR2CPSR(); + } + } + } + + protected final void setFlagsForAdd(int lhs, int rhs) { + + if (updateConditionCodes) { + if (Rd != 15) { + int result = lhs + rhs; + boolean carry = Utils.unsignedAddOverflow(lhs, rhs); + boolean overflow = Utils.signedAddOverflow(lhs, rhs); + regs.setFlags(result < 0, result == 0, carry, overflow); + } + else { + regs.restoreSPSR2CPSR(); + } + } + } + + public int getSuccessor(int pc) { + if (Rd == 15) + return pc + 4; + else + return -1; + } + } + + private final class DataProcessing_And extends DataProcessing { + + protected DataProcessing_And(int instr) { + super(instr); + } + + + @Override + public void execute() { + int result = regs.get(Rn) & resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private final class DataProcessing_Eor extends DataProcessing { + + protected DataProcessing_Eor(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = regs.get(Rn) ^ resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Add extends DataProcessing { + + public DataProcessing_Add(int instr) { + super(instr); + } + + protected int resolveOperand1() { + return regs.get(Rn); + } + + public void execute() { + int operand1 = resolveOperand1(); + int operand2 = resolveOperand2(); + int result = operand1 + operand2; + + regs.set(Rd, result); + setFlagsForAdd(operand1, operand2); + } + } + + private final class DataProcessing_Sub extends DataProcessing_Add { + + public DataProcessing_Sub(int instr) { + super(instr); + } + + @Override + protected int resolveOperand2() { + return -super.resolveOperand2(); + } + } + + private final class DataProcessing_Rsb extends DataProcessing_Add { + + protected DataProcessing_Rsb(int instr) { + super(instr); + } + + @Override + protected int resolveOperand1() { + return -super.resolveOperand1(); + } + } + + private class DataProcessing_Adc extends DataProcessing_Add { + + protected int cachedOperand1; + protected int cachedOperand2; + + protected DataProcessing_Adc(int instr) { + super(instr); + } + + @Override + protected int resolveOperand1() { + return cachedOperand1; + } + + @Override + protected int resolveOperand2() { + return cachedOperand2; + } + + @Override + public void execute() { + cachedOperand1 = super.resolveOperand1(); + cachedOperand2 = super.resolveOperand2(); + + if (regs.isCarrySet()) { + if (cachedOperand1 != Integer.MAX_VALUE) { + cachedOperand1++; + } else if (cachedOperand2 != Integer.MAX_VALUE) { + cachedOperand2++; + } else { + regs.setFlags(cachedOperand1 > 0, cachedOperand1 != 0, true, true); + return; + } + } + + super.execute(); + } + } + + private class DataProcessing_Sbc extends DataProcessing_Adc { + + protected DataProcessing_Sbc(int instr) { + super(instr); + } + + @Override + protected int resolveOperand2() { + return -cachedOperand2; + } + } + + private class DataProcessing_Rsc extends DataProcessing_Adc { + + protected DataProcessing_Rsc(int instr) { + super(instr); + } + + @Override + protected int resolveOperand1() { + return -cachedOperand1; + } + } + + private class DataProcessing_Tst extends DataProcessing { + + protected DataProcessing_Tst(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForResult(regs.get(Rn) & resolveOperand2()); + } + } + + private class DataProcessing_Teq extends DataProcessing { + + protected DataProcessing_Teq(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForResult(regs.get(Rn) ^ resolveOperand2()); + } + } + + private class DataProcessing_Cmp extends DataProcessing { + + protected DataProcessing_Cmp(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForAdd(regs.get(Rn), -resolveOperand2()); + } + } + + private class DataProcessing_Cmn extends DataProcessing { + + protected DataProcessing_Cmn(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForAdd(regs.get(Rn), resolveOperand2()); + } + } + + private class DataProcessing_Orr extends DataProcessing { + + protected DataProcessing_Orr(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = regs.get(Rn) | resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Mov extends DataProcessing { + + protected DataProcessing_Mov(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Bic extends DataProcessing { + + protected DataProcessing_Bic(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = regs.get(Rn) & (~resolveOperand2()); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Mvn extends DataProcessing { + + protected DataProcessing_Mvn(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = ~resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class Swap extends ARM_Instructions.Swap implements Interpreter.Instruction { + + public Swap(int instr) { + super(instr); + } + + public void execute() { + int memAddr = regs.get(Rn); + + //swap exchanges the value of a memory address with the value in a register + int tmp = ps.memory.load32(memAddr); + ps.memory.store16(memAddr, regs.get(Rm)); + + //according to the ARM architecture reference, the value loaded from a memory address is rotated + //according to the number of ones in the first two bits of the address + regs.set(Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class BlockDataTransfer extends ARM_Instructions.BlockDataTransfer implements Interpreter.Instruction { + + public BlockDataTransfer(int instr) { + super(instr); + } + + public void execute() { + //start address ignores the last two bits + int startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + + //build a map of registers that are to be transfered + int registerCount = 0; + boolean transferPC = false; + int[] registersToTransfer = new int[16]; + + for (int i = 0; i < 14; i++) + if (transferRegister(i)) { + registersToTransfer[registerCount++] = i; + } + + //also remember if we're supposed to transfer the pc, but don't include it in the register list + transferPC = transferRegister(15); + + if (!incrementBase) { + if (postIndexing) + startAddress -= (registerCount + (transferPC ? -1 : 0)) * 4; //post-indexing, backward reading + else + startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; //pre-indexing, backward-reading + } + else if (postIndexing) { + //post-indexing, forward reading + startAddress -= 4; + } + + //are we supposed to load or store multiple registers? + if (isLoad) { + //read the actual registers + for (int i = 0; i < registerCount; i++) { + startAddress += 4; + regs.set(registersToTransfer[i], ps.memory.load32(startAddress)); + } + + //if we also transferred the program counter + if (transferPC) { + int newpc = ps.memory.load32(startAddress + 4); + regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); + + //shall we switch to thumb mode + regs.setThumbMode((newpc & 0x1) != 0); + } + } + else { + //also transfer the program counter, if requested so + if (transferPC) + registersToTransfer[registerCount++] = 15; + + for (int i = 0; i < registerCount; i++) { + startAddress += 4; + ps.memory.store32(startAddress, regs.get(i)); + } + } + } + + public int getSuccessor(int pc) { + //if we're loading values into the PC, then we can't tell where this instruction will be going + if (isLoad && transferRegister(ARM_Registers.PC)) + return -1; + else + return pc+4; + } + } + + private class Branch extends ARM_Instructions.Branch implements Interpreter.Instruction { + + public Branch(int instr) { + super(instr); + } + + public void execute() { + int previousAddress = regs.get(ARM_Registers.PC); + + //jump to the new address + regs.set(ARM_Registers.PC, previousAddress + getOffset()); + + //if we're supposed to link, then write the previous address into the link register + if (link) + regs.set(ARM_Registers.LR, previousAddress + 4); + } + + public int getSuccessor(int pc) { + return pc + getOffset(); + } + } + + private class BranchExchange extends ARM_Instructions.BranchExchange implements Interpreter.Instruction { + + public BranchExchange(int instr) { + super(instr); + } + + public void execute() { + int previousAddress = regs.get(ARM_Registers.PC); + boolean thumb; + int targetAddress; + + switch (target.getType()) { + case PcRelative: + targetAddress = previousAddress + target.getOffset(); + thumb = true; + break; + + case Register: + targetAddress = regs.get(target.getRegister()); + thumb = (targetAddress & 0x1) != 0; + targetAddress = targetAddress & 0xFFFFFFFE; + break; + + default: + throw new RuntimeException("Unexpected Operand type: " + target.getType()); + } + + //jump to the new address + regs.set(ARM_Registers.PC, targetAddress); + regs.setThumbMode(thumb); + + //if we're supposed to link, then write the previous address into the link register + if (link) + regs.set(ARM_Registers.LR, previousAddress + 4); + } + + public int getSuccessor(int pc) { + //if we're jumping relative to the PC, then we can predict the next instruction + if (target.getType() == OperandWrapper.Type.PcRelative) { + return pc + target.getOffset(); + } + else { + //otherwise we can't predict it + return -1; + } + } + } + + private class CountLeadingZeros extends ARM_Instructions.CountLeadingZeros implements Interpreter.Instruction { + + public CountLeadingZeros(int instr) { + super(instr); + } + + public void execute() { + int leadingZeros = Integer.numberOfLeadingZeros(regs.get(Rm)); + regs.set(Rd, leadingZeros); + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class IntMultiply extends ARM_Instructions.IntMultiply implements Interpreter.Instruction { + + protected IntMultiply(int instr) { + super(instr); + } + + public void execute() { + int result = regs.get(Rm) * regs.get(Rs); + + if (accumulate) + result += regs.get(Rn); + + regs.set(Rd, result); + + if (updateConditionCodes) { + regs.setFlags(result < 0, result == 0); + } + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class MoveFromStatusRegister extends ARM_Instructions.MoveFromStatusRegister implements Interpreter.Instruction { + + public MoveFromStatusRegister(int instr) { + super(instr); + } + + public void execute() { + int statusRegisterValue; + + if (transferSavedPSR) { + statusRegisterValue = regs.getSPSR(); + } + else { + statusRegisterValue = regs.getCPSR(); + } + + regs.set(Rd, statusRegisterValue); + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt implements Interpreter.Instruction { + + public SoftwareInterrupt(int instr) { + super(instr); + } + + public void execute() { + ps.doSysCall(); + } + + public int getSuccessor(int pc) { + return -1; + } + + } + + private class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer implements Interpreter.Instruction { + + public SingleDataTransfer(int instr) { + super(instr); + } + + public void execute() { + + } + + public int getSuccessor(int pc) { + //if we're loading to the PC, then the next instruction is undefined + if (Rd == ARM_Registers.PC) + return -1; + + return pc+4; + } + + } + + private class UndefinedInstruction implements Interpreter.Instruction { + + private final int instruction; + + public UndefinedInstruction(int instr) { + this.instruction = instr; + } + + public void execute() { + throw new RuntimeException("Undefined instruction: " + instruction); + } + + public int getSuccessor(int pc) { + return -1; + } + } + + class InterpreterFactory implements + ARM_InstructionFactory<Interpreter.Instruction> { + + public Interpreter.Instruction createDataProcessing(int instr) { + Opcode opcode = Opcode.values()[Utils.getBits(instr, 21, 24)]; + + switch (opcode) { + case ADC: + return new DataProcessing_Adc(instr); + case ADD: + return new DataProcessing_Add(instr); + case AND: + return new DataProcessing_And(instr); + case BIC: + return new DataProcessing_Bic(instr); + case CMN: + return new DataProcessing_Cmn(instr); + case CMP: + return new DataProcessing_Cmp(instr); + case EOR: + return new DataProcessing_Eor(instr); + case MOV: + return new DataProcessing_Mov(instr); + case MVN: + return new DataProcessing_Mvn(instr); + case ORR: + return new DataProcessing_Orr(instr); + case RSB: + return new DataProcessing_Rsb(instr); + case RSC: + return new DataProcessing_Rsc(instr); + case SBC: + return new DataProcessing_Sbc(instr); + case SUB: + return new DataProcessing_Sub(instr); + case TEQ: + return new DataProcessing_Teq(instr); + case TST: + return new DataProcessing_Tst(instr); + + default: + throw new RuntimeException("Unexpected Data Procesing opcode: " + + opcode); + } + } + + public Instruction createBlockDataTransfer(int instr) { + return new BlockDataTransfer(instr); + } + + public Instruction createBranch(int instr) { + return new Branch(instr); + } + + public Instruction createBranchExchange(int instr) { + return new BranchExchange(instr); + } + + public Instruction createCoprocessorDataProcessing(int instr) { + //TODO: Implement coprocessor instructions + throw new RuntimeException("Coprocessor instructions are not yet supported."); + } + + public Instruction createCoprocessorDataTransfer(int instr) { +// TODO: Implement coprocessor instructions + throw new RuntimeException("Coprocessor instructions are not yet supported."); + } + + public Instruction createCoprocessorRegisterTransfer(int instr) { +// TODO: Implement coprocessor instructions + throw new RuntimeException("Coprocessor instructions are not yet supported."); + } + + public Instruction createCountLeadingZeros(int instr) { + return new CountLeadingZeros(instr); + } + + public Instruction createIntMultiply(int instr) { + return new IntMultiply(instr); + } + + public Instruction createLongMultiply(int instr) { + throw new RuntimeException("Long Multiplications are not yet supported."); + } + + public Instruction createMoveFromStatusRegister(int instr) { + return new MoveFromStatusRegister(instr); + } + + public Instruction createMoveToStatusRegister(int instr) { + //TODO: Implement Register -> CPSR transfers + throw new RuntimeException("Modifying the status register using MSR is not yet supported."); + } + + public Instruction createSingleDataTransfer(int instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createSoftwareInterrupt(int instr) { + return new SoftwareInterrupt(instr); + } + + public Instruction createSwap(int instr) { + return new Swap(instr); + } + + public Instruction createUndefinedInstruction(int instr) { + return new UndefinedInstruction(instr); + } + } + +} Added: src/org/binarytranslator/arch/arm/decoder/Utils.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/Utils.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-04-17 18:11:39 UTC (rev 60) @@ -0,0 +1,84 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.DBT; + +class Utils { + + /** + * Checks if a bit is set within a word. + * @param word + * The word that is being examined. + * @param bit + * The number of the bit that is to be checked, starting from zero. + * @return + * True, if the given bit is set within the word, false otherwise. + */ + static final boolean getBit(int word, int bit) { + if (DBT.VerifyAssertions) + DBT._assert(bit >= 0 && bit <= 31); + return (word & (1 << bit)) != 0; + } + + /** + * Extracts a subsequence of bits from a word. + * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. + * @param word + * The word that is to be examined. + * @param from + * The first bit (starting from 0) that is to be extracted. + * @param to + * The last bit (starting from 0) that is to be extracted from the word. + * @return + * A zero-based version of the bit sequence. + */ + static final int getBits(int word, int from, int to) { + if (DBT.VerifyAssertions) + DBT._assert(from < to && from >= 0 && to <= 31); + return (word & ((1 << (to + 1)) - 1)) >> from; + } + + /** + * Sign extends a given value. + * @param value + * The value to sign extends. + * @param bitsUsed + * The number bits used within this values. + * @return + * A sign extended value. + */ + static int signExtend(int value, int bitsUsed) { + return (value << (32 - bitsUsed)) >> (32 - bitsUsed); + } + + /** + * Returns true, if the addition of both operands as unsigned integers will cause an overflow. + * This basically checks <code> operand1 + operand2 > Integer.MAX_VALUE</code>. + */ + static boolean unsignedAddOverflow(int operand1, int operand2) { + return operand1 > Integer.MAX_VALUE - operand2; + } + + /** + * Returns true, if the subtraction of both operand1 - operand2 (both unsigned) will be a negative number. + * That only happens when <code>operand1 < operand2</code> + */ + static boolean unsignedSubOverflow(int operand1, int operand2) { + return operand1 < operand2; + } + + /** + * Returns true, if the addition of both operands as unsigned integers will cause an overflow. + * The algorithm for this code was taken from http://msdn2.microsoft.com/en-us/library/ms972705.aspx. + */ + static boolean signedAddOverflow(int operand1, int operand2) { + //overflow can only occur when both signs differ + if ((operand1 ^ operand2) >= 0) { + return false; + } + + if (operand1 < 0) + return operand1 < Integer.MIN_VALUE - operand2; + else + return Integer.MAX_VALUE - operand1 < operand2; + } +} Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-17 18:11:39 UTC (rev 60) @@ -75,7 +75,7 @@ public static ProcessSpace createProcessSpaceFromBinary(Loader loader) throws IOException { if (loader.isARM_ABI() || loader.isSysV_ABI()) { - report("Creating ARM Linux ABI [rocess space"); + report("Creating ARM Linux ABI Process space"); return new ARM_LinuxProcessSpace(); } else { report("Creating ARM image process space."); @@ -96,21 +96,21 @@ */ @Uninterruptible public int getCurrentInstructionAddress() { - return registers.read(ARM_Registers.PC); + return registers.get(ARM_Registers.PC); } /** * Sets the current instruction's address */ public void setCurrentInstructionAddress(int pc) { - registers.write(ARM_Registers.PC, pc); + registers.set(ARM_Registers.PC, pc); } /** * Return as an integer the current instruction's address */ public int getCurrentStackAddress() { - return registers.read(14); + return registers.get(ARM_Registers.SP); } /** Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-17 18:11:39 UTC (rev 60) @@ -4,8 +4,8 @@ public final class ARM_Registers { - public final static int SP = 14; - + public final static int SP = 13; + public final static int LR = 14; public final static int PC = 15; /** @@ -77,23 +77,38 @@ public final static byte OPERATING_MODE_ABT = 0x17; public final static byte OPERATING_MODE_UND = 0x1A; + + /** Is the processor currently in thumb mode? */ + private boolean thumbMode = false; public ARM_Registers() { } - public int read(int reg) { + /** Returns the value of the specified register. */ + public int get(int reg) { if (VM.VerifyAssertions) VM._assert(reg < 16); return regs[reg]; } - public void write(int reg, int value) { + /** Sets the value of the specified register (<code>reg</code>) to <code>value</code>. */ + public void set(int reg, int value) { if (VM.VerifyAssertions) VM._assert(reg < 16); regs[reg] = value; } + + /** + * Restores the saved program status register of the current operating mode to the CPSR, + * thereby effectively switching to a different operating mode. + */ + public void restoreSPSR2CPSR() { + if (VM.VerifyAssertions) VM._assert(operatingMode != OPERATING_MODE_USR && operatingMode != OPERATING_MODE_SVC); + + setFlagsFromCPSR(getSPSR()); + } /** * Returns the content of ARM's Current Program Status Register. @@ -104,8 +119,13 @@ return (flagNegative ? 1 << 31 : 0) | (flagZero ? 1 << 30 : 0) | (flagCarry ? 1 << 29 : 0) | (flagOverflow ? 1 << 28 : 0) | (flagIRQsDisabled ? 1 << 7 : 0) | (flagFIQsDisabled ? 1 << 6 : 0) - | operatingMode; + | (thumbMode ? 1 << 5 : 0) | operatingMode; } + + /** Returns the content of the current mode's Saved Program Status register.*/ + public int getSPSR() { + throw new RuntimeException("Accessing the SPSR is not yet implemented"); + } /** * Restores the processor state to the state saved within the given CPSR. @@ -114,7 +134,69 @@ * ARM CPSR register content */ public void setFlagsFromCPSR(int cpsr) { - throw new RuntimeException("Not yet implemented."); + throw new RuntimeException("Interpreting a previous SPSR is not yet implemented."); } + + /** + * This function switches the processor to either ARM or Thumb mode. + * + * @param enable + * Set to true to enable execution of thumb code, false otherwise. + */ + public void setThumbMode(boolean enable) { + thumbMode = enable; + } + + /** + * Sets all flags at once. This operation is very common in the ARm architecture and therefore + * implemented explicitely. + * @param negative + * The value of the negative flag. + * @param zero + * The value of the zero flag. + * @param carry + * The value of the carry flag. + * @param overflow + * The value of the overflow flag. + */ + public void setFlags(boolean negative, boolean zero, boolean carry, boolean overflow) { + flagNegative = negative; + flagZero = zero; + flagCarry = carry; + flagOverflow = overflow; + } + + /** + * Sets all flags, except for the overflow flag, at once. This operation is very common in the ARm architecture and therefore + * implemented explicitely. + * @param negative + * The value of the negative flag. + * @param zero + * The value of the zero flag. + * @param carry + * The value of the carry flag. + */ + public void setFlags(boolean negative, boolean zero, boolean carry) { + flagNegative = negative; + flagZero = zero; + flagCarry = carry; + } + + /** + * Sets the negative and zero flags at once. + * @param negative + * The value of the negative flag. + * @param zero + * The value of the zero flag. + */ + public void setFlags(boolean negative, boolean zero) { + flagNegative = negative; + flagZero = zero; + } + + /** Returns true if the carry flag is set, false otherwise. */ + public boolean isCarrySet() { + return flagCarry; + } } Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-17 18:11:39 UTC (rev 60) @@ -29,7 +29,7 @@ @Override public void initialise(Loader loader, int pc, int brk) { - registers.write(ARM_Registers.PC, pc); + registers.set(ARM_Registers.PC, pc); } } Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-17 18:11:39 UTC (rev 60) @@ -47,7 +47,7 @@ @Override public void initialise(Loader loader, int pc, int brk) { - registers.write(ARM_Registers.PC, pc); + registers.set(ARM_Registers.PC, pc); this.brk = brk; // initialize the stack Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java 2007-04-17 18:11:39 UTC (rev 60) @@ -15,7 +15,7 @@ } public int nextInt() { - return ps.registers.read(currentArgument++); + return ps.registers.get(currentArgument++); } public long nextLong() { Modified: src/org/binarytranslator/generic/decoder/DisassembledInstruction.java =================================================================== --- src/org/binarytranslator/generic/decoder/DisassembledInstruction.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/generic/decoder/DisassembledInstruction.java 2007-04-17 18:11:39 UTC (rev 60) @@ -1,7 +1,8 @@ package org.binarytranslator.generic.decoder; /** - * Represents a disassembled instruction. + * 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 */ Added: src/org/binarytranslator/generic/decoder/Interpreter.java =================================================================== --- src/org/binarytranslator/generic/decoder/Interpreter.java (rev 0) +++ src/org/binarytranslator/generic/decoder/Interpreter.java 2007-04-17 18:11:39 UTC (rev 60) @@ -0,0 +1,12 @@ +package org.binarytranslator.generic.decoder; + +public interface Interpreter { + + public interface Instruction { + + void execute(); + int getSuccessor(int pc); + } + + Instruction decode(int pc); +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-18 22:26:28
|
Revision: 71 http://svn.sourceforge.net/pearcolator/?rev=71&view=rev Author: captain5050 Date: 2007-04-18 15:26:30 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Fix at least one silly mistake in Linux stack initialization and enable stack debug. argv[0] is always the executable file name. Modified Paths: -------------- src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java src/org/binarytranslator/vmInterface/DynamicCodeRunner.java Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java 2007-04-18 18:44:18 UTC (rev 70) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java 2007-04-18 22:26:30 UTC (rev 71) @@ -299,8 +299,12 @@ // grab the vector of command line options that are to be delivered to the // linux program - String[] argv = DBT_Options.executableArguments; - + String[] argv = new String[DBT_Options.executableArguments.length+1]; + argv[0] = DBT_Options.executableFile; + for (int i=0; i < DBT_Options.executableArguments.length; i++) { + argv[i+1] = DBT_Options.executableArguments[i]; + } + // --- // First create the information block by concatenating all strings // together, then compute pointers to values in the information Modified: src/org/binarytranslator/vmInterface/DynamicCodeRunner.java =================================================================== --- src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-04-18 18:44:18 UTC (rev 70) +++ src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-04-18 22:26:30 UTC (rev 71) @@ -44,7 +44,7 @@ VM.sysWriteHex(ps.getCurrentInstructionAddress()); VM.sysWriteln(); VM.sysWriteln(ps.toString()); - // ps.dumpStack(20); + ps.dumpStack(20); VM.sysWrite("About to bridge to "); VM.sysWriteHex(VM_Magic.objectAsAddress(code).toInt()); VM.sysWriteln(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-19 15:35:54
|
Revision: 72 http://svn.sourceforge.net/pearcolator/?rev=72&view=rev Author: captain5050 Date: 2007-04-19 08:35:38 -0700 (Thu, 19 Apr 2007) Log Message: ----------- Support to disassemble instructions as they are ran (rather than just at translate time). Fixes for x86 sysinfo (vdso) page support - disabling vdso for now. Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DynamicCodeRunner.java Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -5,6 +5,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Interpreter; import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; +import org.binarytranslator.arch.x86.decoder.X86_InstructionDecoder; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.memory.DebugMemory; import org.binarytranslator.generic.os.loader.Loader; @@ -90,6 +91,14 @@ } /** + * Return a string disassembly of the instuction at the given address + */ + @Uninterruptible + public String disassembleInstruction(int pc) { + return "TODO"; + } + + /** * Return as an integer the current instruction's address */ public int getCurrentStackAddress() { Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -22,6 +22,7 @@ import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.ppc.PPC_Disassembler; import org.vmmagic.pragma.Uninterruptible; /** @@ -176,6 +177,15 @@ } /** + * Return a string disassembly of the instuction at the given address + */ + @Uninterruptible + public String disassembleInstruction(int pc) { + int instr = memory.load32(pc); + return PPC_Disassembler.disasm(instr, pc); + } + + /** * Return as an integer the current instruction's address */ public int getCurrentStackAddress() { Modified: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -16,6 +16,7 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.loader.elf.ELF_Loader; import org.binarytranslator.generic.os.process.ProcessSpace; /** @@ -99,12 +100,13 @@ 0x64, LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, - 0xBADADD8E, // todo + ((ELF_Loader)loader).getProgramHeaderAddress(), + LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, + ((ELF_Loader)loader).elfHeader.getNumberOfProgramSegmentHeaders(), LinuxStackInitializer.AuxiliaryVectorType.AT_PHENT, - 0xBAD1BAD1, // todo - LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, - 0xBAD2BAD2, // todo - LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, + ((ELF_Loader)loader).elfHeader.getProgramSegmentHeaderSize(), + + //LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, pc, LinuxStackInitializer.AuxiliaryVectorType.AT_UID, DBT_Options.UID, Modified: src/org/binarytranslator/arch/x86/decoder/X862IR.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-19 15:35:38 UTC (rev 72) @@ -54,12 +54,8 @@ * @return the next instruction address or -1 */ protected int translateInstruction(Laziness lazy, int pc) { - if (pc != 0xffffe400) { - return X86_InstructionDecoder.translateInstruction((X862IR) this, - (X86_ProcessSpace) ps, (X86_Laziness) lazy, pc); - } else { - return plantSystemCallGateEntry((X86_Laziness) lazy, pc); - } + return X86_InstructionDecoder.translateInstruction((X862IR) this, + (X86_ProcessSpace) ps, (X86_Laziness) lazy, pc); } /** Modified: src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java 2007-04-19 15:35:38 UTC (rev 72) @@ -220,7 +220,11 @@ this.base = base; this.scale = scale; this.index = index; - this.displacement = displacement; + if (segment == X86_Registers.GS){ + this.displacement = displacement + 0xffffe000; + } else { + this.displacement = displacement; + } this.addressSize = addressSize; this.operandSize = operandSize; } Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-19 15:35:38 UTC (rev 72) @@ -21,7 +21,7 @@ /** * Decoder for X86 instructions */ -class X86_InstructionDecoder extends InstructionDecoder { +public class X86_InstructionDecoder extends InstructionDecoder { /* * Process defaults @@ -714,7 +714,7 @@ /** * Get the decoder */ - static X86_InstructionDecoder getDecoder(ProcessSpace ps, int pc) { + public static X86_InstructionDecoder getDecoder(ProcessSpace ps, int pc) { int opcode = ps.memory.loadInstruction8(pc); return primaryOpcodeLookup(opcode).getDecoder(ps, pc, 1, null, null, null, null, null); Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -20,6 +20,7 @@ import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; +import org.binarytranslator.arch.x86.decoder.X86_InstructionDecoder; import org.binarytranslator.generic.os.loader.Loader; import org.vmmagic.pragma.Uninterruptible; @@ -183,7 +184,16 @@ public void setCurrentInstructionAddress(int pc) { registers.eip = pc; } + /** + * Return a string disassembly of the instuction at the given address + */ + @Uninterruptible + public String disassembleInstruction(int pc) { + return X86_InstructionDecoder.getDecoder(this,pc).disassemble(this, pc); + } + + /** * Return as an integer the current instruction's address */ public int getCurrentStackAddress() { Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -16,7 +16,9 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.loader.elf.ELF_Loader; import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.generic.memory.MemoryMapException; /** * Linux specific parts of the process @@ -61,19 +63,27 @@ registers.eip = pc; this.brk = brk; registers.writeGP32(X86_Registers.ESP, initialiseStack(loader, pc)); + try { + memory.map(0xffffe000, 8192, true, true, true); + } catch (MemoryMapException e) { + throw new Error ("Error creating VDSO page"); + } + memory.store8(0xffffe400, 0xCD); // INT + memory.store8(0xffffe400, 0x80); // 80h + memory.store8(0xffffe400, 0xC3); // RET } /** * Initialise the stack */ private int initialiseStack(Loader loader, int pc) { - int[] auxVector = {LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, 0xffffe400, - LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO_EHDR, 0xffffe000, + int[] auxVector = {//LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, 0xffffe400, + //LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO_EHDR, 0xffffe000, LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x78bfbff, LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 0x1000, LinuxStackInitializer.AuxiliaryVectorType.AT_CLKTCK, 0x64, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, 0xBADADD8E, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, 0xBAD2BAD2, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, ((ELF_Loader)loader).getProgramHeaderAddress(), + LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, ((ELF_Loader)loader).elfHeader.getNumberOfProgramSegmentHeaders(), LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, pc, Modified: src/org/binarytranslator/generic/decoder/DecoderUtils.java =================================================================== --- src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-19 15:35:38 UTC (rev 72) @@ -1046,13 +1046,17 @@ * @return true => try to stop the trace */ protected boolean suitableToStop() { - switch (gc.options.getOptLevel()) { - case 0: - return numberOfInstructions > DBT_Options.instrOpt0; - case 1: - return numberOfInstructions > DBT_Options.instrOpt1; - default: - return numberOfInstructions > DBT_Options.instrOpt2; + if (DBT_Options.singleInstrTranslation && (numberOfInstructions >= 1)) { + return true; + } else { + switch (gc.options.getOptLevel()) { + case 0: + return numberOfInstructions > DBT_Options.instrOpt0; + case 1: + return numberOfInstructions > DBT_Options.instrOpt1; + default: + return numberOfInstructions > DBT_Options.instrOpt2; + } } } Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-19 15:35:38 UTC (rev 72) @@ -29,7 +29,7 @@ /** * Header of ELF file */ - private ELF_Header elfHeader; + public ELF_Header elfHeader; /** * Program segment headers @@ -259,6 +259,13 @@ return elfHeader.isARM_ABI(); } + /** + * Where did the program header get loaded in memory? + */ + public int getProgramHeaderAddress() { + return elfHeader.e_phoff - segmentHeaders[0].p_offset + segmentHeaders[0].p_vaddr; + } + /* * Local classes holding structures from the ELF file */ @@ -267,7 +274,7 @@ * Class to read and hold ELF header information */ @SuppressWarnings("unused") - class ELF_Header { + public class ELF_Header { /** * Class to read and hold ELF header indentity information */ @@ -744,7 +751,7 @@ int getEntryPoint() { return e_entry; } - + /** * Program header table file offset */ @@ -760,56 +767,56 @@ /** * Section header table file offset */ - private int e_shoff; + private final int e_shoff; /** * Processor-specific flags */ - private int e_flags; + private final int e_flags; /** * ELF header size in bytes */ - private short e_ehsize; + private final short e_ehsize; /** * Program header table entry size */ - private short e_phentsize; + private final short e_phentsize; /** * What's the size of a program segment header? */ - int getProgramSegmentHeaderSize() { + public int getProgramSegmentHeaderSize() { return e_phentsize; } /** * Program header table entry count */ - private short e_phnum; + private final short e_phnum; /** * How many program segments are in this ELF binary? */ - int getNumberOfProgramSegmentHeaders() { + public int getNumberOfProgramSegmentHeaders() { return e_phnum; } /** * Section header table entry size */ - private short e_shentsize; + private final short e_shentsize; /** * Section header table entry count */ - private short e_shnum; + private final short e_shnum; /** * Section header table index */ - private short e_shstrndx; + private final short e_shstrndx; /** * Construct/read ELF header Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -138,6 +138,12 @@ public abstract void setCurrentInstructionAddress(int pc); /** + * Return a string disassembly of the instuction at the given address + */ + @Uninterruptible + public abstract String disassembleInstruction(int pc); + + /** * Return as an integer the current instruction's address */ public abstract int getCurrentStackAddress(); Modified: src/org/binarytranslator/vmInterface/DynamicCodeRunner.java =================================================================== --- src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-04-19 15:35:38 UTC (rev 72) @@ -40,11 +40,12 @@ throws BadInstructionException { // Useful when debugging in GDB: if (DBT_Options.debugRuntime) { + VM.sysWriteln(ps.toString()); + ps.dumpStack(20); VM.sysWrite("Running PC="); VM.sysWriteHex(ps.getCurrentInstructionAddress()); - VM.sysWriteln(); - VM.sysWriteln(ps.toString()); - ps.dumpStack(20); + VM.sysWrite(" "); + VM.sysWriteln(ps.disassembleInstruction(ps.getCurrentInstructionAddress())); VM.sysWrite("About to bridge to "); VM.sysWriteHex(VM_Magic.objectAsAddress(code).toInt()); VM.sysWriteln(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-20 18:42:26
|
Revision: 75 http://svn.sourceforge.net/pearcolator/?rev=75&view=rev Author: michael_baer Date: 2007-04-20 11:42:26 -0700 (Fri, 20 Apr 2007) Log Message: ----------- Refactored ELF_Loader to check a few conditions and at least use enums partially. Far from perfect, but better... Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/generic/os/loader/Loader.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/generic/os/loader/image/ImageLoader.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-19 23:18:32 UTC (rev 74) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-20 18:42:26 UTC (rev 75) @@ -1088,6 +1088,7 @@ else { //TODO: calculate the post-indexed address //and set it to Rn + throw new RuntimeException("Not yet implemented."); } } } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-19 23:18:32 UTC (rev 74) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-20 18:42:26 UTC (rev 75) @@ -61,7 +61,8 @@ */ public static ProcessSpace createProcessSpaceFromBinary(Loader loader) throws IOException { - if (loader.isARM_ABI() || loader.isSysV_ABI()) { + Loader.ABI abi = loader.getABI(); + if (abi == Loader.ABI.ARM || abi == Loader.ABI.SystemV) { report("Creating ARM Linux ABI Process space"); return new ARM_LinuxProcessSpace(); } else { Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-19 23:18:32 UTC (rev 74) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-20 18:42:26 UTC (rev 75) @@ -152,12 +152,17 @@ */ public static ProcessSpace createProcessSpaceFromBinary(Loader loader) throws IOException { - if (loader.isLinuxABI() || loader.isSysV_ABI()) { - report("Linux/SysV ABI"); - return new PPC_LinuxProcessSpace(loader); - } else { - throw new IOException("Binary of " + loader.getABIString() - + " ABI is unsupported for the PowerPC architecture"); + + Loader.ABI abi = loader.getABI(); + + switch (abi) { + case Linux: + case SystemV: + report("Linux/SysV ABI"); + return new PPC_LinuxProcessSpace(loader); + + default: + throw new IOException("Binary of " + abi + " ABI is unsupported for the PowerPC architecture"); } } Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-19 23:18:32 UTC (rev 74) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-20 18:42:26 UTC (rev 75) @@ -18,6 +18,7 @@ import org.binarytranslator.generic.memory.ByteAddressedMemory; import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.arch.ppc.os.process.linux.PPC_LinuxProcessSpace; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; import org.binarytranslator.arch.x86.decoder.X86_InstructionDecoder; @@ -155,13 +156,17 @@ * @return the appropriate process space */ public static ProcessSpace createProcessSpaceFromBinary (Loader loader) throws IOException { - if (loader.isLinuxABI() || loader.isSysV_ABI()) { - report("Linux/SysV ABI"); - return new X86_LinuxProcessSpace(loader); + Loader.ABI abi = loader.getABI(); + + switch (abi) { + case Linux: + case SystemV: + report("Linux/SysV ABI"); + return new PPC_LinuxProcessSpace(loader); + + default: + throw new IOException("Binary of " + abi + " ABI is unsupported for the PowerPC architecture"); } - else { - throw new IOException("Binary of " + loader.getABIString() + " ABI is unsupported for the X86 architecture"); - } } /** Modified: src/org/binarytranslator/generic/os/loader/Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/Loader.java 2007-04-19 23:18:32 UTC (rev 74) +++ src/org/binarytranslator/generic/os/loader/Loader.java 2007-04-20 18:42:26 UTC (rev 75) @@ -48,51 +48,29 @@ */ abstract public ProcessSpace readBinary(String filename) throws IOException; - /** - * Return the application binary interface (ABI) supported by this file - */ - abstract public String getABIString(); + /** A list of supported instruction set architectures. */ + public enum ISA { + Undefined, + X86, + PPC, + ARM + } + + /** A list of supported Application binary interface. */ + public enum ABI { + Undefined, + SystemV, + Linux, + ARM + } + + /** Returns the instruction set architecture required by this executable. */ + public abstract ISA getISA(); + + /** Shall return the Application Binary Interface that is required to load this executable. */ + public abstract ABI getABI(); /** - * Return the architecture (ISA) supported by this file - */ - abstract public String getArchitectureString(); - - /** - * Is the binary for the X86 ISA? - */ - abstract public boolean isX86_ISA(); - - /** - * Is the binary for the Power PC ISA? - */ - abstract public boolean isPPC_ISA(); - - /** - * Is the binary for the ARM ISA? - */ - abstract public boolean isARM_ISA(); - - /** - * Does this file support the SysV ABI? - */ - abstract public boolean isSysV_ABI(); - - /** - * Does this file support the Linux ABI? - */ - abstract public boolean isLinuxABI(); - - /** - * Does this file support the ARM ABI? - */ - abstract public boolean isARM_ABI(); - - /* - * Static methods - */ - - /** * Open and read the start of the file to determine the appropriate file * loader to use * Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-19 23:18:32 UTC (rev 74) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-20 18:42:26 UTC (rev 75) @@ -8,23 +8,27 @@ */ package org.binarytranslator.generic.os.loader.elf; -import org.binarytranslator.generic.os.loader.Loader; -import org.binarytranslator.generic.os.process.ProcessSpace; +import java.io.IOException; +import java.io.RandomAccessFile; + +import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.memory.MemoryMapException; -import org.binarytranslator.DBT_Options; +import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.process.ProcessSpace; -import java.io.*; - public class ELF_Loader extends Loader { - /* - * Instance variables - */ /** * Wrapper class used for reading the ELF file with the required endianness */ private ELF_BinaryReader reader; + + /** + * Field holding identity information + */ + private ELF_Identity identity; /** * Header of ELF file @@ -36,10 +40,6 @@ */ private ELF_ProgramSegmentHeader segmentHeaders[]; - /* - * Utility functions - */ - /** * Debug information * @param s string of debug information @@ -50,79 +50,97 @@ System.out.println(s); } } - - /* - * Utility classes - */ - /** - * Reader for byte and multibyte values respecting endianness + * Reader for byte and multibyte values respecting endianness. */ - private static class ELF_BinaryReader { + private abstract static class ELF_BinaryReader { + + /** File to read from */ + protected RandomAccessFile rFile; + /** - * Do we need to byte swap multi-byte values? + * Returns a new ELF_BinaryReader for the specified byte order and file. + * + * @param byteOrder + * The byte order that the file posesses. + * @param file + * The file that is to be read. + * @return + * An ELF_BinaryReader, that hides the details of the byte order. */ - private final boolean needsBswap; + public static ELF_BinaryReader create(ELF_Identity.ByteOrder byteOrder, RandomAccessFile file) { + + if (byteOrder == ELF_Identity.ByteOrder.BigEndian) + return new NonSwappingReader(file); + else + return new ByteSwappingReader(file); + } - /** - * File to read from - */ - RandomAccessFile rFile; - - /** - * Constructor - * @param rFile file to read from - * @param needsBswap do multibyte values need byte swapping - */ - ELF_BinaryReader(RandomAccessFile rFile, boolean needsBswap) { + /** Hide the constructor, because this class shall only be instantiated by using the factory method {@link #create(org.binarytranslator.generic.os.loader.elf.ELF_Loader.ELF_Header.ByteOrder, RandomAccessFile)}. */ + private ELF_BinaryReader(RandomAccessFile rFile) { this.rFile = rFile; - this.needsBswap = needsBswap; } - - /** - * Byte swap a 32-bit integer - */ - private static int bswap(int x) { - return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) - | (x >>> 24); + + /** Seek to location from beginning of file */ + void seek(long pos) throws IOException { + rFile.seek(pos); } + + /** Read an integer from the file. This function is supposed to hide the difference between little and big endian reads. */ + public abstract int readInt() throws IOException; + + /** Read a short from the file. This function is supposed to hide the difference between little and big endian reads. */ + public abstract short readShort() throws IOException; + + /** Reader that performs byte swaps for each int/short read. */ + private static class ByteSwappingReader extends ELF_BinaryReader { + + ByteSwappingReader(RandomAccessFile rFile) { + super(rFile); + } - /** - * Byte swap a 16-bit integer - */ - private static short bswap(short x) { - short result = (short) (((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); - return result; - } + /** Byte swap a 32-bit integer */ + private static int bswap(int x) { + return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) + | (x >>> 24); + } - /** - * Read a 32bit int value - */ - int readInt() throws IOException { - int result = rFile.readInt(); - return needsBswap ? bswap(result) : result; - } + /** Byte swap a 16-bit integer */ + private static short bswap(short x) { + short result = (short) (((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); + return result; + } - /** - * Read a 16bit short value - */ - short readShort() throws IOException { - short result = rFile.readShort(); - return needsBswap ? bswap(result) : result; + @Override + public int readInt() throws IOException { + return bswap(rFile.readInt()); + } + + @Override + public short readShort() throws IOException { + return bswap(rFile.readShort()); + } } + + /** Reader that does not perform any byte swaps.*/ + private static class NonSwappingReader extends ELF_BinaryReader { - /** - * Seek to location from beginning of file - */ - void seek(long pos) throws IOException { - rFile.seek(pos); + NonSwappingReader(RandomAccessFile rFile) { + super(rFile); + } + + @Override + public int readInt() throws IOException { + return rFile.readInt(); + } + + @Override + public short readShort() throws IOException { + return rFile.readShort(); + } } } - /* - * Methods - */ - /** * Main entry point that loads the binary * @param filename the program file name @@ -131,8 +149,14 @@ public ProcessSpace readBinary(String filename) throws IOException { report("Opening File: " + filename); RandomAccessFile rFile = new RandomAccessFile(filename, "r"); + + // Identification is in bytes and therefore is endian agnostic + identity = new ELF_Identity(rFile); + + // Set up reader to handle endianness for the rest of the file + reader = ELF_BinaryReader.create(identity.byteOrder, rFile); - elfHeader = new ELF_Header(rFile); // NB also sets up reader + elfHeader = new ELF_Header(reader); // NB also sets up reader report("ELF header read successfully"); ProcessSpace ps = ProcessSpace.createProcessSpaceFromBinary(this); @@ -202,391 +226,179 @@ return segmentHeaders; } - /** - * Return the application binary interface (ABI) supported by this file - */ - public String getABIString() { - return elfHeader.getABIString(); + @Override + public ABI getABI() { + return identity.getABI(); } - - /** - * Return the architecture (ISA) supported by this file - */ - public String getArchitectureString() { - return elfHeader.getArchitectureString(); + + @Override + public ISA getISA() { + return elfHeader.getISA(); } /** - * Is the ELF's machine field Intel 80386 - */ - public boolean isX86_ISA() { - return elfHeader.isX86_ISA(); - } - - /** - * Is the ELF's machine field PowerPC - */ - public boolean isPPC_ISA() { - return elfHeader.isPPC_ISA(); - } - - /** - * Is this binary for the ARM architecture? - */ - public boolean isARM_ISA() { - return elfHeader.isARM_ISA(); - } - - /** - * Does this file support the SysV ABI? - */ - public boolean isSysV_ABI() { - return elfHeader.isSysV_ABI(); - } - - /** - * Does this file support the Linux ABI? - */ - public boolean isLinuxABI() { - return elfHeader.isLinuxABI(); - } - - /** - * Does this file support the ARM ABI? - * @return - */ - public boolean isARM_ABI() { - return elfHeader.isARM_ABI(); - } - - /** * Where did the program header get loaded in memory? */ public int getProgramHeaderAddress() { return elfHeader.e_phoff - segmentHeaders[0].p_offset + segmentHeaders[0].p_vaddr; } - /* - * Local classes holding structures from the ELF file - */ - + /** An interface for enums where each value is identified by an identifier.*/ + private static interface IdentifiedEnum { + int getIdentifier(); + } + + /** + * Creates a corresponding enum value from an integer identifier for enums implementing the {@link IdentifiedEnum} interface. + * In case no corresponding enum value is available, the function returns null. */ + private static <T extends Enum<T> & IdentifiedEnum> T getEnumFromIdentifier(Class<T> enumClass, int identifier) { + for (T value : enumClass.getEnumConstants()) + if (value.getIdentifier() == identifier) + return value; + + return null; + } + /** - * Class to read and hold ELF header information + * Class to read and hold ELF header indentity information */ - @SuppressWarnings("unused") - public class ELF_Header { - /** - * Class to read and hold ELF header indentity information - */ - @SuppressWarnings("unused") - private class ELF_Identity { - /** - * Size of ELF identity structure - */ - private static final int EI_NIDENT = 16; - /** - * Backing store for identity structure: - * {0x7f,'E','L','F',class,data,version,padding..} - */ - private byte[] e_ident = new byte[EI_NIDENT]; - - /** - * ELF Magic numbers locations in identity - */ - private static final int EI_MAG0 = 0, EI_MAG1 = 1, EI_MAG2 = 2, - EI_MAG3 = 3; - - /** - * ELF magic values indicating an ELF file - */ - private static final byte ELFMAG0 = 0x7f, ELFMAG1 = 'E', ELFMAG2 = 'L', - ELFMAG3 = 'F'; - - /** - * Location of class data in identity structure - */ - private static final int EI_CLASS = 4; - - /** - * ELF file is invalid - */ - private static final byte ELFCLASSNONE = 0; - - /** - * ELF file contains 32bit data - */ - private static final byte ELFCLASS32 = 1; - - /** - * ELF file contains 64bit data - */ - private static final byte ELFCLASS64 = 2; - - /** - * Location of data information in identity structure - */ - private static final int EI_DATA = 5; - - /** - * Invalid data encoding - */ - private static final byte ELFDATANONE = 0; - - /** - * LSB or little-endian encoding N.B. not the native Java format - */ - private static final byte ELFDATA2LSB = 1; - - /** - * MSB or big-endian encoding N.B. the native Java format - */ - private static final byte ELFDATA2MSB = 2; - - /** - * Is this ELF MSB encoded? - */ - boolean isMSB() throws IOException { - switch (e_ident[EI_DATA]) { - case ELFDATA2LSB: - return false; - case ELFDATA2MSB: - return true; - default: - throw new IOException("Unrecognized data encoding"); - } + private static class ELF_Identity { + + /** Represents acceptable ELF address sizes. */ + enum AddressSize implements IdentifiedEnum { + Size32(1), + Size64(2); + + private int identifier; + + private AddressSize(int identifier) { + this.identifier = identifier; } - /** - * Location of version data - should be EV_CURRENT as defined by the ELF - * header - */ - private static final int EI_VERSION = 6; - - /** - * Location of OS ABI data - */ - private static final int EI_OSABI = 7; - - /** - * UNIX System V ABI. - */ - private static final byte ELFOSABI_SYSV = 0; - - /** - * HP-UX ABI - */ - private static final byte ELFOSABI_HPUX = 1; - - /** - * NetBSD ABI - */ - private static final byte ELFOSABI_NETBSD = 2; - - /** - * Linux ABI - */ - private static final byte ELFOSABI_LINUX = 3; - - /** - * Solaris ABI - */ - private static final byte ELFOSABI_SOLARIS = 6; - - /** - * AIX ABI - */ - private static final byte ELFOSABI_AIX = 7; - - /** - * IRIX ABI - */ - private static final byte ELFOSABI_IRIX = 8; - - /** - * FreeBSD ABI - */ - private static final byte ELFOSABI_FREEBSD = 9; - - /** - * TRU64 UNIX ABI - */ - private static final byte ELFOSABI_TRU64 = 10; - - /** - * Novell Modesto - */ - private static final byte ELFOSABI_MODESTO = 11; - - /** - * Open BSD - */ - private static final byte ELFOSABI_OPENBSD = 12; - - /** - * Open VMS - */ - private static final byte ELFOSABI_OPENVMS = 13; - - /** - * Hewlett-Packard Non-Stop Kernel - */ - private static final byte ELFOSABI_NSK = 14; - - /** - * ARM ABI, probably using the ARM AAPCS. - */ - private static final byte ELFOSABI_ARM = 97; - - /** - * Return the application binary interface (ABI) supported by this file - */ - String getABIString() { - switch (e_ident[EI_OSABI]) { - case ELFOSABI_SYSV: - return "SysV"; - case ELFOSABI_HPUX: - return "HP-UX"; - case ELFOSABI_NETBSD: - return "NetBSD"; - case ELFOSABI_LINUX: - return "Linux"; - case ELFOSABI_SOLARIS: - return "Solaris"; - case ELFOSABI_AIX: - return "AIX"; - case ELFOSABI_IRIX: - return "IRIX"; - case ELFOSABI_FREEBSD: - return "FreeBSD"; - case ELFOSABI_TRU64: - return "TRU64"; - case ELFOSABI_MODESTO: - return "Novell Modesto"; - case ELFOSABI_OPENBSD: - return "OpenBSD"; - case ELFOSABI_OPENVMS: - return "OpenVMS"; - case ELFOSABI_NSK: - return "Hewlett-Packard Non-Stop Kernel"; - case ELFOSABI_ARM: - return "ARM ABI"; - default: - return "Unknown ELF ABI: " + e_ident[EI_OSABI]; - } + public int getIdentifier() { + return identifier; } - - /** - * Does this file support the SysV ABI? - */ - boolean isSysV_ABI() { - return e_ident[EI_OSABI] == ELFOSABI_SYSV; + } + + /** Represents accepted ELF byte orders. */ + enum ByteOrder implements IdentifiedEnum { + LittleEndian(1), + BigEndian(2); + + private int identifier; + + private ByteOrder(int identifier) { + this.identifier = identifier; } - /** - * Does this file support the Linux ABI? - */ - boolean isLinuxABI() { - return e_ident[EI_OSABI] == ELFOSABI_LINUX; + public int getIdentifier() { + return identifier; } - - boolean isARM_ABI() { - return e_ident[EI_OSABI] == ELFOSABI_ARM; - } - - /** - * Location of OS ABI version data - */ - private static final int EI_ABIVERSION = 8; - - /** - * Location of padding bytes - */ - private static final int EI_PAD = 9; - - /** - * Construct/read ELF identity - */ - ELF_Identity(RandomAccessFile rFile) throws IOException { - // Identification is in bytes and therefore is endian agnostic - rFile.read(e_ident); - // Check magic is correct - if ((ELFMAG0 != e_ident[EI_MAG0]) || (ELFMAG1 != e_ident[EI_MAG1]) - || (ELFMAG2 != e_ident[EI_MAG2]) || (ELFMAG3 != e_ident[EI_MAG3])) { - throw new IOException("Bad ELF file magic: " + rFile); - } - } } /** - * Field holding identity information + * ELF magic values indicating an ELF file */ - private ELF_Identity identity; + private static final byte ELF_MAGIC_VALUE[] = { 0x7f, 'E', 'L','F' }; + /** Specifies the size of an address within this elf.*/ + private AddressSize addressSize; + + /** The byte order used by this elf.*/ + private ByteOrder byteOrder; + + /** The ABI that is used by this ELF.*/ + private byte abi; + /** - * Return the application binary interface (ABI) supported by this file + * Construct/read ELF identity */ - String getABIString() { - return identity.getABIString(); - } + ELF_Identity(RandomAccessFile rFile) throws IOException { + // Identification is in bytes and therefore is endian agnostic + byte[] magic = new byte[ELF_MAGIC_VALUE.length]; + + if (rFile.read(magic) != magic.length) + throw new IOException("ELF file too short."); + + // Check that the ELF magic is correct + for (int i = 0; i < ELF_MAGIC_VALUE.length; i++) { + if (magic[i] != ELF_MAGIC_VALUE[i]) { + throw new IOException("Bad ELF file magic: " + rFile); + } + } + + //read the address size + addressSize = getEnumFromIdentifier(AddressSize.class, rFile.readByte()); + if (addressSize == null) + throw new IOException("Invalid address sizer specified by ELF file."); - /** - * Does this file support the SysV ABI? - */ - boolean isSysV_ABI() { - return identity.isSysV_ABI(); + //read the byte order + byteOrder = getEnumFromIdentifier(ByteOrder.class, rFile.readByte()); + if (byteOrder == null) + throw new IOException("Invalid byte order specified by ELF file."); + + //Check the ELF's file version + if (rFile.readByte() != 1) { + throw new IOException("Invalid ELF File version."); + } + + //read a byte describing the target ABI + abi = rFile.readByte(); + + //skip the remaining padding bytes so that we're arriving at a 16 byte alignment. + if (rFile.skipBytes(8) != 8) { + throw new IOException("ELF file is too short."); + } } - /** - * Does this file support the Linux ABI? - */ - boolean isLinuxABI() { - return identity.isLinuxABI(); + public ABI getABI() + { + //read the OS ABI + switch (abi) { + case 0: + return ABI.SystemV; + + case 3: + return ABI.Linux; + + case 97: + return ABI.ARM; + + default: + return ABI.Undefined; + } } + } - /** - * Does this file support the ARM ABI? - */ - boolean isARM_ABI() { - return identity.isARM_ABI(); - } + /** + * Class to read and hold ELF header information + */ + @SuppressWarnings("unused") + public static class ELF_Header { - /** - * Object file type - */ - private short e_type; + /** A list of possible object file types. */ + enum ObjectFileType implements IdentifiedEnum { + Relocatable(1), + Executable(2), + SharedObject(3), + Core(4); + + private int identifier; + + private ObjectFileType(int identifier) { + this.identifier = identifier; + } - /** - * No file type - */ - private static final short ET_NONE = 0; + public int getIdentifier() { + return identifier; + } + } + + /** Object file type */ + private ObjectFileType e_type; /** - * Relocatable file - */ - private static final short ET_REL = 1; - - /** - * Executable file - */ - private static final short ET_EXEC = 2; - - /** - * Shared object file - */ - private static final short ET_DYN = 3; - - /** - * Core file - */ - private static final short ET_CORE = 4; - - /** - * Number of defined types - */ - private static final short ET_NUM = 5; - - /** * Start of OS reserved region */ private static final short ET_LOOS = (short) 0xfe00; @@ -611,160 +423,36 @@ */ private short e_machine; - /** - * No machine - */ - private static final short EM_NONE = 0; - - /** - * AT&T WE 32100 - */ + /* Short names for a few known machine types. Not an enum, because this list is not complete. */ private static final short EM_M32 = 1; - - /** - * SPARC - */ private static final short EM_SPARC = 2; - - /** - * Intel 80386 - */ private static final short EM_386 = 3; - - /** - * Motoral 68000 - */ private static final short EM_68K = 4; - - /** - * Motorola 88000 - */ private static final short EM_88K = 5; - - /** - * Intel 80860 - */ private static final short EM_860 = 7; - - /** - * MIPS RS3000 - */ private static final short EM_MIPS = 8; - - /** - * PowerPC - */ private static final short EM_PPC = 20; - - /** - * ARM - */ private static final short EM_ARM = 40; - - /** - * Alpha - */ private static final short EM_ALPHA = 41; - - /** - * Sparc V9 - */ private static final short EM_SPARCV9 = 43; /** - * Is the ELF's machine field Intel 80386 - */ - boolean isX86_ISA() { - return e_machine == EM_386; - } - - /** - * Is the ELF's machine field PowerPC - */ - boolean isPPC_ISA() { - return e_machine == EM_PPC; - } - - /** - * Is the elf binary for an ARM architecture? - */ - boolean isARM_ISA() { - return e_machine == EM_ARM; - } - - /** - * Return the architecture (ISA) supported by this file - */ - public String getArchitectureString() { - switch (e_machine) { - case EM_M32: - return "AT&T WE 32100"; - case EM_SPARC: - return "SPARC"; - case EM_386: - return "Intel 80386"; - case EM_68K: - return "Motorola 68000"; - case EM_88K: - return "Motorola 88000"; - case EM_860: - return "Intel 80860"; - case EM_MIPS: - return "MIPS RS3000"; - case EM_PPC: - return "PowerPC"; - case EM_ARM: - return "ARM"; - case EM_ALPHA: - return "Alpha"; - case EM_SPARCV9: - return "SPARC V9"; - default: - return "Unknown architecture " + e_machine; - } - } - - /** * Object file version */ private int e_version; /** - * Invalid version - */ - private static final int EV_NONE = 0; - - /** - * Current version - */ - private static final int EV_CURRENT = 1; - - /** * Entry point virtual address. The virtual address to which the system * first transfers control, thus starting the process. */ private int e_entry; /** - * Return the entry point of the binary - */ - int getEntryPoint() { - return e_entry; - } - - /** * Program header table file offset */ private int e_phoff; /** - * What is the offset in the file of the program headers - */ - int getProgramSegmentHeaderOffset() { - return e_phoff; - } - - /** * Section header table file offset */ private final int e_shoff; @@ -783,27 +471,13 @@ * Program header table entry size */ private final short e_phentsize; - + /** - * What's the size of a program segment header? - */ - public int getProgramSegmentHeaderSize() { - return e_phentsize; - } - - /** * Program header table entry count */ private final short e_phnum; /** - * How many program segments are in this ELF binary? - */ - public int getNumberOfProgramSegmentHeaders() { - return e_phnum; - } - - /** * Section header table entry size */ private final short e_shentsize; @@ -821,16 +495,22 @@ /** * Construct/read ELF header */ - ELF_Header(RandomAccessFile rFile) { + ELF_Header(ELF_BinaryReader reader) { try { - // Identification is in bytes and therefore is endian agnostic - identity = new ELF_Identity(rFile); - // Set up reader to handle endianness for the rest of the file - reader = new ELF_BinaryReader(rFile, !identity.isMSB()); // Read in rest of header - e_type = reader.readShort(); + e_type = getEnumFromIdentifier(ObjectFileType.class, reader.readShort()); + + if (e_type == null) { + throw new Error("Invalid Object file type."); + } + e_machine = reader.readShort(); e_version = reader.readInt(); + + if (e_version != 1) { + throw new Error("Unexpected ELF File version: " + e_version); + } + e_entry = reader.readInt(); e_phoff = reader.readInt(); e_shoff = reader.readInt(); @@ -845,7 +525,94 @@ throw new Error(e); } } + + /** + * What is the offset in the file of the program headers + */ + int getProgramSegmentHeaderOffset() { + return e_phoff; + } + + /** + * What's the size of a program segment header? + */ + public int getProgramSegmentHeaderSize() { + return e_phentsize; + } + + /** + * How many program segments are in this ELF binary? + */ + public int getNumberOfProgramSegmentHeaders() { + return e_phnum; + } + + /** + * Return the entry point of the binary + */ + int getEntryPoint() { + return e_entry; + } + + /** Maps the ISA specified within the ELF file to an ISA supported by Pearcolator. */ + public ISA getISA() { + switch (e_machine) { + case EM_ARM: + return ISA.ARM; + + case EM_386: + return ISA.X86; + + case EM_PPC: + return ISA.PPC; + + default: + return ISA.Undefined; + } + } } + + /** Identifies a named segment range. */ + private enum SegmentRange { + /** SUN reserved segments */ + SunReserved(0x6ffffffa, 0x6fffffff, "SUN Reserved Segment"), + + /** OS reserved segment types */ + OperatingSystem(0x60000000, 0x6fffffff, ("Operating System Segment")), + + /** processor reserved segment types */ + Processor(0x70000000, 0x7fffffff, "Processor Segment"), + + /** remaining (unknown) segment types */ + Unknown(0x0, 0xffffffff, "Unknown Segment"); + + private int lowAddress; + private int highAddress; + private String description; + + private SegmentRange(int from, int to, String description) { + + if (DBT.VerifyAssertions) DBT._assert(from < to); + + lowAddress = from; + highAddress = to; + this.description = description; + } + + public static SegmentRange fromInteger(int address) { + for (SegmentRange range : values()) { + if (range.lowAddress >= address && range.highAddress <= address) + return range; + } + + return null; + } + + @Override + public String toString() { + return description; + } + } /** * Header representing a segment in the process (e.g. stack, heap, code aka @@ -900,15 +667,10 @@ */ private static final int PT_TLS = 7; - /** - * Number of defined types - */ - private static final int PT_NUM = 8; /** * Start of OS reserved segment types */ - private static final int PT_LOOS = 0x60000000; /** * SUN unwind table segment @@ -933,7 +695,6 @@ /** * Start of SUN reserved segments */ - private static final int PT_LOSUNW = 0x6ffffffa; /** * The array element has the same attributes as a PT_LOAD element and is @@ -960,24 +721,13 @@ /** * End of SUN reserved segments */ - private static final int PT_HISUNW = 0x6fffffff; /** * End of OS reserved segment types */ - private static final int PT_HIOS = 0x6fffffff; - /** - * Start of processor reserved segment types - */ - private static final int PT_LOPROC = 0x70000000; /** - * End of processor reserved segment types - */ - private static final int PT_HIPROC = 0x7fffffff; - - /** * Offset of first byte of segment data in file */ private final int p_offset; @@ -1194,17 +944,8 @@ case PT_GNU_STACK: return "GNU stack executability"; default: - if ((p_type > PT_LOPROC) && (p_type <= PT_HIPROC)) { - return "Processor specific segment 0x" + Integer.toHexString(p_type); - } else if ((p_type > PT_LOOS) && (p_type <= PT_HIOS)) { - if ((p_type > PT_LOSUNW) && (p_type <= PT_HISUNW)) { - return "Sun OS specific segment 0x" + Integer.toHexString(p_type); - } else { - return "OS specific segment 0x" + Integer.toHexString(p_type); - } - } else { - return "Unknown segment: 0x" + Integer.toHexString(p_type); - } + SegmentRange range = SegmentRange.fromInteger(p_type); + return range.toString() + "(0x" + Integer.toHexString(p_type) + ")"; } } } Modified: src/org/binarytranslator/generic/os/loader/image/ImageLoader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/image/ImageLoader.java 2007-04-19 23:18:32 UTC (rev 74) +++ src/org/binarytranslator/generic/os/loader/image/ImageLoader.java 2007-04-20 18:42:26 UTC (rev 75) @@ -25,44 +25,23 @@ private String architecture; @Override - public String getABIString() { - return null; + public ABI getABI() { + return ABI.Undefined; } @Override - public String getArchitectureString() { - return architecture; + public ISA getISA() { + if (architecture.equals("ARM")) + return ISA.ARM; + else + if (architecture.equals("PPC")) + return ISA.PPC; + else + if (architecture.equals("X86")) + return ISA.X86; + + return ISA.Undefined; } - - @Override - public boolean isARM_ABI() { - return false; - } - - @Override - public boolean isARM_ISA() { - return architecture.equals("ARM"); - } - - @Override - public boolean isLinuxABI() { - return false; - } - - @Override - public boolean isPPC_ISA() { - return architecture.equals("ISA"); - } - - @Override - public boolean isSysV_ABI() { - return false; - } - - @Override - public boolean isX86_ISA() { - return architecture.equals("X86"); - } /** * Read from the given file and determine whether it contains the correct ID string for an Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-19 23:18:32 UTC (rev 74) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-20 18:42:26 UTC (rev 75) @@ -80,19 +80,27 @@ public static ProcessSpace createProcessSpaceFromBinary(Loader loader) throws IOException { ProcessSpace result; - if (loader.isX86_ISA()) { - report("X86 Binary"); - result = X86_ProcessSpace.createProcessSpaceFromBinary(loader); - } else if (loader.isPPC_ISA()) { - report("PPC Binary"); - result = PPC_ProcessSpace.createProcessSpaceFromBinary(loader); - } else if (loader.isARM_ISA()) { - report("ARM Binary"); - result = ARM_ProcessSpace.createProcessSpaceFromBinary(loader); - } else { - throw new UnsupportedOperationException("Binary of " - + loader.getArchitectureString() + " architecture is unsupported"); + + Loader.ISA isa = loader.getISA(); + report("Found " + isa.toString() + " ISA."); + + switch (isa) { + case X86: + result = X86_ProcessSpace.createProcessSpaceFromBinary(loader); + break; + + case PPC: + result = PPC_ProcessSpace.createProcessSpaceFromBinary(loader); + break; + + case ARM: + result = ARM_ProcessSpace.createProcessSpaceFromBinary(loader); + break; + + default: + throw new UnsupportedOperationException("Binary of "+ isa + " architecture is unsupported"); } + return result; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-20 22:15:51
|
Revision: 77 http://svn.sourceforge.net/pearcolator/?rev=77&view=rev Author: captain5050 Date: 2007-04-20 15:15:52 -0700 (Fri, 20 Apr 2007) Log Message: ----------- Some x86 improvements and GDB stub support Modified Paths: -------------- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/generic/execution/GdbController.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-20 18:51:50 UTC (rev 76) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-20 22:15:52 UTC (rev 77) @@ -759,8 +759,10 @@ * instruction and instruction address * @return the next instruction interpreter */ - public InstructionDecoder interpret(ProcessSpace ps) + public InstructionDecoder interpret(ProcessSpace ps, int pc) throws BadInstructionException { + X86_InstructionDecoder decoder = getDecoder(ps, pc); + System.err.println("Attempt to interpret " + decoder.disassemble(ps, pc)); TODO(); return null; } @@ -1144,12 +1146,12 @@ X86_Registers.ECX, 32); translationHelper.appendInstructionToCurrentBlock( - Binary.create(INT_ADD, ecx.copyRO(), ecx.copyRO(), new OPT_IntConstantOperand(-1))); + Binary.create(INT_ADD, ecx, ecx.copyRO(), new OPT_IntConstantOperand(-1))); OPT_RegisterOperand guardResult = translationHelper.getTempValidation(0); translationHelper.appendInstructionToCurrentBlock( IfCmp.create(INT_IFCMP, guardResult, ecx.copyRO(), new OPT_IntConstantOperand(0), - OPT_ConditionOperand.EQUAL(), instructionBlock.makeJumpTarget(), + OPT_ConditionOperand.NOT_EQUAL(), instructionBlock.makeJumpTarget(), OPT_BranchProfileOperand.likely())); instructionBlock.insertOut(instructionBlock); @@ -2539,7 +2541,7 @@ // Perform copy OPT_RegisterOperand temp = translationHelper.getTempInt(0); source.readToRegister(translationHelper, lazy, temp); - destination.writeValue(translationHelper, lazy, temp); + destination.writeValue(translationHelper, lazy, temp.copyRO()); // Do update OPT_RegisterOperand esi = translationHelper.getGPRegister(lazy, @@ -2614,11 +2616,11 @@ // TODO: apply segment override switch (operandSize) { case 8: - return "movsb ds:" + addressPrefix + "si, " + addressPrefix + "di"; + return "movsb es:" + addressPrefix + "di, ds:" + addressPrefix + "si"; case 16: - return "movsw ds:" + addressPrefix + "si, " + addressPrefix + "di"; + return "movsw es:" + addressPrefix + "di, ds:" + addressPrefix + "si"; case 32: - return "movsd ds:" + addressPrefix + "si, " + addressPrefix + "di"; + return "movsd es:" + addressPrefix + "di, ds:" + addressPrefix + "si"; default: DBT_OptimizingCompilerException.UNREACHABLE(); return "error"; Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-20 18:51:50 UTC (rev 76) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-20 22:15:52 UTC (rev 77) @@ -9,6 +9,7 @@ package org.binarytranslator.arch.x86.os.process; import java.io.*; +import java.util.Hashtable; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; @@ -18,12 +19,15 @@ import org.binarytranslator.generic.memory.ByteAddressedMemory; import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.arch.ppc.os.process.linux.PPC_LinuxProcessSpace; +import org.binarytranslator.arch.ppc.decoder.PPC_InstructionDecoder; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; import org.binarytranslator.arch.x86.decoder.X86_InstructionDecoder; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.vmInterface.DBT_Trace; +import org.binarytranslator.vmInterface.DynamicCodeRunner; import org.vmmagic.pragma.Uninterruptible; +import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; /** * Encapsulate the parts of an X86 process that are common across operating systems @@ -157,23 +161,39 @@ */ public static ProcessSpace createProcessSpaceFromBinary (Loader loader) throws IOException { Loader.ABI abi = loader.getABI(); - + switch (abi) { - case Linux: - case SystemV: - report("Linux/SysV ABI"); - return new PPC_LinuxProcessSpace(loader); - - default: - throw new IOException("Binary of " + abi + " ABI is unsupported for the PowerPC architecture"); + case Linux: + case SystemV: + report("Linux/SysV ABI"); + return new X86_LinuxProcessSpace(loader); + default: + throw new IOException("Binary of " + abi + " ABI is unsupported for the X86 architecture"); } } + Hashtable<Integer, DBT_Trace> singleInstrCodeHash = new Hashtable<Integer, DBT_Trace>(); /** * Run a single instruction */ public void runOneInstruction() throws BadInstructionException { - throw new UnsupportedOperationException("To be implemented"); + try { + // X86_InstructionDecoder.getDecoder(this,registers.eip).interpret(this, registers.eip); + DBT_Trace trace = singleInstrCodeHash.get(registers.eip); + if (trace == null) { + trace = new DBT_Trace(this, registers.eip); + if (DBT_Options.debugRuntime) { + report("Translating code for 0x" + Integer.toHexString(trace.pc)); + } + DBT_Options.singleInstrTranslation = true; + trace.compile(); + singleInstrCodeHash.put(registers.eip, trace); + } + VM_CodeArray code = trace.getCurrentCompiledMethod().getEntryCodeArray(); + registers.eip = DynamicCodeRunner.invokeCode(code, this); + } catch (NullPointerException e) { + throw new BadInstructionException(registers.eip, this); + } } /** Modified: src/org/binarytranslator/generic/execution/GdbController.java =================================================================== --- src/org/binarytranslator/generic/execution/GdbController.java 2007-04-20 18:51:50 UTC (rev 76) +++ src/org/binarytranslator/generic/execution/GdbController.java 2007-04-20 22:15:52 UTC (rev 77) @@ -506,7 +506,7 @@ */ private void handle_getMemValue(int dataEnd) throws IOException { String data = bufferToString(2, dataEnd); - int address = Integer.parseInt(data.substring(0, data.indexOf(',')), 16); + int address = (int)Long.parseLong(data.substring(0, data.indexOf(',')), 16); int count = Integer.parseInt(data.substring(data.indexOf(',') + 1), 16); try { byte value[] = new byte[count * 2]; Modified: src/org/binarytranslator/generic/memory/ByteAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-04-20 18:51:50 UTC (rev 76) +++ src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-04-20 22:15:52 UTC (rev 77) @@ -509,9 +509,13 @@ * the address of where to store */ public void store32(int addr, int value) { - store8(addr + 3, value >> 24); - store8(addr + 2, value >> 16); - store8(addr + 1, value >> 8); - store8(addr, value); + try { + store8(addr + 3, value >> 24); + store8(addr + 2, value >> 16); + store8(addr + 1, value >> 8); + store8(addr, value); + } catch (Exception e) { + throw new SegmentationFault(addr); + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-21 19:45:02
|
Revision: 79 http://svn.sourceforge.net/pearcolator/?rev=79&view=rev Author: michael_baer Date: 2007-04-21 12:44:59 -0700 (Sat, 21 Apr 2007) Log Message: ----------- - Added ABI support for ARM linux: legacy ABI and ARM EABI - Fixed bug in system call interface - fixed ARM decoder bugs Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Added Paths: ----------- src/org/binarytranslator/arch/arm/os/process/linux/abi/ src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java Removed Paths: ------------- src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-20 22:55:52 UTC (rev 78) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-21 19:44:59 UTC (rev 79) @@ -317,7 +317,7 @@ String registers = ""; - for (int i = 0; i < 15; i++) + for (int i = 0; i <= 15; i++) if (instr.transferRegister(i)) registers += ", r" + i; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-20 22:55:52 UTC (rev 78) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-21 19:44:59 UTC (rev 79) @@ -691,7 +691,7 @@ transferPC = transferRegister(15); int regCount = 0; - for (int i = 0; i < 14; i++) + for (int i = 0; i <= 14; i++) if (transferRegister(i)) { registersToTransfer[regCount++] = i; } @@ -756,7 +756,7 @@ //also transfer the program counter, if requested so if (transferPC) { nextAddress += 4; - ps.memory.store32(nextAddress, regs.get(15)); + ps.memory.store32(nextAddress, regs.get(15) + 8); } } Modified: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-04-20 22:55:52 UTC (rev 78) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-04-21 19:44:59 UTC (rev 79) @@ -7,6 +7,26 @@ public ARM_LinuxSystemCalls(LinuxSystemCallGenerator src) { super(src); + + systemCallTable[1] = new LinuxSystemCalls.SysExit(); + systemCallTable[3] = new LinuxSystemCalls.SysRead(); + systemCallTable[4] = new LinuxSystemCalls.SysWrite(); + systemCallTable[5] = new LinuxSystemCalls.SysOpen(); + systemCallTable[6] = new LinuxSystemCalls.SysClose(); + systemCallTable[24] = new LinuxSystemCalls.SysGetUID(); + systemCallTable[45] = new LinuxSystemCalls.SysBrk(); + systemCallTable[47] = new LinuxSystemCalls.SysGetGID(); + systemCallTable[49] = new LinuxSystemCalls.SysGetEUID(); + systemCallTable[50] = new LinuxSystemCalls.SysGetEGID(); + systemCallTable[90] = new LinuxSystemCalls.SysMmap(); + systemCallTable[122] = new LinuxSystemCalls.SysUname(); + systemCallTable[146] = new LinuxSystemCalls.SysWriteV(); + systemCallTable[199] = new LinuxSystemCalls.SysGetEUID(); + systemCallTable[200] = new LinuxSystemCalls.SysGetEGID(); + systemCallTable[201] = new LinuxSystemCalls.SysGetEUID(); + systemCallTable[202] = new LinuxSystemCalls.SysGetEGID(); + systemCallTable[221] = new LinuxSystemCalls.SysFcntl64(); + systemCallTable[252] = new LinuxSystemCalls.SysExitGroup(); } @Override @@ -17,7 +37,308 @@ @Override public String sysCallToString(int syscall) { - throw new RuntimeException("Not yet implemented."); + switch(syscall) { + case 0: return "restart_syscall"; + case 1: return "exit"; + case 2: return "fork"; + case 3: return "read"; + case 4: return "write"; + case 5: return "open"; + case 6: return "close"; + case 7: return "waitpid"; + case 8: return "creat"; + case 9: return "link"; + case 10: return "unlink"; + case 11: return "execve"; + case 12: return "chdir"; + case 13: return "time"; + case 14: return "mknod"; + case 15: return "chmod"; + case 16: return "lchown"; + case 17: return "break"; + case 18: return "oldstat"; + case 19: return "lseek"; + case 20: return "getpid"; + case 21: return "mount"; + case 22: return "umount"; + case 23: return "setuid"; + case 24: return "getuid"; + case 25: return "stime"; + case 26: return "ptrace"; + case 27: return "alarm"; + case 28: return "oldfstat"; + case 29: return "pause"; + case 30: return "utime"; + case 31: return "stty"; + case 32: return "gtty"; + case 33: return "access"; + case 34: return "nice"; + case 35: return "ftime"; + case 36: return "sync"; + case 37: return "kill"; + case 38: return "rename"; + case 39: return "mkdir"; + case 40: return "rmdir"; + case 41: return "dup"; + case 42: return "pipe"; + case 43: return "times"; + case 44: return "prof"; + case 45: return "brk"; + case 46: return "setgid"; + case 47: return "getgid"; + case 48: return "signal"; + case 49: return "geteuid"; + case 50: return "getegid"; + case 51: return "acct"; + case 52: return "umount2"; + case 53: return "lock"; + case 54: return "ioctl"; + case 55: return "fcntl"; + case 56: return "mpx"; + case 57: return "setpgid"; + case 58: return "ulimit"; + case 59: return "oldolduname"; + case 60: return "umask"; + case 61: return "chroot"; + case 62: return "ustat"; + case 63: return "dup2"; + case 64: return "getppid"; + case 65: return "getpgrp"; + case 66: return "setsid"; + case 67: return "sigaction"; + case 68: return "sgetmask"; + case 69: return "ssetmask"; + case 70: return "setreuid"; + case 71: return "setregid"; + case 72: return "sigsuspend"; + case 73: return "sigpending"; + case 74: return "sethostname"; + case 75: return "setrlimit"; + case 76: return "getrlimit"; + case 77: return "getrusage"; + case 78: return "gettimeofday"; + case 79: return "settimeofday"; + case 80: return "getgroups"; + case 81: return "setgroups"; + case 82: return "select"; + case 83: return "symlink"; + case 84: return "oldlstat"; + case 85: return "readlink"; + case 86: return "uselib"; + case 87: return "swapon"; + case 88: return "reboot"; + case 89: return "readdir"; + case 90: return "mmap"; + case 91: return "munmap"; + case 92: return "truncate"; + case 93: return "ftruncate"; + case 94: return "fchmod"; + case 95: return "fchown"; + case 96: return "getpriority"; + case 97: return "setpriority"; + case 98: return "profil"; + case 99: return "statfs"; + case 100: return "fstatfs"; + case 101: return "ioperm"; + case 102: return "socketcall"; + case 103: return "syslog"; + case 104: return "setitimer"; + case 105: return "getitimer"; + case 106: return "stat"; + case 107: return "lstat"; + case 108: return "fstat"; + case 109: return "olduname"; + case 110: return "iopl"; + case 111: return "vhangup"; + case 112: return "idle"; + case 113: return "vm86old"; + case 114: return "wait4"; + case 115: return "swapoff"; + case 116: return "sysinfo"; + case 117: return "ipc"; + case 118: return "fsync"; + case 119: return "sigreturn"; + case 120: return "clone"; + case 121: return "setdomainname"; + case 122: return "uname"; + case 123: return "modify_ldt"; + case 124: return "adjtimex"; + case 125: return "mprotect"; + case 126: return "sigprocmask"; + case 127: return "create_module"; + case 128: return "init_module"; + case 129: return "delete_module"; + case 130: return "get_kernel_syms"; + case 131: return "quotactl"; + case 132: return "getpgid"; + case 133: return "fchdir"; + case 134: return "bdflush"; + case 135: return "sysfs"; + case 136: return "personality"; + case 137: return "afs_syscall"; + case 138: return "setfsuid"; + case 139: return "setfsgid"; + case 140: return "_llseek"; + case 141: return "getdents"; + case 142: return "_newselect"; + case 143: return "flock"; + case 144: return "msync"; + case 145: return "readv"; + case 146: return "writev"; + case 147: return "getsid"; + case 148: return "fdatasync"; + case 149: return "_sysctl"; + case 150: return "mlock"; + case 151: return "munlock"; + case 152: return "mlockall"; + case 153: return "munlockall"; + case 154: return "sched_setparam"; + case 155: return "sched_getparam"; + case 156: return "sched_setscheduler"; + case 157: return "sched_getscheduler"; + case 158: return "sched_yield"; + case 159: return "sched_get_priority_max"; + case 160: return "sched_get_priority_min"; + case 161: return "sched_rr_get_interval"; + case 162: return "nanosleep"; + case 163: return "mremap"; + case 164: return "setresuid"; + case 165: return "getresuid"; + case 166: return "vm86"; + case 167: return "query_module"; + case 168: return "poll"; + case 169: return "nfsservctl"; + case 170: return "setresgid"; + case 171: return "getresgid"; + case 172: return "prctl"; + case 173: return "rt_sigreturn"; + case 174: return "rt_sigaction"; + case 175: return "rt_sigprocmask"; + case 176: return "rt_sigpending"; + case 177: return "rt_sigtimedwait"; + case 178: return "rt_sigqueueinfo"; + case 179: return "rt_sigsuspend"; + case 180: return "pread64"; + case 181: return "pwrite64"; + case 182: return "chown"; + case 183: return "getcwd"; + case 184: return "capget"; + case 185: return "capset"; + case 186: return "sigaltstack"; + case 187: return "sendfile"; + case 188: return "getpmsg"; + case 189: return "putpmsg"; + case 190: return "vfork"; + case 191: return "ugetrlimit"; + case 192: return "mmap2"; + case 193: return "truncate64"; + case 194: return "ftruncate64"; + case 195: return "stat64"; + case 196: return "lstat64"; + case 197: return "fstat64"; + case 198: return "lchown32"; + case 199: return "getuid32"; + case 200: return "getgid32"; + case 201: return "geteuid32"; + case 202: return "getegid32"; + case 203: return "setreuid32"; + case 204: return "setregid32"; + case 205: return "getgroups32"; + case 206: return "setgroups32"; + case 207: return "fchown32"; + case 208: return "setresuid32"; + case 209: return "getresuid32"; + case 210: return "setresgid32"; + case 211: return "getresgid32"; + case 212: return "chown32"; + case 213: return "setuid32"; + case 214: return "setgid32"; + case 215: return "setfsuid32"; + case 216: return "setfsgid32"; + case 217: return "pivot_root"; + case 218: return "mincore"; + case 219: return "madvise"; + case 220: return "getdents64"; + case 221: return "fcntl64"; + + case 224: return "gettid"; + case 225: return "readahead"; + case 226: return "setxattr"; + case 227: return "lsetxattr"; + case 228: return "fsetxattr"; + case 229: return "getxattr"; + case 230: return "lgetxattr"; + case 231: return "fgetxattr"; + case 232: return "listxattr"; + case 233: return "llistxattr"; + case 234: return "flistxattr"; + case 235: return "removexattr"; + case 236: return "lremovexattr"; + case 237: return "fremovexattr"; + case 238: return "tkill"; + case 239: return "sendfile64"; + case 240: return "futex"; + case 241: return "sched_setaffinity"; + case 242: return "sched_getaffinity"; + case 243: return "set_thread_area"; + case 244: return "get_thread_area"; + case 245: return "io_setup"; + case 246: return "io_destroy"; + case 247: return "io_getevents"; + case 248: return "io_submit"; + case 249: return "io_cancel"; + case 250: return "fadvise64"; + case 251: return "set_zone_reclaim"; + case 252: return "exit_group"; + case 253: return "lookup_dcookie"; + case 254: return "epoll_create"; + case 255: return "epoll_ctl"; + case 256: return "epoll_wait"; + case 257: return "remap_file_pages"; + case 258: return "set_tid_address"; + case 259: return "timer_create"; + case 260: return "timer_settime"; + case 261: return "timer_gettime"; + case 262: return "timer_getoverrun"; + case 263: return "timer_delete"; + case 264: return "clock_settime"; + case 265: return "clock_gettime"; + case 266: return "clock_getres"; + case 267: return "clock_nanosleep"; + case 268: return "statfs64"; + case 269: return "fstatfs64"; + case 270: return "tgkill"; + case 271: return "utimes"; + case 272: return "fadvise64_64"; + case 273: return "vserver"; + case 274: return "mbind"; + case 275: return "get_mempolicy"; + case 276: return "set_mempolicy"; + case 277: return "mq_open"; + case 278: return "mq_unlink"; + case 279: return "mq_timedsend"; + case 280: return "mq_timedreceive"; + case 281: return "mq_notify"; + case 282: return "mq_getsetattr"; + case 283: return "sys_kexec_load"; + case 284: return "waitid"; + case 285: return "sys_setaltroot"; + case 286: return "add_key"; + case 287: return "request_key"; + case 288: return "keyctl"; + case 289: return "ioprio_set"; + case 290: return "ioprio_get"; + case 291: return "inotify_init"; + case 292: return "inotify_add_watch"; + case 293: return "inotify_rm_watch"; + default: + if ((syscall > 0) && (syscall < 294)) { + return "unused"; + } + else { + return "invalid system call number " + syscall; + } + } } } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-20 22:55:52 UTC (rev 78) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-21 19:44:59 UTC (rev 79) @@ -5,7 +5,6 @@ import org.binarytranslator.arch.arm.decoder.ARM_Interpreter; import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; -import org.binarytranslator.arch.x86.decoder.X86_InstructionDecoder; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.memory.DebugMemory; import org.binarytranslator.generic.os.loader.Loader; Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-20 22:55:52 UTC (rev 78) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-21 19:44:59 UTC (rev 79) @@ -4,29 +4,25 @@ import org.binarytranslator.arch.arm.os.abi.linux.ARM_LinuxSystemCalls; 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.linux.abi.Legacy; import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.os.abi.linux.LinuxStackInitializer; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.loader.elf.ELF_Loader; -import org.binarytranslator.generic.os.process.ProcessSpace; -public class ARM_LinuxProcessSpace extends ARM_ProcessSpace implements - LinuxSystemCallGenerator { +public class ARM_LinuxProcessSpace extends ARM_ProcessSpace { /** * A link to the current system call interface */ private final LinuxSystemCalls sysCalls; + + /** As ARM provides two different linux ABIs, we put the system call specifics into a separate class.*/ + private final LinuxSystemCallGenerator sysCallGenerator; /** - * A re-used iterator that allows enumerating the argument of the current - * system call - */ - private final ARM_SyscallArgumentIterator syscallArgs; - - /** * The top of the stack */ private static final int STACK_TOP = 0xC0000000; @@ -37,13 +33,17 @@ private int brk; public ARM_LinuxProcessSpace() { - sysCalls = new ARM_LinuxSystemCalls(this); - syscallArgs = new ARM_SyscallArgumentIterator(this); + sysCallGenerator = new Legacy(this); + sysCalls = new ARM_LinuxSystemCalls(sysCallGenerator); } @Override public void doSysCall() { sysCalls.doSysCall(); + + //simulate a return from the call + //TODO: This actually assumes that we're calling from ARM32 + registers.set(ARM_Registers.PC, getCurrentInstructionAddress() + 4); } @Override @@ -75,38 +75,9 @@ registers.set(ARM_Registers.SP, LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector)); } - public int getBrk() { - return brk; - } - - public int getSysCallNumber() { - // TODO Auto-generated method stub - return 0; - } - - public CallArgumentIterator getSysCallArguments() { - syscallArgs.reset(); - return syscallArgs; - } - - public void setBrk(int address) { - brk = address; - } - - public void setSysCallError(int r) { - // TODO Auto-generated method stub - } - - public void setSysCallReturn(int r) { - // TODO Auto-generated method stub - } - @Override public GdbTarget getGdbTarget() { return null; } - public ProcessSpace getProcessSpace() { - return this; - } } Deleted: src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java 2007-04-20 22:55:52 UTC (rev 78) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java 2007-04-21 19:44:59 UTC (rev 79) @@ -1,37 +0,0 @@ -package org.binarytranslator.arch.arm.os.process.linux; - -import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; - -public class ARM_SyscallArgumentIterator implements - LinuxSystemCallGenerator.CallArgumentIterator { - - private final ARM_LinuxProcessSpace ps; - - private int currentArgument; - - public ARM_SyscallArgumentIterator(ARM_LinuxProcessSpace ps) { - this.ps = ps; - this.currentArgument = 0; - } - - public int nextInt() { - return ps.registers.get(currentArgument++); - } - - public long nextLong() { - // only start reading longs from even registers - if ((currentArgument & 1) == 1) - currentArgument++; - - // TODO: This code is actually assuming that we're on little endian - long lowWord = nextInt(); - long highWord = nextInt(); - - return highWord << 32 | lowWord; - } - - public void reset() { - currentArgument = 0; - } - -} Added: src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-21 19:44:59 UTC (rev 79) @@ -0,0 +1,103 @@ +package org.binarytranslator.arch.arm.os.process.linux.abi; + +import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; +import org.binarytranslator.generic.os.process.ProcessSpace; + +/** + * ARM EABI linux system call ABI. + * <code> + * Example call to long ftruncate64(unsigned int fd, loff_t length): + * + * EABI ABI: + * - put fd into r0 + * - put length into r2-r3 (skipping over r1) + * - put 194 into r7 + * - use "swi #0" to call the kernel + * + * </code> + * + * Therefore, note that long values are aligned to even registers. + * The holes, which are created within the register map are not filled, though. + * + * @author Michael Baer + * + */ +public class EABI implements LinuxSystemCallGenerator { + + /** The process space that we're running on. */ + private final ARM_LinuxProcessSpace ps; + private final ArgumentIterator args; + + public EABI(ARM_LinuxProcessSpace ps) { + this.ps = ps; + this.args = new ArgumentIterator(); + } + + public int getBrk() { + // TODO Auto-generated method stub + throw new RuntimeException("Not yet implemented."); + } + + public ProcessSpace getProcessSpace() { + return ps; + } + + public CallArgumentIterator getSysCallArguments() { + args.reset(); + return args; + } + + public int getSysCallNumber() { + return ps.registers.get(7); + } + + public void setBrk(int address) { +// TODO Auto-generated method stub + throw new RuntimeException("Not yet implemented."); + } + + public void setSysCallError(int r) { + // TODO Auto-generated method stub + throw new RuntimeException("Not yet implemented."); + } + + public void setSysCallReturn(int r) { + // TODO Auto-generated method stub + throw new RuntimeException("Not yet implemented."); + } + + /** An argument iterator that hides the layout of syscall arguments on the ARM architecture */ + public final class ArgumentIterator implements + LinuxSystemCallGenerator.CallArgumentIterator { + + /** The current argument number. Set to zero for the first agument.*/ + private int currentArgument; + + public ArgumentIterator() { + this.currentArgument = 0; + } + + public int nextInt() { + return ps.registers.get(currentArgument++); + } + + public long nextLong() { + // only start reading longs from even registers + if ((currentArgument & 1) != 0) + currentArgument++; + + // TODO: This code is actually assuming that we're on little endian + long lowWord = nextInt(); + long highWord = nextInt(); + + return highWord << 32 | lowWord; + } + + /** Restarts argument reading from the first argument. Allows this object to be reused for multiple sys calls. */ + public void reset() { + currentArgument = 0; + } + } + +} Added: src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-21 19:44:59 UTC (rev 79) @@ -0,0 +1,114 @@ +package org.binarytranslator.arch.arm.os.process.linux.abi; + +import org.binarytranslator.DBT; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions; +import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; +import org.binarytranslator.generic.os.process.ProcessSpace; + +/** + * ARM legacy linux system call ABI. + * <code> + * Example call to long ftruncate64(unsigned int fd, loff_t length): + * + * legacy ABI: + * - put fd into r0 + * - put length into r1-r2 + * - use "swi #(0x900000 + 194)" to call the kernel (swi #194 for thumb linux). + * + * </code> + * + * @author Michael Baer + * + */ +public class Legacy implements LinuxSystemCallGenerator { + + /** The process space that we're running on. */ + private final ARM_LinuxProcessSpace ps; + + /** A re-used iterator that allows enumerating the argument of the current + * system call */ + private final ArgumentIterator syscallArgs; + + + public Legacy(ARM_LinuxProcessSpace ps) { + this.ps = ps; + syscallArgs = new ArgumentIterator(); + } + + public int getBrk() { +// TODO Auto-generated method stub + throw new RuntimeException("Not yet implemented."); + } + + public void setBrk(int address) { +// TODO Auto-generated method stub + throw new RuntimeException("Not yet implemented."); + } + + public ProcessSpace getProcessSpace() { + return ps; + } + + public CallArgumentIterator getSysCallArguments() { + syscallArgs.reset(); + return syscallArgs; + } + + public int getSysCallNumber() { + //ARM syscalls are trigged by a SWI instruction, which includes the syscall number within its opcode. + //therefore, we are going to decode the instruction first + int instruction = ps.memory.loadInstruction32(ps.getCurrentInstructionAddress()); + ARM_Instructions.Instruction instr = ARM_InstructionDecoder.decode(instruction); + + if (DBT.VerifyAssertions) { + if (!(instr instanceof ARM_Instructions.SoftwareInterrupt)) { + throw new Error("The current instruction is not a valid system call."); + } + } + + //Thumb system calls start from 0, while ARM calls start from 0x900000. + //Use a mask to let both calls start from the same address + int sysCallNr = ((ARM_Instructions.SoftwareInterrupt)instr).getInterruptNumber(); + return sysCallNr & 0xFFFFF; + } + + public void setSysCallError(int r) { +// TODO Auto-generated method stub + throw new RuntimeException("Not yet implemented."); + } + + public void setSysCallReturn(int value) { + ps.registers.set(0, value); + } + + /** An argument iterator that hides the layout of syscall arguments on the ARM architecture */ + public final class ArgumentIterator implements + LinuxSystemCallGenerator.CallArgumentIterator { + + /** The current argument number. Set to zero for the first agument.*/ + private int currentArgument; + + public ArgumentIterator() { + this.currentArgument = 0; + } + + public int nextInt() { + return ps.registers.get(currentArgument++); + } + + public long nextLong() { + // TODO: This code is actually assuming that we're on little endian + long lowWord = nextInt(); + long highWord = nextInt(); + + return highWord << 32 | lowWord; + } + + /** Restarts argument reading from the first argument. Allows this object to be reused for multiple sys calls. */ + private void reset() { + currentArgument = 0; + } + } +} Modified: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java 2007-04-20 22:55:52 UTC (rev 78) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java 2007-04-21 19:44:59 UTC (rev 79) @@ -53,5 +53,4 @@ public void reset() { nextArgument = 0; } - } Modified: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-04-20 22:55:52 UTC (rev 78) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-04-21 19:44:59 UTC (rev 79) @@ -12,19 +12,21 @@ @Override public void run() { Interpreter interpreter = ps.createInstructionInterpreter(); + int pc = ps.getCurrentInstructionAddress(); while (!ps.finished) { Interpreter.Instruction instruction = interpreter.decode(pc); + System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); pc = instruction.getSuccessor(pc); - System.out.println("Interpreting instruction: " + instruction.toString()); - instruction.execute(); if (pc == -1) pc = ps.getCurrentInstructionAddress(); + else + ps.setCurrentInstructionAddress(pc); } } Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-20 22:55:52 UTC (rev 78) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-21 19:44:59 UTC (rev 79) @@ -24,6 +24,9 @@ * The source of the system calls */ private LinuxSystemCallGenerator src; + + /** Allows access to the system call's arguments */ + private LinuxSystemCallGenerator.CallArgumentIterator arguments; /** * Maximum number of system calls @@ -160,6 +163,7 @@ public void doSysCall() { int sysCallNumber = src.getSysCallNumber(); System.err.println("Syscall "+ sysCallToString(sysCallNumber)); + arguments = src.getSysCallArguments(); systemCallTable[sysCallNumber].doSysCall(); } @@ -484,14 +488,6 @@ */ public abstract void doSysCall(); } - - abstract class ParameterizedSystemCall extends SystemCall { - protected final LinuxSystemCallGenerator.CallArgumentIterator arguments; - - public ParameterizedSystemCall() { - arguments = src.getSysCallArguments(); - } - } /** * Unknown System Call @@ -513,7 +509,7 @@ /** * Exit system call */ - public class SysExit extends ParameterizedSystemCall { + public class SysExit extends SystemCall { public void doSysCall() { int status = arguments.nextInt(); System.exit(status); @@ -523,7 +519,7 @@ /** * Read from a file */ - public class SysRead extends ParameterizedSystemCall { + public class SysRead extends SystemCall { public void doSysCall() { int fd = arguments.nextInt(); int buf = arguments.nextInt(); @@ -574,7 +570,7 @@ /** * Write to a file */ - public class SysWrite extends ParameterizedSystemCall { + public class SysWrite extends SystemCall { public void doSysCall() { int fd = arguments.nextInt(); int buf = arguments.nextInt(); @@ -626,7 +622,7 @@ /** * Write data into multiple buffers */ - public class SysWriteV extends ParameterizedSystemCall { + public class SysWriteV extends SystemCall { public void doSysCall() { int fd = arguments.nextInt(); int vector = arguments.nextInt(); @@ -655,7 +651,7 @@ } } - public class SysOpen extends ParameterizedSystemCall { + public class SysOpen extends SystemCall { public void doSysCall() { int pathname = arguments.nextInt(); int flags = arguments.nextInt(); @@ -703,7 +699,7 @@ } } - public class SysClose extends ParameterizedSystemCall { + public class SysClose extends SystemCall { public void doSysCall() { int fd = arguments.nextInt(); RandomAccessFile raFile = getRAFile(fd); @@ -747,7 +743,7 @@ } } - public class SysBrk extends ParameterizedSystemCall { + public class SysBrk extends SystemCall { public void doSysCall() { int brk = arguments.nextInt(); @@ -767,20 +763,20 @@ } } - public class SysFcntl64 extends ParameterizedSystemCall { + public class SysFcntl64 extends SystemCall { public void doSysCall() { // This is complicated so fudge it for now. int fd = arguments.nextInt(); int cmd = arguments.nextInt(); - if( ((fd == 0) | (fd == 1) | (fd == 2)) & (cmd == 1) ) + if( ((fd == 0) || (fd == 1) || (fd == 2)) && (cmd == 1) ) src.setSysCallReturn(0); else throw new Error("Unrecognised system call."); } } - public class SysUname extends ParameterizedSystemCall { + public class SysUname extends SystemCall { public void doSysCall() { // Simple uname support int addr = arguments.nextInt(); @@ -819,7 +815,7 @@ } } - public class SysMmap extends ParameterizedSystemCall { + public class SysMmap extends SystemCall { public void doSysCall() { int start = arguments.nextInt(); @@ -846,7 +842,7 @@ } } - public class SysMunmap extends ParameterizedSystemCall { + public class SysMunmap extends SystemCall { public void doSysCall() { int start = arguments.nextInt(); @@ -856,7 +852,7 @@ } } - public class SysExitGroup extends ParameterizedSystemCall { + public class SysExitGroup extends SystemCall { public void doSysCall() { // For now, equivalent to SysExit System.exit(arguments.nextInt()); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-23 10:23:20
|
Revision: 83 http://svn.sourceforge.net/pearcolator/?rev=83&view=rev Author: captain5050 Date: 2007-04-23 03:23:21 -0700 (Mon, 23 Apr 2007) Log Message: ----------- Fixes to brk system call Modified Paths: -------------- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/memory/DebugMemory.java src/org/binarytranslator/generic/memory/IntAddressedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-23 09:23:22 UTC (rev 82) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-23 10:23:21 UTC (rev 83) @@ -160,6 +160,12 @@ * @param address new top of BSS segment */ public void setBrk(int address) { + try { + memory.ensureMapped(brk, address); + } catch (MemoryMapException e) { + throw new Error("Error changing top of BSS to address 0x"+Integer.toHexString(address)+ + " from 0x" + Integer.toHexString(brk), e); + } brk = address; } Modified: src/org/binarytranslator/generic/memory/ByteAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-04-23 09:23:22 UTC (rev 82) +++ src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-04-23 10:23:21 UTC (rev 83) @@ -319,11 +319,11 @@ readableMemory[getPTE(addr + i)] = null; unmapped_something = true; } - if (readableMemory[getPTE(addr + i)] != null) { + if (writableMemory[getPTE(addr + i)] != null) { writableMemory[getPTE(addr + i)] = null; unmapped_something = true; } - if (readableMemory[getPTE(addr + i)] != null) { + if (executableMemory[getPTE(addr + i)] != null) { executableMemory[getPTE(addr + i)] = null; unmapped_something = true; } @@ -335,6 +335,24 @@ } /** + * Is the given address mapped into memory? + * @param addr to check + * @return true => memory is mapped + */ + public boolean isMapped(int addr) { + return ((readableMemory[getPTE(addr)] != null) || + (writableMemory[getPTE(addr)] != null) || + (executableMemory[getPTE(addr)] != null)); + } + + /** + * @return the size of a page + */ + public int getPageSize() { + return PAGE_SIZE; + } + + /** * Is the given address aligned on a page boundary? * * @param addr Modified: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-23 09:23:22 UTC (rev 82) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-23 10:23:21 UTC (rev 83) @@ -306,8 +306,26 @@ } } } - + /** + * Is the given address mapped into memory? + * @param addr to check + * @return true => memory is mapped + */ + public boolean isMapped(int addr) { + return ((readableMemory[getPTE(addr)] != null) || + (writableMemory[getPTE(addr)] != null) || + (executableMemory[getPTE(addr)] != null)); + } + + /** + * @return the size of a page + */ + public int getPageSize() { + return PAGE_SIZE; + } + + /** * Is the given address aligned on a page boundary? * * @param addr Modified: src/org/binarytranslator/generic/memory/IntAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-04-23 09:23:22 UTC (rev 82) +++ src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-04-23 10:23:21 UTC (rev 83) @@ -98,6 +98,24 @@ } /** + * Is the given address mapped into memory? + * @param addr to check + * @return true => memory is mapped + */ + public boolean isMapped(int addr) { + return ((readableMemory[getPTE(addr)] != null) || + (writableMemory[getPTE(addr)] != null) || + (executableMemory[getPTE(addr)] != null)); + } + + /** + * @return the size of a page + */ + public int getPageSize() { + return PAGE_SIZE; + } + + /** * Is the given address aligned on a page boundary? * * @param addr Modified: src/org/binarytranslator/generic/memory/Memory.java =================================================================== --- src/org/binarytranslator/generic/memory/Memory.java 2007-04-23 09:23:22 UTC (rev 82) +++ src/org/binarytranslator/generic/memory/Memory.java 2007-04-23 10:23:21 UTC (rev 83) @@ -21,38 +21,24 @@ public abstract class Memory { /** * Map an anonymous page of memory - * - * @param addr - * the address to map or NULL if don't care - * @param len - * the amount of memory to map - * @param read - * is the page readable - * @param write - * is the page writable - * @param exec - * is the page executable + * @param addr the address to map or NULL if don't care + * @param len the amount of memory to map + * @param read is the page readable + * @param write is the page writable + * @param exec is the page executable */ public abstract int map(int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException; /** * Map a page of memory from file - * - * @param file - * the file map in from - * @param offset - * the offset of the file to map from - * @param addr - * the address to map or NULL if don't care - * @param len - * the amount of memory to map - * @param read - * is the page readable - * @param write - * is the page writable - * @param exec - * is the page executable + * @param file the file map in from + * @param offset the offset of the file to map from + * @param addr the address to map or NULL if don't care + * @param len the amount of memory to map + * @param read is the page readable + * @param write is the page writable + * @param exec is the page executable */ public abstract int map(RandomAccessFile file, long offset, int addr, int len, boolean read, boolean write, boolean exec) @@ -60,131 +46,126 @@ /** * Unmap a page of memory - * - * @param addr - * the address to unmap - * @param len - * the amount of memory to unmap + * @param addr the address to unmap + * @param len the amount of memory to unmap */ public abstract void unmap(int addr, int len); /** + * Is the given address mapped into memory? + * @param addr to check + * @return true => memory is mapped + */ + public abstract boolean isMapped(int addr); + + /** + * Ensure memory between start and end is mapped + * @param startAddr starting address for mapped memory + * @param endAddr ending address for mapped memory + */ + public void ensureMapped(int startAddr, int endAddr) throws MemoryMapException { + startAddr = truncateToPage(startAddr); + endAddr = truncateToNextPage(endAddr); + for (;startAddr < endAddr; startAddr += getPageSize()) { + if (!isMapped(startAddr)) { + map(startAddr, getPageSize(), true, true, false); + } + } + } + + /** * Is the given address aligned on a page boundary? - * - * @param addr - * the address to check + * @param addr the address to check * @return whether the address is aligned */ public abstract boolean isPageAligned(int addr); /** * Make the given address page aligned to the page beneath it - * - * @param addr - * the address to truncate + * @param addr the address to truncate * @return the truncated address */ public abstract int truncateToPage(int addr); /** * Make the given address page aligned to the page above it - * - * @param addr - * the address to truncate + * @param addr the address to truncate * @return the truncated address */ public abstract int truncateToNextPage(int addr); /** + * @return the size of a page + */ + public abstract int getPageSize(); + + /** * Perform a byte load where the sign extended result fills the return value - * - * @param addr - * the address of the value to load + * @param addr the address of the value to load * @return the sign extended result */ public abstract int loadSigned8(int addr); /** * Perform a byte load where the zero extended result fills the return value - * - * @param addr - * the address of the value to load + * @param addr the address of the value to load * @return the zero extended result */ public abstract int loadUnsigned8(int addr); /** * Perform a 16bit load where the sign extended result fills the return value - * - * @param addr - * the address of the value to load + * @param addr the address of the value to load * @return the sign extended result */ public abstract int loadSigned16(int addr); /** * Perform a 16bit load where the zero extended result fills the return value - * - * @param addr - * the address of the value to load + * @param addr the address of the value to load * @return the zero extended result */ public abstract int loadUnsigned16(int addr); /** * Perform a 32bit load - * - * @param addr - * the address of the value to load + * @param addr the address of the value to load * @return the result */ public abstract int load32(int addr); /** * Perform a 8bit load from memory that must be executable - * - * @param addr - * the address of the value to load + * @param addr the address of the value to load * @return the result */ public abstract int loadInstruction8(int addr); /** * Perform a 32bit load from memory that must be executable - * - * @param addr - * the address of the value to load + * @param addr the address of the value to load * @return the result */ public abstract int loadInstruction32(int addr); /** * Perform a byte store - * - * @param value - * the value to store - * @param addr - * the address of where to store + * @param value the value to store + * @param addr the address of where to store */ public abstract void store8(int addr, int value); /** * Perform a 16bit store - * - * @param value - * the value to store - * @param addr - * the address of where to store + * @param value the value to store + * @param addr the address of where to store */ public abstract void store16(int addr, int value); /** * Perform a 32bit store - * - * @param value - * the value to store - * @param addr - * the address of where to store + * @param value the value to store + * @param addr the address of where to store */ public abstract void store32(int addr, int value); @@ -197,11 +178,8 @@ /** * Generate the IR code for a byte load where the sign extended result fills * the register - * - * @param dest - * the register to hold the result - * @param addr - * the address of the value to load + * @param dest the register to hold the result + * @param addr the address of the value to load */ public abstract void translateLoadSigned8(OPT_Operand addr, OPT_RegisterOperand dest); @@ -209,11 +187,8 @@ /** * Generate the IR code for a byte load where the zero extended result fills * the register - * - * @param dest - * the register to hold the result - * @param addr - * the address of the value to load + * @param dest the register to hold the result + * @param addr the address of the value to load */ public abstract void translateLoadUnsigned8(OPT_Operand addr, OPT_RegisterOperand dest); @@ -221,11 +196,8 @@ /** * Generate the IR code for a 16bit load where the sign extended result fills * the register - * - * @param dest - * the register to hold the result - * @param addr - * the address of the value to load + * @param dest the register to hold the result + * @param addr the address of the value to load */ public abstract void translateLoadSigned16(OPT_Operand addr, OPT_RegisterOperand dest); @@ -233,68 +205,50 @@ /** * Generate the IR code for a 16bit load where the zero extended result fills * the register - * - * @param dest - * the register to hold the result - * @param addr - * the address of the value to load + * @param dest the register to hold the result + * @param addr the address of the value to load */ public abstract void translateLoadUnsigned16(OPT_Operand addr, OPT_RegisterOperand dest); /** * Generate the IR code for a 32bit load - * - * @param dest - * the register to hold the result - * @param addr - * the address of the value to load + * @param dest the register to hold the result + * @param addr the address of the value to load */ public abstract void translateLoad32(OPT_Operand addr, OPT_RegisterOperand dest); /** * Generate the IR code for a byte store - * - * @param src - * the register that holds the value to store - * @param addr - * the address of the value to store + * @param src the register that holds the value to store + * @param addr the address of the value to store */ - public abstract void translateStore8(OPT_Operand addr, - OPT_RegisterOperand src); + public abstract void translateStore8(OPT_Operand addr, OPT_RegisterOperand src); /** * Generate the IR code for a 16bit store - * - * @param src - * the register that holds the value to store - * @param addr - * the address of the value to store + * @param src the register that holds the value to store + * @param addr the address of the value to store */ public abstract void translateStore16(OPT_Operand addr, OPT_RegisterOperand src); /** * Generate the IR code for a 32bit store - * - * @param src - * the register that holds the value to store - * @param addr - * the address of the value to store + * @param src the register that holds the value to store + * @param addr the address of the value to store */ public abstract void translateStore32(OPT_Operand addr, OPT_RegisterOperand src); /** * Get method reference if linking a call - * - * @param callAddress - * the address associated with this call + * @param callAddress the address associated with this call */ @Uninterruptible public VM_MethodReference getMethodRef(int callAddress) { throw new Error("Error linking method at " + callAddress + " for memory model " + this.getClass()); } -} +} \ No newline at end of file Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java 2007-04-23 09:23:22 UTC (rev 82) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java 2007-04-23 10:23:21 UTC (rev 83) @@ -377,7 +377,7 @@ initialStackSize = memory.truncateToNextPage(initialStackSize); try { - memory.map(stackTop - initialStackSize - 8192, initialStackSize + 8192, + memory.map(stackTop - initialStackSize - (128*1024), initialStackSize + (128*1024), true, true, false); // read/write/no execute } catch (MemoryMapException e) { // Failing to create the stack is a fatal error Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-23 09:23:22 UTC (rev 82) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-23 10:23:21 UTC (rev 83) @@ -746,15 +746,11 @@ public class SysBrk extends SystemCall { public void doSysCall() { int brk = arguments.nextInt(); - - if(brk == 0) { - // Request for the current top of bss. - src.setSysCallReturn(src.getBrk()); - } - else { - // Changing the value. + if(brk != 0) { + // Request to set the current top of bss. src.setBrk(brk); } + src.setSysCallReturn(src.getBrk()); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-23 22:13:20
|
Revision: 89 http://svn.sourceforge.net/pearcolator/?rev=89&view=rev Author: captain5050 Date: 2007-04-23 15:12:34 -0700 (Mon, 23 Apr 2007) Log Message: ----------- Support for move to/from segments, fix for open system call, try to run past unimplemented system calls, fake out x86 set_thread_area syscall with a null system call, try to initialize references as static finals. Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java src/org/binarytranslator/arch/x86/os/process/X86_Registers.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-04-23 21:57:27 UTC (rev 88) +++ src/org/binarytranslator/DBT_Options.java 2007-04-23 22:12:34 UTC (rev 89) @@ -27,7 +27,7 @@ /** * Are unimplemented system calls are fatal? */ - public final static boolean unimplementedSystemCallsFatal = true; + public final static boolean unimplementedSystemCallsFatal = false; // -oO Translation settings Oo- Modified: src/org/binarytranslator/arch/x86/decoder/X862IR.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-23 21:57:27 UTC (rev 88) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-23 22:12:34 UTC (rev 89) @@ -27,6 +27,67 @@ public class X862IR extends DecoderUtils implements OPT_HIRGenerator, OPT_Operators, OPT_Constants { + private static final VM_TypeReference psTref; + private static final VM_FieldReference registersFref; + private static final VM_TypeReference registersTref; + private static final VM_FieldReference segRegFref; + private static final VM_TypeReference segRegTref; + private static final VM_FieldReference gp32Fref; + private static final VM_TypeReference gp32Tref; + private static final VM_FieldReference flagCFref; + private static final VM_FieldReference flagSFref; + private static final VM_FieldReference flagZFref; + private static final VM_FieldReference flagOFref; + private static final VM_FieldReference flagDFref; + + static { + psTref = VM_TypeReference.findOrCreate( + VM_BootstrapClassLoader.getBootstrapClassLoader(), + VM_Atom + .findOrCreateAsciiAtom("Lorg/binarytranslator/arch/x86/os/process/X86_ProcessSpace;")); + + registersFref = VM_MemberReference + .findOrCreate( + psTref, + VM_Atom.findOrCreateAsciiAtom("registers"), + VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/x86/os/process/X86_Registers;")) + .asFieldReference(); + + registersTref = registersFref.getFieldContentsType(); + + segRegFref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("segmentRegister"), + VM_Atom.findOrCreateAsciiAtom("[C")).asFieldReference(); + + segRegTref = segRegFref.getFieldContentsType(); + + gp32Fref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("gp32"), + VM_Atom.findOrCreateAsciiAtom("[I")).asFieldReference(); + + gp32Tref = gp32Fref.getFieldContentsType(); + + flagCFref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("flag_CF"), + VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); + + flagSFref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("flag_SF"), + VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); + + flagZFref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("flag_ZF"), + VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); + + flagOFref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("flag_OF"), + VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); + + flagDFref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("flag_DF"), + VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); + } + /** * Constructor */ @@ -34,6 +95,9 @@ super(context); // Create the registers + SegReg = new OPT_Register[6]; + SegRegInUse = new boolean[6]; + GP32 = new OPT_Register[8]; GP32InUse = new boolean[8]; @@ -94,6 +158,17 @@ // -oO Register Manipulation Oo- /** + * Registers holding 16bit segment values during the trace + */ + private OPT_Register[] SegReg; + + /** + * Which 16bit segment registers have been used during the trace - unused + * registers can be eliminated + */ + private boolean[] SegRegInUse; + + /** * Registers holding 32bit values during the trace */ private OPT_Register[] GP32; @@ -181,6 +256,19 @@ * @param r * the register to read */ + public OPT_RegisterOperand getSegRegister(X86_Laziness laziness, int r) { + SegRegInUse[r] = true; + return new OPT_RegisterOperand(SegReg[r], VM_TypeReference.Int); + } + + /** + * Read a 32bit register + * + * @param laziness + * the lazy state, used to determine register mangling + * @param r + * the register to read + */ public OPT_RegisterOperand getGPRegister32(X86_Laziness laziness, int r) { GP32InUse[r] = true; resolveGPRegister32(laziness, r); @@ -439,9 +527,9 @@ private OPT_Register ps_registers; /** - * The type of ps.registers + * A register holding a reference to ps.registers.segmentRegister */ - private VM_TypeReference registersTref; + private OPT_Register ps_registers_segReg; /** * A register holding a reference to ps.registers.gp32 @@ -449,11 +537,6 @@ private OPT_Register ps_registers_gp32; /** - * The type of ps.registers.gp32 - */ - private VM_TypeReference gp32Tref; - - /** * Fill all the registers from the ProcessSpace, that is take the register * values from the process space and place them in the traces registers. */ @@ -462,19 +545,6 @@ // Get the registers if (ps_registers == null) { // Set up the reference to memory - VM_TypeReference psTref = VM_TypeReference - .findOrCreate( - VM_BootstrapClassLoader.getBootstrapClassLoader(), - VM_Atom - .findOrCreateAsciiAtom("Lorg/binarytranslator/arch/x86/os/process/X86_ProcessSpace;")); - VM_FieldReference registersFref = VM_MemberReference - .findOrCreate( - psTref, - VM_Atom.findOrCreateAsciiAtom("registers"), - VM_Atom - .findOrCreateAsciiAtom("Lorg/binarytranslator/arch/x86/os/process/X86_Registers;")) - .asFieldReference(); - registersTref = registersFref.getFieldContentsType(); ps_registersOp = gc.temps.makeTemp(registersTref); ps_registers = ps_registersOp.register; appendInstructionToCurrentBlock(GetField.create(GETFIELD, ps_registersOp, @@ -484,13 +554,22 @@ } else { ps_registersOp = new OPT_RegisterOperand(ps_registers, registersTref); } + // Get the array of segment registers + OPT_RegisterOperand ps_registers_segRegOp; + if (ps_registers_segReg == null) { + ps_registers_segRegOp = gc.temps.makeTemp(segRegTref); + appendInstructionToCurrentBlock(GetField.create(GETFIELD, + ps_registers_segRegOp, ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(segRegFref.peekResolvedField() + .getOffset()), new OPT_LocationOperand(segRegFref), + new OPT_TrueGuardOperand())); + ps_registers_segReg = ps_registers_segRegOp.register; + } else { + ps_registers_segRegOp = new OPT_RegisterOperand(ps_registers_segReg, segRegTref); + } // Get the array of general purpose registers OPT_RegisterOperand ps_registers_gp32Op; if (ps_registers_gp32 == null) { - VM_FieldReference gp32Fref = VM_MemberReference.findOrCreate( - registersTref, VM_Atom.findOrCreateAsciiAtom("gp32"), - VM_Atom.findOrCreateAsciiAtom("[I")).asFieldReference(); - gp32Tref = gp32Fref.getFieldContentsType(); ps_registers_gp32Op = gc.temps.makeTemp(gp32Tref); appendInstructionToCurrentBlock(GetField.create(GETFIELD, ps_registers_gp32Op, ps_registersOp.copyRO(), @@ -501,6 +580,20 @@ } else { ps_registers_gp32Op = new OPT_RegisterOperand(ps_registers_gp32, gp32Tref); } + // Fill segment registers + for (int i = 0; i < SegReg.length; i++) { + OPT_RegisterOperand segRegOp; + if (GP32[i] == null) { + segRegOp = makeTemp(VM_TypeReference.Char); + SegReg[i] = segRegOp.register; + } else { + segRegOp = new OPT_RegisterOperand(SegReg[i], VM_TypeReference.Char); + } + appendInstructionToCurrentBlock(ALoad.create(USHORT_ALOAD, segRegOp, + ps_registers_segRegOp.copyRO(), new OPT_IntConstantOperand(i), + new OPT_LocationOperand(VM_TypeReference.Char), + new OPT_TrueGuardOperand())); + } // Fill general purpose registers for (int i = 0; i < GP32.length; i++) { OPT_RegisterOperand gp32op; @@ -524,14 +617,11 @@ } else { flag_CF_Op = new OPT_RegisterOperand(flag_CF, VM_TypeReference.Boolean); } - VM_FieldReference flagFref = VM_MemberReference.findOrCreate( - registersTref, VM_Atom.findOrCreateAsciiAtom("flag_CF"), - VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); - VM_TypeReference flagTref = flagFref.getFieldContentsType(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag_CF_Op, - ps_registersOp.copyRO(), new OPT_AddressConstantOperand(flagFref - .peekResolvedField().getOffset()), new OPT_LocationOperand( - flagFref), new OPT_TrueGuardOperand())); + ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(flagCFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(flagCFref), + new OPT_TrueGuardOperand())); } { OPT_RegisterOperand flag_SF_Op; @@ -541,14 +631,11 @@ } else { flag_SF_Op = new OPT_RegisterOperand(flag_SF, VM_TypeReference.Boolean); } - VM_FieldReference flagFref = VM_MemberReference.findOrCreate( - registersTref, VM_Atom.findOrCreateAsciiAtom("flag_SF"), - VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); - VM_TypeReference flagTref = flagFref.getFieldContentsType(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag_SF_Op, - ps_registersOp.copyRO(), new OPT_AddressConstantOperand(flagFref - .peekResolvedField().getOffset()), new OPT_LocationOperand( - flagFref), new OPT_TrueGuardOperand())); + ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(flagSFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(flagSFref), + new OPT_TrueGuardOperand())); } { OPT_RegisterOperand flag_ZF_Op; @@ -558,14 +645,11 @@ } else { flag_ZF_Op = new OPT_RegisterOperand(flag_ZF, VM_TypeReference.Boolean); } - VM_FieldReference flagFref = VM_MemberReference.findOrCreate( - registersTref, VM_Atom.findOrCreateAsciiAtom("flag_ZF"), - VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); - VM_TypeReference flagTref = flagFref.getFieldContentsType(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag_ZF_Op, - ps_registersOp.copyRO(), new OPT_AddressConstantOperand(flagFref - .peekResolvedField().getOffset()), new OPT_LocationOperand( - flagFref), new OPT_TrueGuardOperand())); + ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(flagZFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(flagZFref), + new OPT_TrueGuardOperand())); } { OPT_RegisterOperand flag_OF_Op; @@ -575,14 +659,11 @@ } else { flag_OF_Op = new OPT_RegisterOperand(flag_OF, VM_TypeReference.Boolean); } - VM_FieldReference flagFref = VM_MemberReference.findOrCreate( - registersTref, VM_Atom.findOrCreateAsciiAtom("flag_OF"), - VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); - VM_TypeReference flagTref = flagFref.getFieldContentsType(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag_OF_Op, - ps_registersOp.copyRO(), new OPT_AddressConstantOperand(flagFref - .peekResolvedField().getOffset()), new OPT_LocationOperand( - flagFref), new OPT_TrueGuardOperand())); + ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(flagOFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(flagOFref), + new OPT_TrueGuardOperand())); } { OPT_RegisterOperand flag_DF_Op; @@ -592,14 +673,11 @@ } else { flag_DF_Op = new OPT_RegisterOperand(flag_DF, VM_TypeReference.Boolean); } - VM_FieldReference flagFref = VM_MemberReference.findOrCreate( - registersTref, VM_Atom.findOrCreateAsciiAtom("flag_DF"), - VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); - VM_TypeReference flagTref = flagFref.getFieldContentsType(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag_DF_Op, - ps_registersOp.copyRO(), new OPT_AddressConstantOperand(flagFref - .peekResolvedField().getOffset()), new OPT_LocationOperand( - flagFref), new OPT_TrueGuardOperand())); + ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(flagDFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(flagDFref), + new OPT_TrueGuardOperand())); } } @@ -608,9 +686,24 @@ * into the process space */ protected void spillAllRegisters() { + // spill segment registers + OPT_RegisterOperand ps_registers_segRegOp = + new OPT_RegisterOperand(ps_registers_segReg, segRegTref); + for (int i = 0; i < SegReg.length; i++) { + // We can save spills if the trace has no syscalls and the register was + // never used + if ((DBT_Options.singleInstrTranslation == false) + || (SegRegInUse[i] == true)) { + appendInstructionToCurrentBlock(AStore.create(SHORT_ASTORE, + new OPT_RegisterOperand(GP32[i], VM_TypeReference.Int), + ps_registers_segRegOp.copyRO(), new OPT_IntConstantOperand(i), + new OPT_LocationOperand(VM_TypeReference.Char), + new OPT_TrueGuardOperand())); + } + } // spill general purpose registers - OPT_RegisterOperand ps_registers_gp32Op = new OPT_RegisterOperand( - ps_registers_gp32, gp32Tref); + OPT_RegisterOperand ps_registers_gp32Op = + new OPT_RegisterOperand(ps_registers_gp32, gp32Tref); for (int i = 0; i < GP32.length; i++) { // We can save spills if the trace has no syscalls and the register was // never used @@ -624,67 +717,52 @@ } } // Spill flags - OPT_RegisterOperand ps_registersOp = new OPT_RegisterOperand(ps_registers, - registersTref); + OPT_RegisterOperand ps_registersOp = + new OPT_RegisterOperand(ps_registers, registersTref); { - OPT_RegisterOperand flag_CF_Op = new OPT_RegisterOperand(flag_CF, - VM_TypeReference.Boolean); - VM_FieldReference flagFref = VM_MemberReference.findOrCreate( - registersTref, VM_Atom.findOrCreateAsciiAtom("flag_CF"), - VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); - VM_TypeReference flagTref = flagFref.getFieldContentsType(); - appendInstructionToCurrentBlock(GetField.create(PUTFIELD, flag_CF_Op, - ps_registersOp, new OPT_AddressConstantOperand(flagFref - .peekResolvedField().getOffset()), new OPT_LocationOperand( - flagFref), new OPT_TrueGuardOperand())); + OPT_RegisterOperand flag_CF_Op = + new OPT_RegisterOperand(flag_CF, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(GetField.create(PUTFIELD, + flag_CF_Op, ps_registersOp, + new OPT_AddressConstantOperand(flagCFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(flagCFref), + new OPT_TrueGuardOperand())); } { OPT_RegisterOperand flag_SF_Op = new OPT_RegisterOperand(flag_SF, VM_TypeReference.Boolean); - VM_FieldReference flagFref = VM_MemberReference.findOrCreate( - registersTref, VM_Atom.findOrCreateAsciiAtom("flag_SF"), - VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); - VM_TypeReference flagTref = flagFref.getFieldContentsType(); - appendInstructionToCurrentBlock(GetField.create(PUTFIELD, flag_SF_Op, - ps_registersOp.copyRO(), new OPT_AddressConstantOperand(flagFref - .peekResolvedField().getOffset()), new OPT_LocationOperand( - flagFref), new OPT_TrueGuardOperand())); + appendInstructionToCurrentBlock(GetField.create(PUTFIELD, + flag_SF_Op, ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(flagSFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(flagSFref), + new OPT_TrueGuardOperand())); } { - OPT_RegisterOperand flag_ZF_Op = new OPT_RegisterOperand(flag_ZF, - VM_TypeReference.Boolean); - VM_FieldReference flagFref = VM_MemberReference.findOrCreate( - registersTref, VM_Atom.findOrCreateAsciiAtom("flag_ZF"), - VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); - VM_TypeReference flagTref = flagFref.getFieldContentsType(); - appendInstructionToCurrentBlock(GetField.create(PUTFIELD, flag_ZF_Op, - ps_registersOp.copyRO(), new OPT_AddressConstantOperand(flagFref - .peekResolvedField().getOffset()), new OPT_LocationOperand( - flagFref), new OPT_TrueGuardOperand())); + OPT_RegisterOperand flag_ZF_Op = + new OPT_RegisterOperand(flag_ZF, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(GetField.create(PUTFIELD, + flag_ZF_Op, ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(flagZFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(flagZFref), + new OPT_TrueGuardOperand())); } { - OPT_RegisterOperand flag_OF_Op = new OPT_RegisterOperand(flag_OF, - VM_TypeReference.Boolean); - VM_FieldReference flagFref = VM_MemberReference.findOrCreate( - registersTref, VM_Atom.findOrCreateAsciiAtom("flag_OF"), - VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); - VM_TypeReference flagTref = flagFref.getFieldContentsType(); - appendInstructionToCurrentBlock(GetField.create(PUTFIELD, flag_OF_Op, - ps_registersOp, new OPT_AddressConstantOperand(flagFref - .peekResolvedField().getOffset()), new OPT_LocationOperand( - flagFref), new OPT_TrueGuardOperand())); + OPT_RegisterOperand flag_OF_Op = + new OPT_RegisterOperand(flag_OF, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(GetField.create(PUTFIELD, + flag_OF_Op, ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(flagOFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(flagOFref), + new OPT_TrueGuardOperand())); } { - OPT_RegisterOperand flag_DF_Op = new OPT_RegisterOperand(flag_DF, - VM_TypeReference.Boolean); - VM_FieldReference flagFref = VM_MemberReference.findOrCreate( - registersTref, VM_Atom.findOrCreateAsciiAtom("flag_DF"), - VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); - VM_TypeReference flagTref = flagFref.getFieldContentsType(); - appendInstructionToCurrentBlock(GetField.create(PUTFIELD, flag_DF_Op, - ps_registersOp, new OPT_AddressConstantOperand(flagFref - .peekResolvedField().getOffset()), new OPT_LocationOperand( - flagFref), new OPT_TrueGuardOperand())); + OPT_RegisterOperand flag_DF_Op = + new OPT_RegisterOperand(flag_DF, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(GetField.create(PUTFIELD, + flag_DF_Op, ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(flagDFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(flagDFref), + new OPT_TrueGuardOperand())); } } @@ -713,8 +791,14 @@ * Return an array of unused registers */ protected OPT_Register[] getUnusedRegisters() { - ArrayList unusedRegisterList = new ArrayList(); + ArrayList<OPT_Register> unusedRegisterList = new ArrayList<OPT_Register>(); // Add general purpose registers + for (int i = 0; i < SegRegInUse.length; i++) { + if (SegRegInUse[i] == false) { + unusedRegisterList.add(SegReg[i]); + } + } + // Add general purpose registers for (int i = 0; i < GP32InUse.length; i++) { if (GP32InUse[i] == false) { unusedRegisterList.add(GP32[i]); @@ -736,7 +820,7 @@ if (flag_OF_InUse == false) { unusedRegisterList.add(flag_OF); } - return (OPT_Register[]) unusedRegisterList - .toArray(new OPT_Register[unusedRegisterList.size()]); + return unusedRegisterList.toArray( + new OPT_Register[unusedRegisterList.size()]); } } Modified: src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java 2007-04-23 21:57:27 UTC (rev 88) +++ src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java 2007-04-23 22:12:34 UTC (rev 89) @@ -49,6 +49,13 @@ } /** + * Get a decoded operand for a segment register + */ + static X86_DecodedOperand getSegmentRegister(int reg) { + return new X86_SegRegDecodedOperand(reg); + } + + /** * Get a memory reference to the stack */ static X86_DecodedOperand getStack(int addressSize, int operandSize) { @@ -160,6 +167,50 @@ } /** + * Segment Registers + */ +final class X86_SegRegDecodedOperand extends X86_DecodedOperand { + /** + * The register in question + */ + final int reg; + + /** + * Constructor + */ + X86_SegRegDecodedOperand(int reg) { + this.reg = reg; + } + + /** + * Read the value into a register + */ + void readToRegister(X862IR translationHelper, X86_Laziness lazy, + OPT_RegisterOperand op) { + translationHelper.appendInstructionToCurrentBlock(Move.create(INT_MOVE, op, + translationHelper.getSegRegister(lazy, reg))); + } + + /** + * Write the given operand to this + */ + void writeValue(X862IR translationHelper, X86_Laziness lazy, + OPT_RegisterOperand op) { + OPT_RegisterOperand result = translationHelper.getSegRegister(lazy, reg); + translationHelper.appendInstructionToCurrentBlock(Move.create(INT_MOVE, + result, op)); + } + + /** + * Read the value as giving an address + */ + void readEffectiveAddress(X862IR translationHelper, X86_Laziness lazy, + OPT_RegisterOperand op) { + throw new Error("Trying to read the address of a register!"); + } +} + +/** * Memory */ final class X86_MemDecodedOperand extends X86_DecodedOperand { Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-23 21:57:27 UTC (rev 88) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-23 22:12:34 UTC (rev 89) @@ -328,22 +328,17 @@ /* 0x7E */new X86_Jcc_OpcodeDecoder(LESS_EQUAL, 8), /* 0x7F */new X86_Jcc_OpcodeDecoder(GREATER, 8), - /* 0x80 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] {// 8bit, - // ModRM, - // 8bit - // imm, - // rm - // is - // dest - new X86_Add_OpcodeDecoder(8, true, 8, true),// 0 - new X86_Or_OpcodeDecoder(8, true, 8, true),// 1 - new X86_Adc_OpcodeDecoder(8, true, 8, true),// 2 - new X86_Sbb_OpcodeDecoder(8, true, 8, true),// 3 - new X86_And_OpcodeDecoder(8, true, 8, true),// 4 - new X86_Sub_OpcodeDecoder(8, true, 8, true),// 5 - new X86_Xor_OpcodeDecoder(8, true, 8, true),// 6 - new X86_Cmp_OpcodeDecoder(8, true, 8, true) // 7 - }), + /* 0x80 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { + // 8bit, ModRM, 8bit imm, rm is dest + new X86_Add_OpcodeDecoder(8, true, 8, true),// 0 + new X86_Or_OpcodeDecoder(8, true, 8, true),// 1 + new X86_Adc_OpcodeDecoder(8, true, 8, true),// 2 + new X86_Sbb_OpcodeDecoder(8, true, 8, true),// 3 + new X86_And_OpcodeDecoder(8, true, 8, true),// 4 + new X86_Sub_OpcodeDecoder(8, true, 8, true),// 5 + new X86_Xor_OpcodeDecoder(8, true, 8, true),// 6 + new X86_Cmp_OpcodeDecoder(8, true, 8, true) // 7 + }), /* 0x81 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { // 16/32bit, ModRM, 16/32bit imm, rm is dest new X86_Add_OpcodeDecoder(_16BIT?16:32, true, _16BIT?16:32, true),// 0 @@ -358,46 +353,34 @@ /* 0x82 */null, /* 0x83 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { // 16/32bit, ModRM, 8bit imm, rm is dest - new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 0 - new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 1 - new X86_Adc_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 2 - new X86_Sbb_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 3 - new X86_And_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 4 - new X86_Sub_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 5 - new X86_Xor_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 6 - new X86_Cmp_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true) // 7 - }), - /* 0x84 */new X86_Test_OpcodeDecoder(8, true, 0), // 8bit, has ModRM, no - // imm - /* 0x85 */new X86_Test_OpcodeDecoder(_16BIT ? 16 : 32, true, 0), // 16/32bit,has - // ModRM, - // no - // imm + new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 0 + new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 1 + new X86_Adc_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 2 + new X86_Sbb_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 3 + new X86_And_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 4 + new X86_Sub_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 5 + new X86_Xor_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 6 + new X86_Cmp_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true) // 7 + }), + /* 0x84 */new X86_Test_OpcodeDecoder(8, true, 0), + // 8bit, has ModRM, no imm + /* 0x85 */new X86_Test_OpcodeDecoder(_16BIT ? 16 : 32, true, 0), + // 16/32bit,has ModRM, no imm /* 0x86 */null, /* 0x87 */null, - /* 0x88 */new X86_Mov_OpcodeDecoder(8, true, 0, true), // 8bit, has - // ModRM, no imm, - // rm is dest - /* 0x89 */new X86_Mov_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // dest - /* 0x8A */new X86_Mov_OpcodeDecoder(8, true, 0, false),// 8bit, has - // ModRM, no imm, - // rm is src - /* 0x8B */new X86_Mov_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false),// 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // src - /* 0x8C */null, + /* 0x88 */new X86_Mov_OpcodeDecoder(8, true, 0, true), + // 8bit, has ModRM, no imm, rm is dest + /* 0x89 */new X86_Mov_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), + // 16/32bit,has ModRM, no imm, rm is dest + /* 0x8A */new X86_Mov_OpcodeDecoder(8, true, 0, false), + // 8bit, has ModRM, no imm, rm is src + /* 0x8B */new X86_Mov_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false), + // 16/32bit,has ModRM, no imm, rm is src + /* 0x8C */new X86_MovSeg_OpcodeDecoder(true), + // move Sreg to r/m /* 0x8D */new X86_Lea_OpcodeDecoder(), - /* 0x8E */null, + /* 0x8E */new X86_MovSeg_OpcodeDecoder(false), + // move r/m to Sreg /* 0x8F */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { new X86_Pop_OpcodeDecoder(-1), // 0 - Pop of memory operand null, // 1 @@ -447,30 +430,24 @@ /* 0xAE */null, /* 0xAF */null, - /* 0xB0 */new X86_Mov_OpcodeDecoder(0, 8), // reg, 8bit immediate - /* 0xB1 */new X86_Mov_OpcodeDecoder(1, 8), // reg, 8bit immediate - /* 0xB2 */new X86_Mov_OpcodeDecoder(2, 8), // reg, 8bit immediate - /* 0xB3 */new X86_Mov_OpcodeDecoder(3, 8), // reg, 8bit immediate - /* 0xB4 */new X86_Mov_OpcodeDecoder(4, 8), // reg, 8bit immediate - /* 0xB5 */new X86_Mov_OpcodeDecoder(5, 8), // reg, 8bit immediate - /* 0xB6 */new X86_Mov_OpcodeDecoder(6, 8), // reg, 8bit immediate - /* 0xB7 */new X86_Mov_OpcodeDecoder(7, 8), // reg, 8bit immediate - /* 0xB8 */new X86_Mov_OpcodeDecoder(0, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate - /* 0xB9 */new X86_Mov_OpcodeDecoder(1, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate - /* 0xBA */new X86_Mov_OpcodeDecoder(2, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate - /* 0xBB */new X86_Mov_OpcodeDecoder(3, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate - /* 0xBC */new X86_Mov_OpcodeDecoder(4, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate - /* 0xBD */new X86_Mov_OpcodeDecoder(5, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate - /* 0xBE */new X86_Mov_OpcodeDecoder(6, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate - /* 0xBF */new X86_Mov_OpcodeDecoder(7, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate + // reg, 8bit immediate + /* 0xB0 */new X86_Mov_OpcodeDecoder(0, 8), + /* 0xB1 */new X86_Mov_OpcodeDecoder(1, 8), + /* 0xB2 */new X86_Mov_OpcodeDecoder(2, 8), + /* 0xB3 */new X86_Mov_OpcodeDecoder(3, 8), + /* 0xB4 */new X86_Mov_OpcodeDecoder(4, 8), + /* 0xB5 */new X86_Mov_OpcodeDecoder(5, 8), + /* 0xB6 */new X86_Mov_OpcodeDecoder(6, 8), + /* 0xB7 */new X86_Mov_OpcodeDecoder(7, 8), + // reg, 16/32bit immediate + /* 0xB8 */new X86_Mov_OpcodeDecoder(0, _16BIT ? 16 : 32), + /* 0xB9 */new X86_Mov_OpcodeDecoder(1, _16BIT ? 16 : 32), + /* 0xBA */new X86_Mov_OpcodeDecoder(2, _16BIT ? 16 : 32), + /* 0xBB */new X86_Mov_OpcodeDecoder(3, _16BIT ? 16 : 32), + /* 0xBC */new X86_Mov_OpcodeDecoder(4, _16BIT ? 16 : 32), + /* 0xBD */new X86_Mov_OpcodeDecoder(5, _16BIT ? 16 : 32), + /* 0xBE */new X86_Mov_OpcodeDecoder(6, _16BIT ? 16 : 32), + /* 0xBF */new X86_Mov_OpcodeDecoder(7, _16BIT ? 16 : 32), /* 0xC0 */null, /* 0xC1 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { @@ -478,45 +455,30 @@ null, // 1 null, // 2 null, // 3 - new X86_Shl_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true), // 4 - - // 16/32bit, - // has - // ModRM, - // 8bit - // imm, rm - // is dest - new X86_Ushr_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 5 - - // 16/32bit, - // has - // ModRM, - // 8bit - // imm, rm - // is dest + new X86_Shl_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true), + // 4 - 16/32bit, has ModRM, 8bit imm, rm is dest + new X86_Ushr_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true), + // 5 - 16/32bit, has ModRM, 8bit imm, rm is dest null, // 6 - new X86_Shr_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true) // 7 - - // 16/32bit, - // has - // ModRM, - // 8bit - // imm, rm - // is dest + new X86_Shr_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true) + // 7 - 16/32bit, has ModRM, 8bit imm, rm is dest }), - /* 0xC2 */new X86_Ret_OpcodeDecoder(false, 16), // near return, 16bit - // immediate - /* 0xC3 */new X86_Ret_OpcodeDecoder(false, 0), // near return, no - // immediate + /* 0xC2 */new X86_Ret_OpcodeDecoder(false, 16), + // near return, 16bit immediate + /* 0xC3 */new X86_Ret_OpcodeDecoder(false, 0), + // near return, no immediate /* 0xC4 */null, /* 0xC5 */null, - /* 0xC6 */new X86_Mov_OpcodeDecoder(8, true, 8, true), // 8bit, has - // ModRM, 8bit - // imm, rm is dest + /* 0xC6 */new X86_Mov_OpcodeDecoder(8, true, 8, true), + // 8bit, has ModRM, 8bit imm, rm is dest /* 0xC7 */new X86_Mov_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 : 32, true), // 16/32bit, has ModRM, 16/32bit imm, rm is dest /* 0xC8 */null, /* 0xC9 */new X86_Leave_OpcodeDecoder(), - /* 0xCA */new X86_Ret_OpcodeDecoder(true, 16), // far return, 16bit - // immediate - /* 0xCB */new X86_Ret_OpcodeDecoder(true, 0), // far return, no immediate + /* 0xCA */new X86_Ret_OpcodeDecoder(true, 16), + // far return, 16bit immediate + /* 0xCB */new X86_Ret_OpcodeDecoder(true, 0), + // far return, no immediate /* 0xCC */null, /* 0xCD */new X86_Int_OpcodeDecoder(), /* 0xCE */null, @@ -2483,7 +2445,118 @@ return "mov"; } } +/** + * The decoder for the Mov opcode + */ +class X86_MovSeg_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * Constructor, {@see X86_OpcodeDecoder} + */ + X86_MovSeg_OpcodeDecoder(boolean isMemoryOperandDestination) { + super(X86_64 ? 64 : 16, true, 0, isMemoryOperandDestination); + } + /** + * Perform the actual translation + * @param translationHelper + * @param ps + * @param lazy + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected int translate(X862IR translationHelper, ProcessSpace ps, + X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, + int displacement, int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int operandSize = this.operandSize; + int addressSize; + if (prefix4 == null) { + addressSize = _16BIT ? 16 : 32; + } else { + addressSize = _16BIT ? 32 : 16; + } + X86_DecodedOperand destination; + X86_DecodedOperand source = null; + if (isMemoryOperandDestination) { + destination = modrm.getRM(translationHelper, lazy, sib, displacement, + operandSize, addressSize, (prefix2 != null) ? prefix2.getSegment() + : X86_Registers.DS); + source = modrm.getSReg(); + } else { + destination = modrm.getSReg(); + source = modrm.getRM(translationHelper, lazy, sib, displacement, + operandSize, addressSize, (prefix2 != null) ? prefix2.getSegment() + : X86_Registers.DS); + } + + OPT_RegisterOperand temp = translationHelper.getTempInt(0); + OPT_RegisterOperand sourceOp1 = translationHelper.getTempInt(1); + source.readToRegister(translationHelper, lazy, sourceOp1); + translationHelper.appendInstructionToCurrentBlock(Move.create(INT_MOVE, + temp, sourceOp1.copyRO())); + destination.writeValue(translationHelper, lazy, temp.copyRO()); + return pc + length; + } + + /** + * Disassemble the opcode + * @param ps + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immedate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected String disassemble(ProcessSpace ps, int pc, + X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, int displacement, + int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int operandSize; + if (prefix3 == null) { + operandSize = this.operandSize; + } else if (this.operandSize == 32) { + operandSize = 16; + } else { + operandSize = 32; + } + char addressPrefix; + if (prefix4 == null) { + addressPrefix = _16BIT ? ' ' : 'e'; + } else { + addressPrefix = _16BIT ? 'e' : ' '; + } + // TODO: apply segment override + switch (operandSize) { + case 8: + return "movsb es:" + addressPrefix + "di, ds:" + addressPrefix + "si"; + case 16: + return "movsw es:" + addressPrefix + "di, ds:" + addressPrefix + "si"; + case 32: + return "movsd es:" + addressPrefix + "di, ds:" + addressPrefix + "si"; + default: + DBT_OptimizingCompilerException.UNREACHABLE(); + return "error"; + } + } +} + /** * The decoder for the Movs opcode */ Modified: src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java 2007-04-23 21:57:27 UTC (rev 88) +++ src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java 2007-04-23 22:12:34 UTC (rev 89) @@ -466,6 +466,13 @@ } /** + * Get the segment reg field as a decoded operand + */ + X86_DecodedOperand getSReg() { + return X86_DecodedOperand.getSegmentRegister(reg); + } + + /** * Get the reg/opcode field as an integer */ int getOpcode() { Modified: src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java 2007-04-23 21:57:27 UTC (rev 88) +++ src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java 2007-04-23 22:12:34 UTC (rev 89) @@ -40,6 +40,7 @@ systemCallTable[202] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[221] = new LinuxSystemCalls.SysFcntl64(); systemCallTable[252] = new LinuxSystemCalls.SysExitGroup(); + systemCallTable[243] = new LinuxSystemCalls.NullSystemCall(); } /** * The machine for this system given by uname Modified: src/org/binarytranslator/arch/x86/os/process/X86_Registers.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_Registers.java 2007-04-23 21:57:27 UTC (rev 88) +++ src/org/binarytranslator/arch/x86/os/process/X86_Registers.java 2007-04-23 22:12:34 UTC (rev 89) @@ -56,24 +56,24 @@ /** * Translate a register number into its 32bit string variant */ - private static final String name64[] = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}; + private static final String[] name64 = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}; /** * Translate a register number into its 32bit string variant */ - private static final String name32[] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}; + private static final String[] name32 = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}; /** * Translate a register number into its 16bit string variant */ - private static final String name16[] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"}; + private static final String[] name16 = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"}; /** * Translate a register number into its 32bit string variant */ - private static final String name8[] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}; + private static final String[] name8 = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}; /** * Array holding the 8 32bit versions of the registers */ - private int gp32[] = new int[8]; + private int[] gp32 = new int[8]; /** * The instruction pointer register @@ -83,7 +83,7 @@ /** * Array holding the 6 segment registers */ - private short segmentRegister[] = new short[6]; + private char[] segmentRegister = new char[6]; /* * Flags @@ -405,13 +405,13 @@ /** * Read 16 bit segment */ - public short readSeg(int reg) { + public char readSeg(int reg) { return segmentRegister[reg]; } /** * Write a segment register value */ - public void writeSeg(int reg, short val) { + public void writeSeg(int reg, char val) { segmentRegister[reg] = val; } /** Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-23 21:57:27 UTC (rev 88) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-23 22:12:34 UTC (rev 89) @@ -457,13 +457,15 @@ * Class capturing file control (fcntl) constants */ private final static class fcntl { - public final static int O_RDONLY=0x0; - public final static int O_WRONLY=0x1; - public final static int O_RDWR =0x2; - public final static int O_CREAT =0x40; - public final static int O_EXCL =0x80; - public final static int O_TRUNC =0x200; - public final static int O_APPEND=0x400; + public final static int O_RDONLY = 0; + public final static int O_WRONLY = 1; + public final static int O_RDWR = 2; + public final static int O_CREAT = 0100; + public final static int O_EXCL = 0200; + public final static int O_NOCTTY = 0400; + public final static int O_TRUNC = 01000; + public final static int O_APPEND = 02000; + public final static int O_NONBLOCK = 04000; } /** @@ -512,6 +514,18 @@ } /** + * Null System Call - do nothing just return 0 + */ + public class NullSystemCall extends SystemCall { + /** + * Handle a system call + */ + public void doSysCall() { + src.setSysCallReturn(0); + } + } + + /** * Exit system call */ public class SysExit extends SystemCall { @@ -635,6 +649,7 @@ Memory mem = src.getProcessSpace().memory; if((fd == 1)||(fd == 2)) { // stdout || stderr + PrintStream out = (fd == 1) ? System.out : System.err; int base = mem.load32(vector); int len = mem.load32(vector+4); int currentVector = 0; @@ -646,12 +661,31 @@ len = mem.load32(vector+(currentVector*8)+4); curVectorPos = 0; } - System.out.print((char) mem.loadUnsigned8(base + curVectorPos)); + out.print((char) mem.loadUnsigned8(base + curVectorPos)); curVectorPos++; } src.setSysCallReturn(count); } else { - throw new Error("TODO: "+ fd); + try { + RandomAccessFile out = getRAFile(fd); + int base = mem.load32(vector); + int len = mem.load32(vector+4); + int currentVector = 0; + int curVectorPos = 0; + for(int c = 0 ; c < count; c++) { + if(curVectorPos == len) { + currentVector++; + base = mem.load32(vector+(currentVector*8)); + len = mem.load32(vector+(currentVector*8)+4); + curVectorPos = 0; + } + out.write((int)mem.loadUnsigned8(base + curVectorPos)); + curVectorPos++; + } + src.setSysCallReturn(count); + } catch(IOException e) { + throw new Error("TODO - set error correctly", e); + } } } } @@ -699,8 +733,12 @@ } // NOT YET HANDLING ALL THE flags OPTIONS (IW have included // TRUNC & APPEND but not properly!) - if((flags & ~(fcntl.O_WRONLY | fcntl.O_RDWR | fcntl.O_CREAT | fcntl.O_EXCL | fcntl.O_TRUNC | fcntl.O_APPEND)) != 0) - throw new Error("Not yet implemented option to sys_open. " + Integer.toString(flags,8)); + if((flags & ~(fcntl.O_WRONLY | fcntl.O_RDWR | fcntl.O_CREAT | fcntl.O_EXCL | fcntl.O_TRUNC | + fcntl.O_APPEND | fcntl.O_NOCTTY | fcntl.O_NONBLOCK)) != 0) { + throw new Error("Not yet implemented option to sys_open. 0" + Integer.toString(flags,8) + + " flag 0" + Integer.toString(flags & ~(fcntl.O_WRONLY | fcntl.O_RDWR | fcntl.O_CREAT | + fcntl.O_EXCL | fcntl.O_TRUNC | fcntl.O_APPEND | fcntl.O_NOCTTY | fcntl.O_NONBLOCK),8)); + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-24 23:01:36
|
Revision: 91 http://svn.sourceforge.net/pearcolator/?rev=91&view=rev Author: captain5050 Date: 2007-04-24 16:01:32 -0700 (Tue, 24 Apr 2007) Log Message: ----------- IA32 implementation of set_thread_area, support for ld/st mxcsr, various other improvements. Running crashes as IA32 interpreter controller not yet implemented. Modified Paths: -------------- src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java src/org/binarytranslator/arch/x86/os/process/X86_Registers.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Modified: src/org/binarytranslator/arch/x86/decoder/X862IR.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-24 18:16:44 UTC (rev 90) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-24 23:01:32 UTC (rev 91) @@ -39,7 +39,8 @@ private static final VM_FieldReference flagZFref; private static final VM_FieldReference flagOFref; private static final VM_FieldReference flagDFref; - + private static final VM_FieldReference gsBaseAddrFref; + private static final VM_FieldReference mxcsrFref; static { psTref = VM_TypeReference.findOrCreate( VM_BootstrapClassLoader.getBootstrapClassLoader(), @@ -86,8 +87,16 @@ flagDFref = VM_MemberReference.findOrCreate( registersTref, VM_Atom.findOrCreateAsciiAtom("flag_DF"), VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); - } + gsBaseAddrFref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("gsBaseAddr"), + VM_Atom.findOrCreateAsciiAtom("I")).asFieldReference(); + + mxcsrFref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("mxcsr"), + VM_Atom.findOrCreateAsciiAtom("I")).asFieldReference(); + } + /** * Constructor */ @@ -110,11 +119,8 @@ /** * Translate the instruction at the given pc - * - * @param lazy - * the status of the lazy evaluation - * @param pc - * the program counter for the instruction + * @param lazy the status of the lazy evaluation + * @param pc the program counter for the instruction * @return the next instruction address or -1 */ protected int translateInstruction(Laziness lazy, int pc) { @@ -203,11 +209,8 @@ /** * Resolve a 32bit register - * - * @param laziness - * the lazy state, used to determine register mangling - * @param r - * the register to resolve + * @param laziness the lazy state, used to determine register mangling + * @param r the register to resolve */ private void resolveGPRegister32(X86_Laziness laziness, int r) { if (laziness.is32bitRegisterValid(r) == false) { @@ -250,11 +253,8 @@ /** * Read a 32bit register - * - * @param laziness - * the lazy state, used to determine register mangling - * @param r - * the register to read + * @param laziness the lazy state, used to determine register mangling + * @param r the register to read */ public OPT_RegisterOperand getSegRegister(X86_Laziness laziness, int r) { SegRegInUse[r] = true; @@ -262,12 +262,34 @@ } /** + * Add a segment base address to the given address + * @param segment segment to get base address for + * @param address the address to add the value onto + */ + public void addSegmentBaseAddress(int segment, OPT_RegisterOperand address) { + switch(segment) { + case X86_Registers.GS: { + OPT_RegisterOperand temp = getTempInt(9); + appendInstructionToCurrentBlock(GetField.create(GETFIELD, + temp, new OPT_RegisterOperand(ps_registers, registersTref), + new OPT_AddressConstantOperand(gsBaseAddrFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(gsBaseAddrFref), + new OPT_TrueGuardOperand())); + appendInstructionToCurrentBlock(Binary.create(INT_ADD, + address.copyRO(), address.copyRO(), temp.copyRO())); + break; + } + case X86_Registers.FS: + throw new Error("Unhandled segment override FS"); + default: + break; + } + } + + /** * Read a 32bit register - * - * @param laziness - * the lazy state, used to determine register mangling - * @param r - * the register to read + * @param laziness the lazy state, used to determine register mangling + * @param r the register to read */ public OPT_RegisterOperand getGPRegister32(X86_Laziness laziness, int r) { GP32InUse[r] = true; @@ -277,11 +299,8 @@ /** * Read a 16bit register - * - * @param laziness - * the lazy state, used to determine register mangling - * @param r - * the register to read + * @param laziness the lazy state, used to determine register mangling + * @param r the register to read */ public OPT_RegisterOperand getGPRegister16(X86_Laziness laziness, int r) { GP32InUse[r] = true; @@ -324,11 +343,8 @@ /** * Read a 8bit register - * - * @param laziness - * the lazy state, used to determine register mangling - * @param r - * the register to read + * @param laziness the lazy state, used to determine register mangling + * @param r the register to read */ public OPT_RegisterOperand getGPRegister8(X86_Laziness laziness, int r) { int rl, rh; // low and high 8bit registers @@ -375,11 +391,8 @@ /** * Read a 8bit register - * - * @param laziness - * the lazy state, used to determine register mangling - * @param r - * the register to read + * @param laziness the lazy state, used to determine register mangling + * @param r the register to read */ public OPT_RegisterOperand getGPRegister(X86_Laziness laziness, int r, int size) { @@ -396,6 +409,14 @@ } } + /** + * Read the MXCSR register + */ + public OPT_RegisterOperand getMXCSR() { + ps_registers_mxcsr_InUse = true; + return new OPT_RegisterOperand(ps_registers_mxcsr, VM_TypeReference.Int); + } + // -- status flags /** * X86 flag register constituants - bit 0 - CF or carry flag @@ -537,6 +558,16 @@ private OPT_Register ps_registers_gp32; /** + * X87 mxcsr register + */ + private OPT_Register ps_registers_mxcsr; + + /** + * Was the register used during the trace? + */ + private boolean ps_registers_mxcsr_InUse; + + /** * Fill all the registers from the ProcessSpace, that is take the register * values from the process space and place them in the traces registers. */ @@ -608,6 +639,21 @@ new OPT_LocationOperand(VM_TypeReference.Int), new OPT_TrueGuardOperand())); } + // Fill MXCSR + { + OPT_RegisterOperand ps_registers_mxcsr_Op; + if (ps_registers_mxcsr == null) { + ps_registers_mxcsr_Op = makeTemp(VM_TypeReference.Int); + ps_registers_mxcsr = ps_registers_mxcsr_Op.register; + } else { + ps_registers_mxcsr_Op = new OPT_RegisterOperand(flag_CF, VM_TypeReference.Boolean); + } + appendInstructionToCurrentBlock(GetField.create(GETFIELD, ps_registers_mxcsr_Op, + ps_registersOp.copyRO(), + new OPT_AddressConstantOperand(mxcsrFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(mxcsrFref), + new OPT_TrueGuardOperand())); + } // Fill flags { OPT_RegisterOperand flag_CF_Op; @@ -716,14 +762,25 @@ new OPT_TrueGuardOperand())); } } - // Spill flags OPT_RegisterOperand ps_registersOp = new OPT_RegisterOperand(ps_registers, registersTref); + // Spill mxcsr { + OPT_RegisterOperand ps_registers_mxcsr_Op = + new OPT_RegisterOperand(ps_registers_mxcsr, VM_TypeReference.Int); + appendInstructionToCurrentBlock(GetField.create(PUTFIELD, + ps_registers_mxcsr_Op, ps_registersOp, + new OPT_AddressConstantOperand(mxcsrFref.peekResolvedField().getOffset()), + new OPT_LocationOperand(mxcsrFref), + new OPT_TrueGuardOperand())); + } + + // Spill flags + { OPT_RegisterOperand flag_CF_Op = new OPT_RegisterOperand(flag_CF, VM_TypeReference.Boolean); appendInstructionToCurrentBlock(GetField.create(PUTFIELD, - flag_CF_Op, ps_registersOp, + flag_CF_Op, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(flagCFref.peekResolvedField().getOffset()), new OPT_LocationOperand(flagCFref), new OPT_TrueGuardOperand())); @@ -777,9 +834,7 @@ /** * Plant instructions modifying a lazy state into one with no laziness - * - * @param laziness - * the laziness to modify + * @param laziness the laziness to modify */ public void resolveLaziness(Laziness laziness) { for (int i = 0; i < GP32.length; i++) { @@ -807,6 +862,10 @@ // ignore GP16 and GP8 registers as they are only created lazily, // and so must be in use + // Add MXCSR + if (ps_registers_mxcsr_InUse == false) { + unusedRegisterList.add(ps_registers_mxcsr); + } // Add flags if (flag_CF_InUse == false) { unusedRegisterList.add(flag_CF); Modified: src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java 2007-04-24 18:16:44 UTC (rev 90) +++ src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java 2007-04-24 23:01:32 UTC (rev 91) @@ -248,7 +248,7 @@ * The size of the operand */ final int operandSize; - + /** * Constructor */ @@ -271,11 +271,7 @@ this.base = base; this.scale = scale; this.index = index; - if (segment == X86_Registers.GS){ - this.displacement = displacement + 0xffffe000; - } else { - this.displacement = displacement; - } + this.displacement = displacement; this.addressSize = addressSize; this.operandSize = operandSize; } @@ -285,7 +281,7 @@ */ void readToRegister(X862IR translationHelper, X86_Laziness lazy, OPT_RegisterOperand op) { - OPT_RegisterOperand address = translationHelper.getTempInt(9); + OPT_RegisterOperand address = translationHelper.getTempInt(8); readEffectiveAddress(translationHelper, lazy, address); // Perform the load switch (operandSize) { @@ -308,7 +304,7 @@ */ void writeValue(X862IR translationHelper, X86_Laziness lazy, OPT_RegisterOperand op) { - OPT_RegisterOperand address = translationHelper.getTempInt(9); + OPT_RegisterOperand address = translationHelper.getTempInt(8); readEffectiveAddress(translationHelper, lazy, address); // Perform the store switch (operandSize) { @@ -356,5 +352,7 @@ address.copyRO(), address.copyRO(), new OPT_IntConstantOperand( displacement))); } + // Add on any base address from a segment override + translationHelper.addSegmentBaseAddress(segment, address); } } Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-24 18:16:44 UTC (rev 90) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-24 23:01:32 UTC (rev 91) @@ -127,8 +127,10 @@ /* 0x15 */null, /* 0x16 */null, /* 0x17 */null, - /* 0x18 */null, - /* 0x19 */null, + /* 0x18 */new X86_Sbb_OpcodeDecoder(8, true, 0, true), + // 8bit, has ModRM, no imm, rm is dest + /* 0x19 */new X86_Sbb_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), + // 16/32bit, has ModRM, no imm, rm is dest /* 0x1A */null, /* 0x1B */null, /* 0x1C */null, @@ -136,28 +138,16 @@ /* 0x1E */null, /* 0x1F */null, - /* 0x20 */new X86_And_OpcodeDecoder(8, true, 0, true), // 8bit, has - // ModRM, no imm, - // rm is dest - /* 0x21 */new X86_And_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // dest - /* 0x22 */new X86_And_OpcodeDecoder(8, true, 0, false),// 8bit, has - // ModRM, no imm, - // rm is src - /* 0x23 */new X86_And_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false),// 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // src - /* 0x24 */new X86_And_OpcodeDecoder(8, false, 8, false),// 8bit, no ModRM, - // 8bit imm + /* 0x20 */new X86_And_OpcodeDecoder(8, true, 0, true), + // 8bit, has ModRM, no imm, rm is dest + /* 0x21 */new X86_And_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), + // 16/32bit, has ModRM, no imm, rm is dest + /* 0x22 */new X86_And_OpcodeDecoder(8, true, 0, false), + // 8bit, has ModRM, no imm, rm is src + /* 0x23 */new X86_And_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false), + // 16/32bit, has ModRM, no imm, rm is src + /* 0x24 */new X86_And_OpcodeDecoder(8, false, 8, false), + // 8bit, no ModRM, 8bit imm /* 0x25 */new X86_And_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT ? 16 : 32, false),// 16/32bit, no ModRM, 16/32bit imm /* 0x26 */new X86_ES_SegmentOverride_PrefixDecoder(), @@ -303,9 +293,9 @@ /* 0x67 */new X86_AddressSizeOverride_PrefixDecoder(), /* 0x68 */new X86_Push_OpcodeDecoder(_16BIT ? -16 : -32), // Push 16/32bit // immediate - /* 0x69 */null, + /* 0x69 */new X86_Imul_OpcodeDecoder(_16BIT ? 16 : 32, _16BIT ? 16 : 32, false), /* 0x6A */new X86_Push_OpcodeDecoder(-8), // Push 8bit immediate - /* 0x6B */null, + /* 0x6B */new X86_Imul_OpcodeDecoder(_16BIT ? 16 : 32, 8, false), /* 0x6C */null, /* 0x6D */null, /* 0x6E */null, @@ -1919,7 +1909,7 @@ /** * Look up table to find secondary opcode translator */ - private static final X86_OpcodeDecoder[] secondaryOpcodes = { + private static final X86_InstructionDecoder[] secondaryOpcodes = { /* 0x00 */null, /* 0x01 */null, /* 0x02 */null, @@ -2104,12 +2094,21 @@ /* 0xAB */null, /* 0xAC */null, /* 0xAD */null, - /* 0xAE */null, + /* 0xAE */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { + null,// 0 + null,// 1 + new X86_LdMXCSR_OpcodeDecoder(),// 2 + new X86_StMXCSR_OpcodeDecoder(),// 3 + null,// 4 + null,// 5 + null,// 6 + null // 7 + }), /* 0xAF */new X86_Imul_OpcodeDecoder(_16BIT ? 16 : 32, 0, false), // 16/32bit, no imm, not edx:eax - /* 0xB0 */null, - /* 0xB1 */null, + /* 0xB0 */new X86_CmpXChg_OpcodeDecoder(8), + /* 0xB1 */new X86_CmpXChg_OpcodeDecoder(_16BIT ? 16 : 32), /* 0xB2 */null, /* 0xB3 */null, /* 0xB4 */null, @@ -2406,6 +2405,93 @@ } /** + * The decoder for the Cmp opcode + */ +class X86_CmpXChg_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * Constructor, {@see X86_OpcodeDecoder} + */ + X86_CmpXChg_OpcodeDecoder(int size) { + super(size, true, 0, true); + } + + /** + * Perform the actual translation + * @param translationHelper + * @param ps + * @param lazy + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected int translate(X862IR translationHelper, ProcessSpace ps, + X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, + int displacement, int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int operandSize; + if (prefix3 == null) { + operandSize = this.operandSize; + } else { + switch (this.operandSize) { + case 32: + operandSize = 16; + break; + case 16: + operandSize = 32; + break; + default: + operandSize = -1; + DBT_OptimizingCompilerException.UNREACHABLE(); + } + } + int addressSize; + if (prefix4 == null) { + addressSize = _16BIT ? 16 : 32; + } else { + addressSize = _16BIT ? 32 : 16; + } + + X86_DecodedOperand destination = modrm.getRM(translationHelper, lazy, sib, displacement, + operandSize, addressSize, (prefix2 != null) ? prefix2.getSegment() + : X86_Registers.DS); + X86_DecodedOperand source = modrm.getReg(operandSize); + + + OPT_RegisterOperand newValue = translationHelper.getTempInt(0); + OPT_RegisterOperand oldValue = translationHelper.getTempInt(1); + + source.readToRegister(translationHelper, lazy, newValue); + destination.readToRegister(translationHelper, lazy, oldValue); + OPT_RegisterOperand expected = translationHelper.getGPRegister(lazy, X86_Registers.EAX, operandSize); + + translationHelper.appendInstructionToCurrentBlock(CondMove.create(INT_COND_MOVE, + newValue.copyRO(), + expected, oldValue.copyRO(), OPT_ConditionOperand.EQUAL(), + newValue.copyRO(), oldValue.copyRO() + )); + + destination.writeValue(translationHelper, lazy, newValue.copyRO()); + return pc + length; + } + + /** + * Return "cmpxchg" + */ + String getOperatorString() { + return "cmpxchg"; + } +} + +/** * The decoder for the Mov opcode */ class X86_Mov_OpcodeDecoder extends X86_OpcodeDecoder { @@ -2949,7 +3035,6 @@ * Return the SBB operator */ OPT_Operator getOperator() { - TODO(); return INT_SUB; } @@ -4207,7 +4292,88 @@ } } } +/** + * The decoder for the STMXCSR opcode + */ +class X86_StMXCSR_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * Constructor, {@see X86_OpcodeDecoder} + */ + X86_StMXCSR_OpcodeDecoder() { + super(32, // operandSize + true, // hasModRM, + 0, // immediateSize + true // isMemoryOperandDestination + ); + } + /** + * Perform the actual translation + * @param translationHelper + * @param ps + * @param lazy + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected int translate(X862IR translationHelper, ProcessSpace ps, + X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, + int displacement, int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int addressSize; + if (prefix4 == null) { + addressSize = _16BIT ? 16 : 32; + } else { + addressSize = _16BIT ? 32 : 16; + } + + X86_DecodedOperand destination = modrm.getRM(translationHelper, lazy, sib, displacement, + 32, addressSize, (prefix2 != null) ? prefix2.getSegment() : X86_Registers.DS); + + OPT_RegisterOperand mxcsr = translationHelper.getMXCSR(); + destination.writeValue(translationHelper, lazy, mxcsr); + return pc + length; + } + + /** + * Disassemble the opcode + * @param ps + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immedate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected String disassemble(ProcessSpace ps, int pc, + X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, int displacement, + int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int addressSize; + if (prefix4 == null) { + addressSize = _16BIT ? 16 : 32; + } else { + addressSize = _16BIT ? 32 : 16; + } + return "stmxcsr " + modrm.disassembleRM(sib, displacement, 32, addressSize, (prefix2 != null) ? prefix2.getSegment() : X86_Registers.DS); + } +} + /** * The decoder for the Set opcode */ @@ -4571,6 +4737,91 @@ } /** + * The decoder for the LDMXCSR opcode + */ +class X86_LdMXCSR_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * Constructor, {@see X86_OpcodeDecoder} + */ + X86_LdMXCSR_OpcodeDecoder() { + super(32, // operandSize + true, // hasModRM, + 0, // immediateSize + false // isMemoryOperandDestination + ); + } + + /** + * Perform the actual translation + * @param translationHelper + * @param ps + * @param lazy + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected int translate(X862IR translationHelper, ProcessSpace ps, + X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, + int displacement, int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int addressSize; + if (prefix4 == null) { + addressSize = _16BIT ? 16 : 32; + } else { + addressSize = _16BIT ? 32 : 16; + } + + X86_DecodedOperand source = modrm.getRM(translationHelper, lazy, sib, displacement, + 32, addressSize, (prefix2 != null) ? prefix2.getSegment() : X86_Registers.DS); + + OPT_RegisterOperand temp = translationHelper.getTempInt(0); + source.readToRegister(translationHelper, lazy, temp); + + OPT_RegisterOperand mxcsr = translationHelper.getMXCSR(); + translationHelper.appendInstructionToCurrentBlock(Move.create(INT_MOVE, mxcsr, temp.copyRO())); + return pc + length; + } + + /** + * Disassemble the opcode + * @param ps + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immedate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected String disassemble(ProcessSpace ps, int pc, + X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, int displacement, + int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int addressSize; + if (prefix4 == null) { + addressSize = _16BIT ? 16 : 32; + } else { + addressSize = _16BIT ? 32 : 16; + } + return "ldmxcsr " + modrm.disassembleRM(sib, displacement, 32, addressSize, (prefix2 != null) ? prefix2.getSegment() : X86_Registers.DS); + } +} + +/** * The decoder for the Lea opcode */ class X86_Lea_OpcodeDecoder extends X86_OpcodeDecoder { Modified: src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java 2007-04-24 18:16:44 UTC (rev 90) +++ src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java 2007-04-24 23:01:32 UTC (rev 91) @@ -8,8 +8,11 @@ */ package org.binarytranslator.arch.x86.os.abi.linux; +import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; +import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls.SystemCall; /** * Linux system call handling class @@ -40,7 +43,7 @@ systemCallTable[202] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[221] = new LinuxSystemCalls.SysFcntl64(); systemCallTable[252] = new LinuxSystemCalls.SysExitGroup(); - systemCallTable[243] = new LinuxSystemCalls.NullSystemCall(); + systemCallTable[243] = new SetThreadAreaSystemCall(); } /** * The machine for this system given by uname @@ -356,4 +359,45 @@ } } } + /** + * Set the thread area - Set a Thread Local Storage (TLS) area + */ + public class SetThreadAreaSystemCall extends LinuxSystemCalls.SystemCall { + /** + * Handle a system call + */ + public void doSysCall() { + // Ok, we're faking this call at the moment. It's called by glibc to set + // up a TLS area that GS will address. The call will provide -1 asking us + // for a GS segment number and to record the base_addr,... for GS. + Memory mem = src.getProcessSpace().memory; + int user_desc_ptr = arguments.nextInt(); + + int user_desc_entry_number = mem.load32(user_desc_ptr); + System.err.println("entry number="+user_desc_entry_number); + int user_desc_base_addr = mem.load32(user_desc_ptr+4); + System.err.println("base addr="+user_desc_base_addr); + int user_desc_limit = mem.load32(user_desc_ptr+8); + System.err.println("limit="+user_desc_limit); + int packed = mem.load32(user_desc_ptr+12); + System.err.println("packed="+packed); + + boolean user_desc_seg_32bit = (packed & 1) != 0; + int user_desc_contents = (packed >> 1) & 0x3; + boolean user_desc_read_exec_only = ((packed >> 3) & 0x1) != 0; + boolean user_desc_limit_in_pages = ((packed >> 4) & 0x1) != 0; + boolean user_desc_seg_not_present= ((packed >> 4) & 0x1) != 0; + boolean user_desc_useable = ((packed >> 4) & 0x1) != 0; + + if (user_desc_entry_number == -1) { + user_desc_entry_number = 7; + mem.store32(user_desc_ptr, user_desc_entry_number); + ((X86_ProcessSpace)src.getProcessSpace()).registers.writeGS_BaseAddr(user_desc_base_addr); + src.setSysCallReturn(0); + } else { + throw new Error("Unexpected use of set_thread_area"); + } + } + } + } Modified: src/org/binarytranslator/arch/x86/os/process/X86_Registers.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_Registers.java 2007-04-24 18:16:44 UTC (rev 90) +++ src/org/binarytranslator/arch/x86/os/process/X86_Registers.java 2007-04-24 23:01:32 UTC (rev 91) @@ -85,6 +85,11 @@ */ private char[] segmentRegister = new char[6]; + /** + * Base address to be added onto gs segment overrides + */ + private int gsBaseAddr; + /* * Flags */ @@ -414,7 +419,15 @@ public void writeSeg(int reg, char val) { segmentRegister[reg] = val; } + /** + * Write a segment register value + */ + public void writeGS_BaseAddr(int baseAddr) { + gsBaseAddr = baseAddr; + } + + /** * Read flags */ public int readFlags() { Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-24 18:16:44 UTC (rev 90) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-24 23:01:32 UTC (rev 91) @@ -157,8 +157,6 @@ files.add(System.in); files.add(System.out); files.add(System.err); - - structures = new LinuxStructureFactory(); } /** @@ -489,7 +487,7 @@ /** * Define the system call interface */ - abstract class SystemCall { + public abstract class SystemCall { /** * Handle a system call */ @@ -514,18 +512,6 @@ } /** - * Null System Call - do nothing just return 0 - */ - public class NullSystemCall extends SystemCall { - /** - * Handle a system call - */ - public void doSysCall() { - src.setSysCallReturn(0); - } - } - - /** * Exit system call */ public class SysExit extends SystemCall { @@ -853,7 +839,6 @@ domainName = localhostString.substring(index + 1); hostName = localhostString.substring(0,index); } - // Fill in utsname struct - see /usr/include/sys/utsname.h memoryWriteString (addr, getSysName()); // sysname memoryWriteString (addr+65, hostName); // nodename This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-25 19:15:39
|
Revision: 92 http://svn.sourceforge.net/pearcolator/?rev=92&view=rev Author: michael_baer Date: 2007-04-25 12:15:36 -0700 (Wed, 25 Apr 2007) Log Message: ----------- - Added AutoMappingMemory as a decorator, which makes sure that no memory accesses fail due to non-mapped pages. - Partially enabled functions that use the ARM shadow registers. - Cosmetic fixes to the ARM disassembler. - First version of ARM Angel Semihosting ABI that can run a libc program. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/generic/memory/MemoryMapException.java Added Paths: ----------- src/org/binarytranslator/generic/memory/AutoMappingMemory.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-24 23:01:32 UTC (rev 91) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-25 19:15:36 UTC (rev 92) @@ -185,13 +185,17 @@ } public void visit(DataProcessing instr) { - String mnemonic = instr.getOpcode().name(); + + DataProcessing.Opcode opcode = instr.getOpcode(); + String mnemonic = opcode.name(); mnemonic += cond(instr); String parameters; - - if (instr.getOpcode() == DataProcessing.Opcode.CMN || - instr.getOpcode() == DataProcessing.Opcode.CMP) { + + if (opcode == DataProcessing.Opcode.CMN || + opcode == DataProcessing.Opcode.CMP || + opcode == DataProcessing.Opcode.TST || + opcode == DataProcessing.Opcode.TEQ) { //these functions don't use the destination register and always set the condition codes setResult(String.format("%s r%s, %s", mnemonic, instr.getRn(), operand(instr.getOperand2()))); return; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-24 23:01:32 UTC (rev 91) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-25 19:15:36 UTC (rev 92) @@ -197,7 +197,7 @@ } shifterCarryOut = Utils.getBit(value, shiftAmount - 1); - return value >>> shiftAmount; + return value >> shiftAmount; case LSL: @@ -237,7 +237,7 @@ } shifterCarryOut = Utils.getBit(value, shiftAmount - 1); - return value >> shiftAmount; + return value >>> shiftAmount; case ROR: @@ -1014,7 +1014,7 @@ switch (offset.getShiftType()) { case ASR: - addrOffset = addrOffset >>> offset.getShiftAmount(); + addrOffset = addrOffset >> offset.getShiftAmount(); break; case LSL: @@ -1022,7 +1022,7 @@ break; case LSR: - addrOffset = addrOffset >> offset.getShiftAmount(); + addrOffset = addrOffset >>> offset.getShiftAmount(); break; case ROR: Modified: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-04-24 23:01:32 UTC (rev 91) +++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-04-25 19:15:36 UTC (rev 92) @@ -1,14 +1,17 @@ package org.binarytranslator.arch.arm.os.abi.semihosting; +import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.PrintStream; import java.io.RandomAccessFile; import java.util.HashMap; import java.util.Map; +import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; @@ -39,20 +42,21 @@ private final ARM_ProcessSpace ps; /** A mapping from file handles to open files. */ - private final Map<Integer, RandomAccessFile> files = new HashMap<Integer, RandomAccessFile>(); + private final Map<Integer, AngelFileStream> files = new HashMap<Integer, AngelFileStream>(); /** The directory in which temporary files are created. Note that the path is expected to end with a path delimiter.*/ private final static String TEMP_FILE_DIR = "/tmp/"; - /** The file handle that is distributed with the next call to {@link #addFile(RandomAccessFile)}*/ - private int nextFileHandle = 0; + /** The file handle that is distributed with the next call to {@link #addFile(RandomAccessFile)}. + * Valid Angle handles are non-zero values (i.e. >= 1).*/ + private int nextFileHandle = 1; /** */ private AngelSystemCall[] sysCalls; public AngelSystemCalls(ARM_ProcessSpace ps) { this.ps = ps; - sysCalls = new AngelSystemCall[0x31]; + sysCalls = new AngelSystemCall[0x32]; sysCalls[0x1] = new Sys_Open(); sysCalls[0x2] = new Sys_Close(); @@ -76,6 +80,7 @@ sysCalls[0x14] = null; //Another undefined call sysCalls[0x15] = new Sys_Get_CmdLine(); sysCalls[0x16] = new Sys_HeapInfo(); + sysCalls[0x18] = new Sys_Exit(); sysCalls[0x30] = new Sys_Elapsed(); sysCalls[0x31] = new Sys_TickFreq(); } @@ -93,20 +98,20 @@ } /** Add a file to the open file table and return its handle. */ - private int addFile(RandomAccessFile file) { + private int addFile(AngelFileStream file) { int handle = nextFileHandle++; files.put(handle, file); return handle; } /** Returns the file associated with an open file handle or null, if that file handle does not exist. */ - private RandomAccessFile getFile(int handle) { + private AngelFileStream getFile(int handle) { return files.get(handle); } private boolean closeFile(int handle) { try { - RandomAccessFile file = files.get(handle); + AngelFileStream file = files.get(handle); file.close(); return true; } @@ -118,6 +123,133 @@ } } + private interface AngelFileStream { + + boolean isTty(); + int getLength(); + void close(); + + int read() throws IOException; + int read(byte[] buffer) throws IOException; + + void write(int b) throws IOException; + void write(byte[] buffer) throws IOException; + + void seek(long pos) throws IOException; + } + + private class ConsoleStream implements AngelFileStream { + + private String previousInputLine = null; + + public void close() { + throw new RuntimeException("The stdin and stdout are not closeable."); + } + + public int getLength() { + return 0; + } + + public boolean isTty() { + return false; + } + + public int read() throws IOException { + return System.in.read(); + } + + public int read(byte[] buffer) throws IOException { + + //do we already have unhandled input? + if (previousInputLine == null) { + //if not, query a line from the prompt + + previousInputLine = new BufferedReader(new InputStreamReader(System.in)).readLine(); + + //don't forget the Angel expects us to submit a carriage return etc. too + previousInputLine += "\n\r"; + } + + if (DBT.VerifyAssertions) DBT._assert(previousInputLine != null); + + int bytesToRead = Math.min(previousInputLine.length(), buffer.length); + + for (int i = 0; i < bytesToRead; i++) { + buffer[i] = (byte)previousInputLine.charAt(i); + } + + //if we put the complete line into the buffer, then read a new line the next time + if (bytesToRead == previousInputLine.length()) + previousInputLine = null; + + return bytesToRead; + } + + public void seek(long pos) throws IOException { + throw new IOException("The stdin and stdout are not seekable."); + } + + public void write(int b) throws IOException { + System.out.write(b); + } + + public void write(byte[] buffer) throws IOException { + System.out.write(buffer); + } + } + + private class FileStream implements AngelFileStream { + + private final RandomAccessFile file; + + public FileStream(RandomAccessFile file) { + this.file = file; + } + + public void close() { + try { + file.close(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + + public int getLength() { + try { + return (int)file.length(); + } + catch (IOException e) { + e.printStackTrace(); + return 0; + } + } + + public boolean isTty() { + return false; + } + + public int read() throws IOException { + return file.read(); + } + + public int read(byte[] buffer) throws IOException { + return file.read(buffer); + } + + public void seek(long pos) throws IOException { + file.seek(pos); + } + + public void write(int b) throws IOException { + file.write(b); + } + + public void write(byte[] buffer) throws IOException { + file.write(buffer); + } + } + abstract class AngelSystemCall { public abstract void execute(); @@ -149,18 +281,29 @@ @Override public void execute() { int ptrParamBlock = ps.registers.get(1); - int ptrBuffer = ps.memory.loadUnsigned8(ptrParamBlock); - int fileMode = ps.memory.loadUnsigned8(ptrParamBlock + 4); - int length = ps.memory.loadUnsigned8(ptrParamBlock + 8); + int ptrBuffer = ps.memory.load32(ptrParamBlock); + int fileMode = ps.memory.load32(ptrParamBlock + 4); + int length = ps.memory.load32(ptrParamBlock + 8); String fileName = readString(ptrBuffer, length); try { - String openMode = (fileMode >= 4) ? "rw" : "w"; - RandomAccessFile file = new RandomAccessFile(fileName, openMode); + AngelFileStream stream; + //Angel uses a special file called ":tt" to denote stdin / stdout + if (fileName.equals(":tt")) { + //we're supposed to open the console + stream = new ConsoleStream(); + } + else { + //we're supposed to open a file + String openMode = (fileMode >= 4) ? "rw" : "w"; + RandomAccessFile file = new RandomAccessFile(fileName, openMode); + stream = new FileStream(file); + } + //return the file's index within this table as a file handle - setReturn(addFile(file)); + setReturn(addFile(stream)); } catch (FileNotFoundException e) { @@ -187,7 +330,9 @@ public void execute() { int ptrCharToOutput = ps.registers.get(1); char output = (char)ps.memory.loadUnsigned8(ptrCharToOutput); - consoleOutput.print(output); + + if (output != 0) + consoleOutput.print(output); } } @@ -196,7 +341,6 @@ @Override public void execute() { int ptrOutput = ps.registers.get(1); - char output = (char)ps.memory.loadUnsigned8(ptrOutput++); while (output != 0) { @@ -216,12 +360,16 @@ int length = ps.memory.load32(ptrParamBlock + 8); try { - RandomAccessFile file = getFile(fileHandle); + AngelFileStream file = getFile(fileHandle); - while (length != 0) { - file.writeByte(ps.memory.loadUnsigned8(ptrBuffer++)); - length--; - } + //first try to read the whole buffer from memory + byte[] buf = new byte[length]; + + for (int i = 0; i < length; i++) + buf[i] = (byte)ps.memory.loadUnsigned8(ptrBuffer++); + + file.write(buf); + length = 0; } catch (Exception e) {} @@ -239,7 +387,7 @@ int ptrBuffer = ps.memory.load32(ptrParamBlock + 4); int length = ps.memory.load32(ptrParamBlock + 8); - RandomAccessFile file = getFile(fileHandle); + AngelFileStream file = getFile(fileHandle); //fail with EOF if the handle is invalid. Angel does not provide any facilities to //notify about an invalid handle @@ -248,21 +396,28 @@ return; } - int leftToRead = length; - while (leftToRead-- != 0) { - try { - ps.memory.store8(ptrBuffer++, file.readByte()); + byte buf[] = new byte[length]; + try { + int bytesRead = file.read(buf); + + //store the retrieved info into the buffer + for (int i = 0; i < bytesRead; i++) + ps.memory.store8(ptrBuffer++, buf[i]); + + if (bytesRead == length) { + setReturn(0); } - catch (Exception e) { - //did we read any values at all? - if (leftToRead == length) { - setReturn(length); //no, then fail with eof - return; - } + else { + setReturn(bytesRead + 2*length); } + + } catch (IOException e1) { + e1.printStackTrace(); + + //due to us not having a better return code, just return EOF. + setReturn(length); + return; } - - setReturn(length + leftToRead); //otherwise return that we partially filled the buffer } } @@ -303,11 +458,10 @@ int ptrParamBlock = ps.registers.get(1); int fileHandle = ps.memory.load32(ptrParamBlock); - RandomAccessFile file = getFile(fileHandle); + AngelFileStream file = getFile(fileHandle); if (file != null) { - //TODO: Check if the file is an interactive device and return 1 in that case. - setReturn(0); + setReturn( file.isTty() ? 1 : 0 ); } else { setReturn(-1); @@ -323,11 +477,12 @@ int fileHandle = ps.memory.load32(ptrParamBlock); int absolutePosition = ps.memory.load32(ptrParamBlock + 4); - RandomAccessFile file = getFile(fileHandle); + AngelFileStream file = getFile(fileHandle); + try { file.seek(absolutePosition); setReturn(0); - } catch (Exception e) { + } catch (Exception e) { //this path also catches null-pointer exceptions, in case an invalid handle is given setReturn(-1); } } @@ -340,12 +495,12 @@ int ptrParamBlock = ps.registers.get(1); int fileHandle = ps.memory.load32(ptrParamBlock); - RandomAccessFile file = getFile(fileHandle); + AngelFileStream file = getFile(fileHandle); try { - setReturn((int)file.length()); + setReturn(file.getLength()); } - catch (Exception e) { + catch (Exception e) { //this path also catches null-pointer exceptions, in case an invalid handle is given setReturn(-1); } } @@ -516,4 +671,13 @@ setReturn(1000000000); //Return that ticks are measured in nanoseconds } } + + class Sys_Exit extends AngelSystemCall { + + @Override + public void execute() { + ps.finished = true; + } + + } } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-24 23:01:32 UTC (rev 91) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-25 19:15:36 UTC (rev 92) @@ -61,7 +61,7 @@ public static ProcessSpace createProcessSpaceFromBinary(Loader loader) throws IOException { Loader.ABI abi = loader.getABI(); - if (abi == Loader.ABI.ARM || abi == Loader.ABI.SystemV) { + if (abi == Loader.ABI.ARM) { report("Creating ARM Linux ABI Process space"); return new ARM_LinuxProcessSpace(); } else { Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-24 23:01:32 UTC (rev 91) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-25 19:15:36 UTC (rev 92) @@ -1,13 +1,16 @@ package org.binarytranslator.arch.arm.os.process; +import org.binarytranslator.DBT; import org.jikesrvm.VM; public final class ARM_Registers { - public final static int FP = 11; - public final static int SP = 13; - public final static int LR = 14; - public final static int PC = 15; + /** Symbolic constants for the registers in ARM that have a special function. + * Note that (except for the PC), those registers can also be used as general purpose registers*/ + public final static int FP = 11; //frame pointer + public final static int SP = 13; //stack pointer + public final static int LR = 14; //link register + public final static int PC = 15; //program counter /** * The currently visible ARM general purpose registers. Register 15 also @@ -17,14 +20,19 @@ /** * The ARM features a number of shadow registers, that are mapped into the - * register map depending on the operating mode. It contains 8 registers for - * fast IRQ handlers 3 registers for SWI handlers 3 registers for abort - * handlers 3 registers for irq handlers 3 registers for undefined instruction - * handlers 8 registers for temporarely storing the user mode registers during - * non-user modes + * register map depending on the operating mode. It contains 3 registers for SWI handlers, + * 3 registers for abort handlers, 3 registers for irq handlers, 3 registers for undefined instruction + * handlers, 8 registers for fast IRQ handlers and 7 registers to store the user/system mode registers r8-r14. + * + * The registers are contained in the said order. All modes (except for the user mode) have their SPSR + * stored as the third element (from the beginning of their registers) in this table. */ @SuppressWarnings("unused") - private int shadowRegisters[] = new int[28]; + private int shadowRegisters[] = new int[27]; + + /** As mentioned above, each mode has its SPSR stored as the third element within the {@link #shadowRegisters} + * table. This constant is a "human-redable" representation of this offset. */ + private final int SPSR_OFFSET = 2; /** * The negative flag from the CPSR. @@ -62,29 +70,39 @@ * The operating mode from the CPSR register. Note that only the bottom five * bits of this register may ever be set. */ - private byte operatingMode = OPERATING_MODE_SVC; + private OperatingMode operatingMode = OperatingMode.SVC; /** - * Definition of symbolic constants for all valid operating modes - */ - public final static byte OPERATING_MODE_USR = 0x10; - - public final static byte OPERATING_MODE_FIQ = 0x11; - - public final static byte OPERATING_MODE_IRQ = 0x12; - - public final static byte OPERATING_MODE_SVC = 0x13; - - public final static byte OPERATING_MODE_ABT = 0x17; - - public final static byte OPERATING_MODE_UND = 0x1A; + * Definition of symbolic constants for all valid operating modes. */ + public enum OperatingMode { + USR ((byte) 0x10, (byte) 20), + SYS ((byte) 0x1F, (byte) 25), //System mode is being treated as a mode with two special registers (r13, r14), that it shares with user mode + FIQ ((byte) 0x11, (byte) 12), + IRQ ((byte) 0x12, (byte) 6), + SVC ((byte) 0x13, (byte) 0), + ABT ((byte) 0x17, (byte) 3), + UND ((byte) 0x1A, (byte) 9); + + /** + * Each operating system is identified by 5 bits within the PSR. This values stores the byte + * which identifies this mode within the Program Status Registers (PSR). */ + public final byte PSR_IDENTIFIER; + + /** + * Most operating modes have banked registers, that are stored in the <code>shadowRegisters</code> array. + * This value determines the offset at which the shadowed registers for the said mode are stored. + * */ + private final byte SHADOW_OFFSET; + + private OperatingMode(byte psrIdentifier, byte shadowOffset) { + this.PSR_IDENTIFIER = psrIdentifier; + this.SHADOW_OFFSET = shadowOffset; + } + } /** Is the processor currently in thumb mode? */ private boolean thumbMode = false; - public ARM_Registers() { - } - /** Returns the value of the specified register. */ public int get(int reg) { if (VM.VerifyAssertions) @@ -101,12 +119,106 @@ regs[reg] = value; } + public void switchOperatingMode(OperatingMode newMode) { + + int previous_cpsr = getCPSR(); + + //if we're either not switching to a new mode or if we're switching between SYS and USR mode, then + //take a special fast-path + if (newMode == operatingMode || + ((operatingMode == OperatingMode.USR || newMode == OperatingMode.SYS) && + (operatingMode == OperatingMode.SYS || newMode == OperatingMode.USR))) { + //we don't need to do anything in this case, except for copying the CPSR to the SPSR + operatingMode = newMode; + setSPSR(previous_cpsr); + return; + } + + //in the first step, we're saving all registers of the current operating mode. + //Furthermore, we are restoring all user registers except for r13 and r14. This way of approaching + //the problem has the benefit, that we're only exchanging the registers that we really need to exchange. + //However, we need to remember that user mode r8-r12 have not been saved after performing the first step. + int shadowOffset = operatingMode.SHADOW_OFFSET; + + if (operatingMode == OperatingMode.FIQ) { + //store the extra fiq registers + shadowRegisters[shadowOffset++] = regs[8]; + shadowRegisters[shadowOffset++] = regs[9]; + + //skip the FIQ mode SPSR + if (DBT.VerifyAssertions) DBT._assert(OperatingMode.FIQ.SHADOW_OFFSET - shadowOffset == SPSR_OFFSET); + shadowOffset++; + + shadowRegisters[shadowOffset++] = regs[10]; + shadowRegisters[shadowOffset++] = regs[11]; + shadowRegisters[shadowOffset++] = regs[12]; + + //and restore their corresponding user mode registers + regs[8] = shadowRegisters[OperatingMode.USR.SHADOW_OFFSET + 0]; + regs[9] = shadowRegisters[OperatingMode.USR.SHADOW_OFFSET + 1]; + regs[10] = shadowRegisters[OperatingMode.USR.SHADOW_OFFSET + 2]; + regs[11] = shadowRegisters[OperatingMode.USR.SHADOW_OFFSET + 3]; + regs[12] = shadowRegisters[OperatingMode.USR.SHADOW_OFFSET + 4]; + } + else if (operatingMode == OperatingMode.USR) { + //skip user mode r8-r12 + shadowOffset += 5; + } + + //store the current mode's r13 and r14 + shadowRegisters[shadowOffset++] = regs[13]; + shadowRegisters[shadowOffset] = regs[14]; + + //Up to there, we have saved the current mode's registers and restored user mode r8-r12. + //Now, load the new mode's registers. However, remember that though r8-r12 are currently in the register map, + //they have not been saved to the shadowMap. So, if the new mode needs r8-r12, then it + //has to save them first. + shadowOffset = newMode.SHADOW_OFFSET; + + if (newMode == OperatingMode.FIQ) { + //if we're switching to FIQ mode, then remember that we also have to save the (previously unsaved) + //r8-r12 registers + shadowRegisters[OperatingMode.USR.SHADOW_OFFSET + 0] = regs[8]; + shadowRegisters[OperatingMode.USR.SHADOW_OFFSET + 1] = regs[9]; + shadowRegisters[OperatingMode.USR.SHADOW_OFFSET + 2] = regs[10]; + shadowRegisters[OperatingMode.USR.SHADOW_OFFSET + 3] = regs[11]; + shadowRegisters[OperatingMode.USR.SHADOW_OFFSET + 4] = regs[12]; + + //then load in the FIQ mode's r8-r12 + regs[8] = shadowRegisters[shadowOffset++]; + regs[9] = shadowRegisters[shadowOffset++]; + + //skip the shadow mode SPSR + if (DBT.VerifyAssertions) DBT._assert(OperatingMode.FIQ.SHADOW_OFFSET - shadowOffset == SPSR_OFFSET); + shadowOffset++; + + regs[10] = shadowRegisters[shadowOffset++]; + regs[11] = shadowRegisters[shadowOffset++]; + regs[12] = shadowRegisters[shadowOffset++]; + } + else if (operatingMode == OperatingMode.USR) { + //skip these shadow registers for now + shadowOffset += 5; + } + + //now load the remaining r13 and r14 registers + regs[13] = shadowRegisters[shadowOffset++]; + regs[14] = shadowRegisters[shadowOffset]; + + //perform the actual mode switch + operatingMode = newMode; + + //save the previous CPSR as the current SPSR + setSPSR(previous_cpsr); + } + + /** * Restores the saved program status register of the current operating mode to the CPSR, * thereby effectively switching to a different operating mode. */ public void restoreSPSR2CPSR() { - if (VM.VerifyAssertions) VM._assert(operatingMode != OPERATING_MODE_USR && operatingMode != OPERATING_MODE_SVC); + if (VM.VerifyAssertions) VM._assert(operatingMode != OperatingMode.USR); setFlagsFromCPSR(getSPSR()); } @@ -115,18 +227,39 @@ * Returns the content of ARM's Current Program Status Register. * * @return + * A integer, containing a bit representation that is equal to what the current processor state + * would look like on the ARM processor. */ public int getCPSR() { return (flagNegative ? 1 << 31 : 0) | (flagZero ? 1 << 30 : 0) | (flagCarry ? 1 << 29 : 0) | (flagOverflow ? 1 << 28 : 0) | (flagIRQsDisabled ? 1 << 7 : 0) | (flagFIQsDisabled ? 1 << 6 : 0) - | (thumbMode ? 1 << 5 : 0) | operatingMode; + | (thumbMode ? 1 << 5 : 0) | operatingMode.PSR_IDENTIFIER; } /** Returns the content of the current mode's Saved Program Status register.*/ public int getSPSR() { - throw new RuntimeException("Accessing the SPSR is not yet implemented"); + if (operatingMode == OperatingMode.USR || operatingMode == OperatingMode.SYS) { + //these modes don't have a SPSR, so throw an exception + throw new RuntimeException("Cannot read a SPSR in operating mode: " + operatingMode); + } + + return shadowRegisters[operatingMode.SHADOW_OFFSET + SPSR_OFFSET]; } + + /** + * Set's the current mode's Saved Program status register. + * @param newSPSR + */ + public void setSPSR(int newSPSR) { + + if (operatingMode == OperatingMode.USR || operatingMode == OperatingMode.SYS) { + //these modes don't have a SPSR, so ignore them + return; + } + + shadowRegisters[operatingMode.SHADOW_OFFSET + SPSR_OFFSET] = newSPSR; + } /** * Restores the processor state to the state saved within the given CPSR. @@ -135,7 +268,26 @@ * ARM CPSR register content */ public void setFlagsFromCPSR(int cpsr) { - throw new RuntimeException("Interpreting a previous SPSR is not yet implemented."); + + //extract teh differnet flags from the PSR + flagNegative = (cpsr & 0x80000000) != 0; //bit 31 + flagZero = (cpsr & 0x40000000) != 0; //bit 30 + flagCarry = (cpsr & 0x20000000) != 0; //bit 29 + flagOverflow = (cpsr & 0x10000000) != 0; //bit 28 + flagIRQsDisabled = (cpsr & 0x80) != 0; //bit 7 + flagFIQsDisabled = (cpsr & 0x40) != 0; //bit 6 + thumbMode = (cpsr & 0x20) != 0; //bit 5 + + //extract the new operating mode + byte mode = (byte)(cpsr & 0x1F); + + //then perform a regular mode switch to update the register map + for (OperatingMode opMode : OperatingMode.values()) + if (opMode.PSR_IDENTIFIER == mode) { + switchOperatingMode(opMode); + } + + if (DBT.VerifyAssertions) DBT._assert(operatingMode.PSR_IDENTIFIER == mode); } /** @@ -214,5 +366,4 @@ public boolean isNegativeSet() { return flagNegative; } - } Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-24 23:01:32 UTC (rev 91) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-25 19:15:36 UTC (rev 92) @@ -1,27 +1,62 @@ package org.binarytranslator.arch.arm.os.process.image; -import org.binarytranslator.arch.arm.decoder.ARM2IR; +import org.binarytranslator.DBT; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions; +import org.binarytranslator.arch.arm.os.abi.semihosting.AngelSystemCalls; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.generic.execution.GdbController.GdbTarget; +import org.binarytranslator.generic.memory.AutoMappingMemory; import org.binarytranslator.generic.os.loader.Loader; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; public class ARM_ImageProcessSpace extends ARM_ProcessSpace { + + private AngelSystemCalls sysCalls = new AngelSystemCalls(this); + + public ARM_ImageProcessSpace() { + super(); + + //make sure that pages of memory are automatically mapped in as they are requested. + memory = new AutoMappingMemory(memory); + } @Override public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { throw new UnsupportedOperationException("Not yet implemented."); - //return new ARM2IR(context); } @Override public void doSysCall() { - throw new UnsupportedOperationException("Syscalls not supported."); + + //check the SWI instrution to make sure, that we're actually doing an Angel call here + int instruction = memory.loadInstruction32(getCurrentInstructionAddress()); + ARM_Instructions.Instruction instr = ARM_InstructionDecoder.decode(instruction); + + if (DBT.VerifyAssertions) { + if (!(instr instanceof ARM_Instructions.SoftwareInterrupt)) { + throw new Error("The current instruction is not a valid system call."); + } + } + + //Thumb system calls start from 0, while ARM calls start from 0x900000. + //Use a mask to let both calls start from the same address + int sysCallNr = ((ARM_Instructions.SoftwareInterrupt)instr).getInterruptNumber(); + + if (sysCallNr == 0x123456) { + sysCalls.doSysCall(registers.get(0)); + + //simulate a proper return from syscalls + setCurrentInstructionAddress(getCurrentInstructionAddress() + 4); + } + else { + throw new RuntimeException("Non-Angel system calls are not yet supported."); + } } - + @Override public GdbTarget getGdbTarget() { throw new UnsupportedOperationException("GDB not implemented."); Added: src/org/binarytranslator/generic/memory/AutoMappingMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/AutoMappingMemory.java (rev 0) +++ src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-04-25 19:15:36 UTC (rev 92) @@ -0,0 +1,221 @@ +package org.binarytranslator.generic.memory; + +import java.io.RandomAccessFile; + +import org.binarytranslator.vmInterface.TranslationHelper; +import org.jikesrvm.classloader.VM_MethodReference; +import org.jikesrvm.compilers.opt.ir.OPT_Operand; +import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; + +/** + * A memory implementation that will automatically map pages into memory, as soon + * as they are requested. Therefore, this memory never fails with an exception + * due to a non-mapped memory page. + * + * The class is implemented as a decorator, therefore it can work with any underlying + * memory that implements the {@link Memory} interface. However, automatic mapping + * of pages is (at the moment) only supported during interpretation. + * + * @author Michael Baer + * + */ +public class AutoMappingMemory extends Memory { + + private Memory mem; + + public AutoMappingMemory(Memory memoryImplementation) { + this.mem = memoryImplementation; + } + + public boolean equals(Object arg0) { + return mem.equals(arg0); + } + + public VM_MethodReference getMethodRef(int callAddress) { + return mem.getMethodRef(callAddress); + } + + public int getPageSize() { + return mem.getPageSize(); + } + + public int hashCode() { + return mem.hashCode(); + } + + public void initTranslate(TranslationHelper helper) { + mem.initTranslate(helper); + } + + public boolean isMapped(int addr) { + return mem.isMapped(addr); + } + + public boolean isPageAligned(int addr) { + return mem.isPageAligned(addr); + } + + public int load32(int addr) { + try { + return mem.load32(addr); + } + catch (Exception e) { + ensureMapped(addr, addr + 4); + return load32(addr); + } + } + + public int loadInstruction32(int addr) { + try { + return mem.loadInstruction32(addr); + } + catch (Exception e) { + ensureMapped(addr, addr + 4); + return loadInstruction32(addr); + } + } + + public int loadInstruction8(int addr) { + try { + return mem.loadInstruction8(addr); + } + catch (Exception e) { + ensureMapped(addr, addr + 1); + return mem.loadInstruction8(addr); + } + } + + public int loadSigned16(int addr) { + try { + return mem.loadSigned16(addr); + } + catch (Exception e) { + ensureMapped(addr, addr + 2); + return mem.loadSigned16(addr); + } + } + + public int loadSigned8(int addr) { + try { + return mem.loadSigned8(addr); + } + catch (Exception e) { + ensureMapped(addr, addr + 1); + return mem.loadSigned8(addr); + } + } + + public int loadUnsigned16(int addr) { + try { + return mem.loadUnsigned16(addr); + } + catch (Exception e) { + ensureMapped(addr, addr + 2); + return mem.loadUnsigned16(addr); + } + } + + public int loadUnsigned8(int addr) { + try { + return mem.loadUnsigned8(addr); + } + catch (Exception e) { + ensureMapped(addr, addr + 1); + return mem.loadUnsigned8(addr); + } + } + + public int map(int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException { + return mem.map(addr, len, read, write, exec); + } + + public int map(RandomAccessFile file, long offset, int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException { + return mem.map(file, offset, addr, len, read, write, exec); + } + + public void store16(int addr, int value) { + try { + mem.store16(addr, value); + } + catch (Exception e) { + ensureMapped(addr, addr + 2); + mem.store16(addr, value); + } + } + + public void store32(int addr, int value) { + try { + mem.store32(addr, value); + } + catch (Exception e) { + ensureMapped(addr, addr + 4); + mem.store32(addr, value); + } + } + + public void store8(int addr, int value) { + try { + mem.store8(addr, value); + } + catch (Exception e) { + ensureMapped(addr, addr + 1); + mem.store8(addr, value); + } + } + + public String toString() { + return mem.toString(); + } + + public void translateLoad32(OPT_Operand addr, OPT_RegisterOperand dest) { + //mem.translateLoad32(addr, dest); + throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); + } + + public void translateLoadSigned16(OPT_Operand addr, OPT_RegisterOperand dest) { + //mem.translateLoadSigned16(addr, dest); + throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); + } + + public void translateLoadSigned8(OPT_Operand addr, OPT_RegisterOperand dest) { + //mem.translateLoadSigned8(addr, dest); + throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); + } + + public void translateLoadUnsigned16(OPT_Operand addr, OPT_RegisterOperand dest) { + //mem.translateLoadUnsigned16(addr, dest); + throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); + } + + public void translateLoadUnsigned8(OPT_Operand addr, OPT_RegisterOperand dest) { + //mem.translateLoadUnsigned8(addr, dest); + throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); + } + + public void translateStore16(OPT_Operand addr, OPT_RegisterOperand src) { + //mem.translateStore16(addr, src); + throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); + } + + public void translateStore32(OPT_Operand addr, OPT_RegisterOperand src) { + //mem.translateStore32(addr, src); + throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); + } + + public void translateStore8(OPT_Operand addr, OPT_RegisterOperand src) { + //mem.translateStore8(addr, src); + throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); + } + + public int truncateToNextPage(int addr) { + return mem.truncateToNextPage(addr); + } + + public int truncateToPage(int addr) { + return mem.truncateToPage(addr); + } + + public void unmap(int addr, int len) { + mem.unmap(addr, len); + } +} Modified: src/org/binarytranslator/generic/memory/MemoryMapException.java =================================================================== --- src/org/binarytranslator/generic/memory/MemoryMapException.java 2007-04-24 23:01:32 UTC (rev 91) +++ src/org/binarytranslator/generic/memory/MemoryMapException.java 2007-04-25 19:15:36 UTC (rev 92) @@ -13,7 +13,7 @@ /** * Captures exceptions that can occur during memory mangement */ -final public class MemoryMapException extends Exception { +final public class MemoryMapException extends RuntimeException { /** * Attempt to allocate on a non-page boundary */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |