You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
|
Feb
|
Mar
(16) |
Apr
(83) |
May
(27) |
Jun
(14) |
Jul
(11) |
Aug
(22) |
Sep
|
Oct
|
Nov
|
Dec
|
From: <mic...@us...> - 2007-04-30 17:59:35
|
Revision: 99 http://svn.sourceforge.net/pearcolator/?rev=99&view=rev Author: michael_baer Date: 2007-04-30 10:59:37 -0700 (Mon, 30 Apr 2007) Log Message: ----------- - Fixed bugs - Removed support of using the PC as an argument where the ARM Ref. manual specifies that using the PC with this opcode yields an undefined result - Added support for long multiplication instructions Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-30 13:24:05 UTC (rev 98) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-30 17:59:37 UTC (rev 99) @@ -441,9 +441,7 @@ super(instr); } - /** Returns the value of operand 1 of the data processing instruction. This is always a register value. - * However, deriving classes may alter this behavior, for example to return a negative register - * value for a RSB instruction. */ + /** Returns the value of operand 1 of the data processing instruction. This is always a register value. */ protected int resolveOperand1() { if (Rn == ARM_Registers.PC) { @@ -635,6 +633,9 @@ operand2++; } else { regs.setFlags(operand1 > 0, operand1 != 0, true, true); + + //set the result to any of the operands + regs.set(Rd, operand1); return; } } @@ -666,6 +667,7 @@ //TODO: Remove this exception, when the correct behavior has been verified. throw new RuntimeException("I'm interested in finding a case where this occurs, so this exception is sooner or later going to 'notify' me.."); //regs.setFlags(operand1 > 0, operand1 != 0, true, true); + //regs.set(Rd, operand1); //return; } } @@ -843,7 +845,7 @@ int memAddr = regs.get(Rn); //swap exchanges the value of a memory address with the value in a register - if (swapByte) { + if (!swapByte) { int tmp = ps.memory.load32(memAddr); ps.memory.store32(memAddr, regs.get(Rm)); @@ -853,8 +855,8 @@ } else { int tmp = ps.memory.loadUnsigned8(memAddr); - ps.memory.store8(memAddr, regs.get(Rm) & 0xFF); - regs.set(Rm, tmp); + ps.memory.store8(memAddr, regs.get(Rm)); + regs.set(Rd, tmp); } } @@ -942,7 +944,6 @@ if (transferPC) { nextAddress += 4; int newpc = ps.memory.load32(nextAddress); - regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); if (forceUser) { //when we are transferring the PC with a forced-user transfer, then we also want to @@ -953,11 +954,18 @@ regs.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); regs.restoreSPSR2CPSR(); + if (regs.getThumbMode()) + newpc = newpc & 0xFFFFFFFE; + else + newpc = newpc & 0xFFFFFFFC; + + regs.set(ARM_Registers.PC, newpc); //there is no write-back for this instruction. return; } else { //shall we switch to thumb mode + regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); regs.setThumbMode((newpc & 0x1) != 0); } } @@ -1024,12 +1032,9 @@ } public void execute() { - //remember the previous address, taking ARM's register offset into account - int previousAddress = regs.get(ARM_Registers.PC); - //if we're supposed to link, then write the previous address into the link register if (link) - regs.set(ARM_Registers.LR, previousAddress + 4); + regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + 4); } public int getSuccessor(int pc) { @@ -1102,25 +1107,16 @@ public void execute() { //get the two operands + //we don't need to consider that any operand might be the PC, because the ARM + //Ref. manual specifies the usage of the PC has undefined results in this operation int operand1 = regs.get(Rm); int operand2 = regs.get(Rs); - //if any of the operands is the PC, consider ARM's PC offset - if (Rm == ARM_Registers.PC) - operand1 += 8; - - if (Rs == ARM_Registers.PC) - operand2 += 8; - //calculate the result - int result = regs.get(Rm) * regs.get(Rs); + int result = operand1 * operand2; if (accumulate) { result += regs.get(Rn); - - //also consider ARM's PC offset when adding the accumulate register - if (Rn == ARM_Registers.PC) - result += 8; } //and finally, update the register map @@ -1132,13 +1128,59 @@ } public int getSuccessor(int pc) { - if (Rd != ARM_Registers.PC) - return pc + 4; - else - return -1; + return pc + 4; } } + + /** Multiply two longs into a register, possibly adding the value of a third register on the way. */ + private final class LongMultiply extends ARM_Instructions.LongMultiply implements + ARM_Instruction { + protected LongMultiply(int instr) { + super(instr); + } + + public void execute() { + + // get the two operands + // We don't need to consider that any operand might be the PC, because the + // ARM Ref. manual specifies the usage of the PC has undefined results in this + // operation + long operand1 = regs.get(Rm); + long operand2 = regs.get(Rs); + + //get rid of the signs, if we're supposed to do unsigned multiplication + if (unsigned) { + operand1 = operand1 & 0xFFFFFFFF; + operand2 = operand2 & 0xFFFFFFFF; + } + + // calculate the result + long result = operand1 * operand2; + + if (accumulate) { + //treat the register as an unsigned value + long operand = regs.get(getRdLow()); + operand &= 0xFFFFFFFF; + result += operand; + + result += regs.get(getRdHigh()) << 32; + } + + // and finally, update the register map + regs.set(getRdLow(), (int) result); + regs.set(getRdHigh(), (int) (result >>> 32)); + + if (updateConditionCodes) { + regs.setFlags(result < 0, result == 0); + } + } + + public int getSuccessor(int pc) { + return pc + 4; + } + } + /** Move the value of the program status register into a register. */ private final class MoveFromStatusRegister extends ARM_Instructions.MoveFromStatusRegister implements @@ -1338,11 +1380,11 @@ break; case HalfWord: - ps.memory.store16(address, value & 0xFFFF); + ps.memory.store16(address, value); break; case Byte: - ps.memory.store8(address, value & 0xFF); + ps.memory.store8(address, value); break; default: @@ -1500,8 +1542,7 @@ } public ARM_Instruction createLongMultiply(int instr) { - //TODO: Implement multiplications with longs - throw new RuntimeException("Long Multiplications are not yet supported."); + return new LongMultiply(instr); } public ARM_Instruction createMoveFromStatusRegister(int instr) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-30 13:24:07
|
Revision: 98 http://svn.sourceforge.net/pearcolator/?rev=98&view=rev Author: michael_baer Date: 2007-04-30 06:24:05 -0700 (Mon, 30 Apr 2007) Log Message: ----------- translateStoreXX functions now store any OPT_Operand (instead of only OPT_RegisterOperands) Modified Paths: -------------- src/org/binarytranslator/generic/memory/AutoMappingMemory.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/DebugMemory.java src/org/binarytranslator/generic/memory/Memory.java Modified: src/org/binarytranslator/generic/memory/AutoMappingMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-04-29 13:34:10 UTC (rev 97) +++ src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-04-30 13:24:05 UTC (rev 98) @@ -192,17 +192,17 @@ throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); } - public void translateStore16(OPT_Operand addr, OPT_RegisterOperand src) { + public void translateStore16(OPT_Operand addr, OPT_Operand 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) { + public void translateStore32(OPT_Operand addr, OPT_Operand 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) { + public void translateStore8(OPT_Operand addr, OPT_Operand src) { //mem.translateStore8(addr, src); throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); } Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-04-29 13:34:10 UTC (rev 97) +++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-04-30 13:24:05 UTC (rev 98) @@ -318,7 +318,7 @@ * the address of the value to store */ private void translateStore(VM_Method storeMethod, int bcIndex, - OPT_Operand addr, OPT_RegisterOperand src) { + OPT_Operand addr, OPT_Operand src) { OPT_Instruction s = Call.create(CALL, null, null, null, null, 3); VM_MethodReference storeMethRef = storeMethod.getMemberRef() .asMethodReference(); @@ -344,7 +344,7 @@ * @param addr * the address of the value to store */ - public void translateStore8(OPT_Operand addr, OPT_RegisterOperand src) { + public void translateStore8(OPT_Operand addr, OPT_Operand src) { translateStore(store8, DBT_Trace.MEMORY_STORE8, addr, src); } @@ -356,7 +356,7 @@ * @param addr * the address of the value to store */ - public void translateStore16(OPT_Operand addr, OPT_RegisterOperand src) { + public void translateStore16(OPT_Operand addr, OPT_Operand src) { translateStore(store16, DBT_Trace.MEMORY_STORE16, addr, src); } @@ -368,7 +368,7 @@ * @param addr * the address of the value to store */ - public void translateStore32(OPT_Operand addr, OPT_RegisterOperand src) { + public void translateStore32(OPT_Operand addr, OPT_Operand src) { translateStore(store32, DBT_Trace.MEMORY_STORE32, addr, src); } Modified: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-29 13:34:10 UTC (rev 97) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-30 13:24:05 UTC (rev 98) @@ -559,19 +559,19 @@ } @Override - public void translateStore16(OPT_Operand addr, OPT_RegisterOperand src) { + public void translateStore16(OPT_Operand addr, OPT_Operand src) { throw new UnsupportedOperationException(); } @Override - public void translateStore32(OPT_Operand addr, OPT_RegisterOperand src) { + public void translateStore32(OPT_Operand addr, OPT_Operand src) { throw new UnsupportedOperationException(); } @Override - public void translateStore8(OPT_Operand addr, OPT_RegisterOperand src) { + public void translateStore8(OPT_Operand addr, OPT_Operand src) { throw new UnsupportedOperationException(); } Modified: src/org/binarytranslator/generic/memory/Memory.java =================================================================== --- src/org/binarytranslator/generic/memory/Memory.java 2007-04-29 13:34:10 UTC (rev 97) +++ src/org/binarytranslator/generic/memory/Memory.java 2007-04-30 13:24:05 UTC (rev 98) @@ -224,7 +224,7 @@ * @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_Operand src); /** * Generate the IR code for a 16bit store @@ -232,7 +232,7 @@ * @param addr the address of the value to store */ public abstract void translateStore16(OPT_Operand addr, - OPT_RegisterOperand src); + OPT_Operand src); /** * Generate the IR code for a 32bit store @@ -240,7 +240,7 @@ * @param addr the address of the value to store */ public abstract void translateStore32(OPT_Operand addr, - OPT_RegisterOperand src); + OPT_Operand src); /** * Get method reference if linking a call This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-29 13:34:09
|
Revision: 97 http://svn.sourceforge.net/pearcolator/?rev=97&view=rev Author: michael_baer Date: 2007-04-29 06:34:10 -0700 (Sun, 29 Apr 2007) Log Message: ----------- - Not calculating the "barrel shifter carry out" if it is not needed - Fixed bug with register-shifted operands when the shift amount is >= 32 Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-28 16:18:58 UTC (rev 96) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-29 13:34:10 UTC (rev 97) @@ -132,7 +132,7 @@ if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) shiftAmount = operand.getShiftAmount(); else { - shiftAmount = (byte) (regs.get(operand.getShiftingRegister()) & 0xF); + shiftAmount = (byte) (regs.get(operand.getShiftingRegister())); } switch (operand.getShiftType()) { @@ -245,7 +245,7 @@ if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) shiftAmount = operand.getShiftAmount(); else { - shiftAmount = (byte) (regs.get(operand.getShiftingRegister()) & 0xF); + shiftAmount = (byte) (regs.get(operand.getShiftingRegister())); } switch (operand.getShiftType()) { @@ -437,18 +437,10 @@ private abstract class DataProcessing extends ARM_Instructions.DataProcessing implements ARM_Instruction { - /** Most data processing instructions may set the carry flag according to the barrel shifter's carry - * out value. The (supposed) value of the barrel shifter is stored within this variable. */ - protected boolean shifterCarryOut; - protected DataProcessing(int instr) { super(instr); } - /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift - * and set the result of the barrel shifter accordingly. */ - - /** Returns the value of operand 1 of the data processing instruction. This is always a register value. * However, deriving classes may alter this behavior, for example to return a negative register * value for a RSB instruction. */ @@ -463,25 +455,11 @@ /** Returns the value of the rhs-operand of the data processing instruction. */ protected int resolveOperand2() { - ResolvedOperand resolvedOperand2 = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); - shifterCarryOut = resolvedOperand2.getShifterCarryOut(); - return resolvedOperand2.getValue(); + return ResolvedOperand.resolve(regs, operand2); } public abstract void execute(); - /** Sets the condition field for logical operations. */ - protected final void setFlagsForLogicalOperator(int result) { - - if (updateConditionCodes) { - if (Rd != 15) { - regs.setFlags(result < 0, result == 0, shifterCarryOut); - } else { - regs.restoreSPSR2CPSR(); - } - } - } - /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ protected final void setFlagsForAdd(int lhs, int rhs) { @@ -521,9 +499,40 @@ return -1; } } + + private abstract class DataProcessing_Logical extends DataProcessing { + + /** Most data processing instructions may set the carry flag according to the barrel shifter's carry + * out value. The value of the barrel shifter is stored within this variable. */ + protected boolean shifterCarryOut; + protected DataProcessing_Logical(int instr) { + super(instr); + } + + /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift + * and set the result of the barrel shifter accordingly. */ + protected int resolveOperand2() { + ResolvedOperand operand = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); + shifterCarryOut = operand.getShifterCarryOut(); + return operand.getValue(); + } + + /** Sets the condition field for logical operations. */ + protected final void setFlagsForLogicalOperator(int result) { + + if (updateConditionCodes) { + if (Rd != 15) { + regs.setFlags(result < 0, result == 0, shifterCarryOut); + } else { + regs.restoreSPSR2CPSR(); + } + } + } + } + /** Binary and. <code>Rd = op1 & op2 </code>.*/ - private final class DataProcessing_And extends DataProcessing { + private final class DataProcessing_And extends DataProcessing_Logical { protected DataProcessing_And(int instr) { super(instr); @@ -538,7 +547,7 @@ } /** Exclusive or. <code>Rd = op1 ^ op2 </code>.*/ - private final class DataProcessing_Eor extends DataProcessing { + private final class DataProcessing_Eor extends DataProcessing_Logical { protected DataProcessing_Eor(int instr) { super(instr); @@ -688,7 +697,7 @@ /** Set the flags according to the logical-and of two values. * <code>Flags = op1 & op2</code>*/ - private final class DataProcessing_Tst extends DataProcessing { + private final class DataProcessing_Tst extends DataProcessing_Logical { protected DataProcessing_Tst(int instr) { super(instr); @@ -702,7 +711,7 @@ /** Sets the flags according to the exclusive-or of two values. * <code>Flags = op1 ^ op2</code> */ - private final class DataProcessing_Teq extends DataProcessing { + private final class DataProcessing_Teq extends DataProcessing_Logical { protected DataProcessing_Teq(int instr) { super(instr); @@ -743,7 +752,7 @@ } /** Binary or. <code>Rd = op1 | op2</code>. */ - private final class DataProcessing_Orr extends DataProcessing { + private final class DataProcessing_Orr extends DataProcessing_Logical { protected DataProcessing_Orr(int instr) { super(instr); @@ -757,7 +766,7 @@ } } - private final class DataProcessing_Mov extends DataProcessing { + private final class DataProcessing_Mov extends DataProcessing_Logical { protected DataProcessing_Mov(int instr) { super(instr); @@ -774,7 +783,7 @@ /** Bit clear. Clear bits in a register by a mask given by a second operand. * <code>Rd = op1 & (~op2)</code>.*/ - private final class DataProcessing_Bic extends DataProcessing { + private final class DataProcessing_Bic extends DataProcessing_Logical { protected DataProcessing_Bic(int instr) { super(instr); @@ -791,7 +800,7 @@ /** Move and negate. Moves an integer between two registers, negating it on the way. * <code>Rd = -op2</code>.*/ - private final class DataProcessing_Mvn extends DataProcessing { + private final class DataProcessing_Mvn extends DataProcessing_Logical { protected DataProcessing_Mvn(int instr) { super(instr); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-28 16:18:58
|
Revision: 96 http://svn.sourceforge.net/pearcolator/?rev=96&view=rev Author: michael_baer Date: 2007-04-28 09:18:58 -0700 (Sat, 28 Apr 2007) Log Message: ----------- - Moved setBrk() / getBrk() to LinuxSystemCalls Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.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/os/abi/linux/LinuxSystemCallGenerator.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 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-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-28 16:18:58 UTC (rev 96) @@ -1,6 +1,5 @@ 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.arch.arm.os.process.ARM_Registers; @@ -10,7 +9,6 @@ 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; public class ARM_LinuxProcessSpace extends ARM_ProcessSpace { @@ -33,7 +31,7 @@ private int[] auxVector; public ARM_LinuxProcessSpace() { - sysCallGenerator = new Legacy(this, 0xEBADADD); + sysCallGenerator = new Legacy(this); sysCalls = new ARM_LinuxSystemCalls(this, sysCallGenerator); } @@ -49,7 +47,7 @@ @Override public void initialise(Loader loader, int pc, int brk) { registers.set(ARM_Registers.PC, pc); - sysCallGenerator.setBrk(brk); + sysCalls.initialize(brk); // initialize the stack auxVector = new int[] { Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-28 16:18:58 UTC (rev 96) @@ -1,7 +1,6 @@ package org.binarytranslator.arch.arm.os.process.linux.abi; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; -import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -29,18 +28,12 @@ /** The process space that we're running on. */ private final ARM_LinuxProcessSpace ps; private final ArgumentIterator args; - private int brk; - public EABI(ARM_LinuxProcessSpace ps, int brk) { + public EABI(ARM_LinuxProcessSpace ps) { this.ps = ps; - this.brk = brk; this.args = new ArgumentIterator(); } - public int getBrk() { - return brk; - } - public ProcessSpace getProcessSpace() { return ps; } @@ -54,19 +47,6 @@ return ps.registers.get(7); } - public void setBrk(int address) { - - try { - ps.memory.ensureMapped(brk, address); - } catch (MemoryMapException e) { - throw new Error(String.format( - "Error changing top of BSS from 0x%x to address 0x%x", brk, address), - e); - } - - brk = address; - } - public void setSysCallError(int r) { ps.registers.set(0, -r); } Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-28 16:18:58 UTC (rev 96) @@ -4,7 +4,6 @@ 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.memory.MemoryMapException; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -32,30 +31,11 @@ * system call */ private final ArgumentIterator syscallArgs; - private int brk; - - - public Legacy(ARM_LinuxProcessSpace ps, int brk) { + public Legacy(ARM_LinuxProcessSpace ps) { this.ps = ps; - this.brk = brk; syscallArgs = new ArgumentIterator(); } - public int getBrk() { - return brk; - } - - public void setBrk(int address) { - try { - ps.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; - } - public ProcessSpace getProcessSpace() { return ps; } 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-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-28 16:18:58 UTC (rev 96) @@ -40,11 +40,6 @@ final PPC_LinuxSyscallArgumentIterator syscallArgs; /** - * The top of the bss segment - */ - private int brk; - - /** * The top of the stack */ private static final int STACK_TOP = 0x80000000; @@ -74,8 +69,8 @@ */ public void initialise(Loader loader, int pc, int brk) { this.pc = pc; - this.brk = brk; this.r1 = initialiseStack(loader, pc); + syscalls.initialize(brk); } /** @@ -178,27 +173,6 @@ setCR_bit(0, true); } - /** - * Get the top of the BSS segment (the heap that reside below the stack in - * memory) - * - * @return top of BSS segment - */ - public int getBrk() { - return brk; - } - - /** - * Set the top of the BSS segment (the heap that reside below the stack in - * memory) - * - * @param address - * new top of BSS segment - */ - public void setBrk(int address) { - brk = address; - } - public GdbTarget getGdbTarget() { return this; } 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-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-28 16:18:58 UTC (rev 96) @@ -40,11 +40,6 @@ private final X86_LinuxSyscallArgumentIterator syscallArgs; /** - * The top of the bss segment - */ - private int brk; - - /** * The top of the stack */ private static final int STACK_TOP = 0xC0000000; @@ -71,7 +66,7 @@ */ public void initialise(Loader loader, int pc, int brk) { registers.eip = pc; - this.brk = brk; + registers.writeGP32(X86_Registers.ESP, initialiseStack(loader, pc)); if (useSysInfoPage) { try { @@ -83,6 +78,8 @@ memory.store8(0xffffe400, 0x80); // 80h memory.store8(0xffffe400, 0xC3); // RET } + + syscalls.initialize(brk); } /** @@ -146,29 +143,6 @@ registers.writeGP32(X86_Registers.EAX, -r); } - /** - * Get the top of the BSS segment (the heap that reside below the - * stack in memory) - * @return top of BSS segment - */ - public int getBrk() { - return brk; - } - /** - * Set the top of the BSS segment (the heap that reside below the - * stack in memory) - * @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; - } - public void setStackPtr(int ptr) {} public int[] getAuxVector() { Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-04-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-04-28 16:18:58 UTC (rev 96) @@ -8,7 +8,6 @@ */ package org.binarytranslator.generic.os.abi.linux; -import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.os.process.ProcessSpace; /** @@ -52,27 +51,7 @@ * @param r the error value */ public void setSysCallError(int r); - /** - * Write to the memory of the system call generator a 32bit value - * @param address where to write - * @param data value to store - */ - - /** - * Returns the process space that this call originated from. - */ + + /** Returns the process space that this call originated from.*/ public ProcessSpace getProcessSpace(); - - /** - * Get the top of the BSS segment (the heap that reside below the - * stack in memory) - * @return top of BSS segment - */ - public int getBrk(); - /** - * Set the top of the BSS segment (the heap that reside below the - * stack in memory) - * @param address new top of BSS segment - */ - public void setBrk(int address); } Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-28 16:18:58 UTC (rev 96) @@ -44,12 +44,15 @@ protected LinuxStructureFactory structures; /** List of currently opened files. */ - private OpenFileList openFiles; + protected OpenFileList openFiles; + + /** The top of the bss segment */ + protected int brk; /** * Maximum number of system calls */ - private static final int MAX_SYSCALLS = 294; + protected static final int MAX_SYSCALLS = 294; /** * Array to de-multiplex Linux system calls. NB we will have to @@ -89,7 +92,7 @@ * @param address where to read * @return the String read */ - private String memoryReadString(int address) { + protected String memoryReadString(int address) { Memory m = src.getProcessSpace().memory; StringBuffer str = new StringBuffer(); @@ -106,7 +109,7 @@ * @param address where to read * @param data the String to write */ - public void memoryWriteString(int address, String data) { + protected void memoryWriteString(int address, String data) { Memory m = src.getProcessSpace().memory; if (data != null) { @@ -117,6 +120,17 @@ m.store8(address + data.length(), (byte) 0); } } + + /** + * Sets up the linux operating space + * + * @param brk + * the initial value for the top of BSS + */ + public void initialize(int brk) { + LinuxSystemCalls.this.brk = brk; + src.getProcessSpace().memory.ensureMapped(brk, brk+1); + } /** * Constructor @@ -397,12 +411,14 @@ public class SysBrk extends SystemCall { public void doSysCall() { - int brk = arguments.nextInt(); - if (brk != 0) { + int newBrk = arguments.nextInt(); + if (newBrk != 0) { // Request to set the current top of bss. - src.setBrk(brk); + brk = newBrk; + src.getProcessSpace().memory.ensureMapped(brk, brk+1); } - src.setSysCallReturn(src.getBrk()); + + src.setSysCallReturn(brk); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-27 15:03:24
|
Revision: 95 http://svn.sourceforge.net/pearcolator/?rev=95&view=rev Author: michael_baer Date: 2007-04-27 08:03:23 -0700 (Fri, 27 Apr 2007) Log Message: ----------- Moved Linux constants into a seperate class. Modified Paths: -------------- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Added Paths: ----------- src/org/binarytranslator/generic/os/abi/linux/LinuxConstants.java Added: src/org/binarytranslator/generic/os/abi/linux/LinuxConstants.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxConstants.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxConstants.java 2007-04-27 15:03:23 UTC (rev 95) @@ -0,0 +1,436 @@ +package org.binarytranslator.generic.os.abi.linux; + +interface LinuxConstants { + /** + * Class capturing errno constants + */ + static interface errno { + /** Operation not permitted */ + final static int EPERM = 1; + + /** No such file or directory */ + final static int ENOENT = 2; + + /** No such process */ + final static int ESRCH = 3; + + /** Interrupted system call */ + final static int EINTR = 4; + + /** I/O error */ + final static int EIO = 5; + + /** No such device or address */ + final static int ENXIO = 6; + + /** Argument list too long */ + final static int E2BIG = 7; + + /** Exec format error */ + final static int ENOEXEC = 8; + + /** Bad file number */ + final static int EBADF = 9; + + /** No child processes */ + final static int ECHILD = 10; + + /** Try again */ + final static int EAGAIN = 11; + + /** Out of memory */ + final static int ENOMEM = 12; + + /** Permission denied */ + final static int EACCES = 13; + + /** Bad address */ + final static int EFAULT = 14; + + /** Block device required */ + final static int ENOTBLK = 15; + + /** Device or resource busy */ + final static int EBUSY = 16; + + /** File exists */ + final static int EEXIST = 17; + + /** Cross-device link */ + final static int EXDEV = 18; + + /** No such device */ + final static int ENODEV = 19; + + /** Not a directory */ + final static int ENOTDIR = 20; + + /** Is a directory */ + final static int EISDIR = 21; + + /** Invalid argument */ + final static int EINVAL = 22; + + /** File table overflow */ + final static int ENFILE = 23; + + /** Too many open files */ + final static int EMFILE = 24; + + /** Not a typewriter */ + final static int ENOTTY = 25; + + /** Text file busy */ + final static int ETXTBSY = 26; + + /** File too large */ + final static int EFBIG = 27; + + /** No space left on device */ + final static int ENOSPC = 28; + + /** Illegal seek */ + final static int ESPIPE = 29; + + /** Read-only file system */ + final static int EROFS = 30; + + /** Too many links */ + final static int EMLINK = 31; + + /** Broken pipe */ + final static int EPIPE = 32; + + /** Math argument out of domain of func */ + final static int EDOM = 33; + + /** Math result not representable */ + final static int ERANGE = 34; + + /** Resource deadlock would occur */ + final static int EDEADLK = 35; + + final static int EDEADLOCK = EDEADLK; + + /** File name too long */ + final static int ENAMETOOLONG = 36; + + /** No record locks available */ + final static int ENOLCK = 37; + + /** Function not implemented */ + final static int ENOSYS = 38; + + /** Directory not empty */ + final static int ENOTEMPTY = 39; + + /** Too many symbolic links encountered */ + final static int ELOOP = 40; + + /** Operation would block */ + final static int EWOULDBLOCK = EAGAIN; + + /** No message of desired type */ + final static int ENOMSG = 42; + + /** Identifier removed */ + final static int EIDRM = 43; + + /** Channel number out of range */ + final static int ECHRNG = 44; + + /** Level 2 not synchronized */ + final static int EL2NSYNC = 45; + + /** Level 3 halted */ + final static int EL3HLT = 46; + + /** Level 3 reset */ + final static int EL3RST = 47; + + /** Link number out of range */ + final static int ELNRNG = 48; + + /** Protocol driver not attached */ + final static int EUNATCH = 49; + + /** No CSI structure available */ + final static int ENOCSI = 50; + + /** Level 2 halted */ + final static int EL2HLT = 51; + + /** Invalid exchange */ + final static int EBADE = 52; + + /** Invalid request descriptor */ + final static int EBADR = 53; + + /** Exchange full */ + final static int EXFULL = 54; + + /** No anode */ + final static int ENOANO = 55; + + /** Invalid request code */ + final static int EBADRQC = 56; + + /** Invalid slot */ + final static int EBADSLT = 57; + + /** Bad font file format */ + final static int EBFONT = 59; + + /** Device not a stream */ + final static int ENOSTR = 60; + + /** No data available */ + final static int ENODATA = 61; + + /** Timer expired */ + final static int ETIME = 62; + + /** Out of streams resources */ + final static int ENOSR = 63; + + /** Machine is not on the network */ + final static int ENONET = 64; + + /** Package not installed */ + final static int ENOPKG = 65; + + /** Object is remote */ + final static int EREMOTE = 66; + + /** Link has been severed */ + final static int ENOLINK = 67; + + /** Advertise error */ + final static int EADV = 68; + + /** Srmount error */ + final static int ESRMNT = 69; + + /** Communication error on send */ + final static int ECOMM = 70; + + /** Protocol error */ + final static int EPROTO = 71; + + /** Multihop attempted */ + final static int EMULTIHOP = 72; + + /** RFS specific error */ + final static int EDOTDOT = 73; + + /** Not a data message */ + final static int EBADMSG = 74; + + /** Value too large for defined data type */ + final static int EOVERFLOW = 75; + + /** Name not unique on network */ + final static int ENOTUNIQ = 76; + + /** File descriptor in bad state */ + final static int EBADFD = 77; + + /** Remote address changed */ + final static int EREMCHG = 78; + + /** Can not access a needed shared library */ + final static int ELIBACC = 79; + + /** Accessing a corrupted shared library */ + final static int ELIBBAD = 80; + + /** .lib section in a.out corrupted */ + final static int ELIBSCN = 81; + + /** Attempting to link in too many shared libraries */ + final static int ELIBMAX = 82; + + /** Cannot exec a shared library directly */ + final static int ELIBEXEC = 83; + + /** Illegal byte sequence */ + final static int EILSEQ = 84; + + /** Interrupted system call should be restarted */ + final static int ERESTART = 85; + + /** Streams pipe error */ + final static int ESTRPIPE = 86; + + /** Too many users */ + final static int EUSERS = 87; + + /** Socket operation on non-socket */ + final static int ENOTSOCK = 88; + + /** Destination address required */ + final static int EDESTADDRREQ = 89; + + /** Message too long */ + final static int EMSGSIZE = 90; + + /** Protocol wrong type for socket */ + final static int EPROTOTYPE = 91; + + /** Protocol not available */ + final static int ENOPROTOOPT = 92; + + /** Protocol not supported */ + final static int EPROTONOSUPPORT = 93; + + /** Socket type not supported */ + final static int ESOCKTNOSUPPORT = 94; + + /** Operation not supported on transport endpoint */ + final static int EOPNOTSUPP = 95; + + /** Protocol family not supported */ + final static int EPFNOSUPPORT = 96; + + /** Address family not supported by protocol */ + final static int EAFNOSUPPORT = 97; + + /** Address already in use */ + final static int EADDRINUSE = 98; + + /** Cannot assign requested address */ + final static int EADDRNOTAVAIL = 99; + + /** Network is down */ + final static int ENETDOWN = 100; + + /** Network is unreachable */ + final static int ENETUNREACH = 101; + + /** Network dropped connection because of reset */ + final static int ENETRESET = 102; + + /** Software caused connection abort */ + final static int ECONNABORTED = 103; + + /** Connection reset by peer */ + final static int ECONNRESET = 104; + + /** No buffer space available */ + final static int ENOBUFS = 105; + + /** Transport endpoint is already connected */ + final static int EISCONN = 106; + + /** Transport endpoint is not connected */ + final static int ENOTCONN = 107; + + /** Cannot send after transport endpoint shutdown */ + final static int ESHUTDOWN = 108; + + /** Too many references: cannot splice */ + final static int ETOOMANYREFS = 109; + + /** Connection timed out */ + final static int ETIMEDOUT = 110; + + /** Connection refused */ + final static int ECONNREFUSED = 111; + + /** Host is down */ + final static int EHOSTDOWN = 112; + + /** No route to host */ + final static int EHOSTUNREACH = 113; + + /** Operation already in progress */ + final static int EALREADY = 114; + + /** Operation now in progress */ + final static int EINPROGRESS = 115; + + /** Stale NFS file handle */ + final static int ESTALE = 116; + + /** Structure needs cleaning */ + final static int EUCLEAN = 117; + + /** Not a XENIX named type file */ + final static int ENOTNAM = 118; + + /** No XENIX semaphores available */ + final static int ENAVAIL = 119; + + /** Is a named type file */ + final static int EISNAM = 120; + + /** Remote I/O error */ + final static int EREMOTEIO = 121; + + /** Quota exceeded */ + final static int EDQUOT = 122; + + /** No medium found */ + final static int ENOMEDIUM = 123; + + /** Wrong medium type */ + final static int EMEDIUMTYPE = 124; + + /** Operation Canceled */ + final static int ECANCELED = 125; + + /** Required key not available */ + final static int ENOKEY = 126; + + /** Key has expired */ + final static int EKEYEXPIRED = 127; + + /** Key has been revoked */ + final static int EKEYREVOKED = 128; + + /** Key was rejected by service */ + final static int EKEYREJECTED = 129; + + /** Owner died */ + final static int EOWNERDEAD = 130; + + /** State not recoverable */ + final static int ENOTRECOVERABLE = 131; + } + + static interface mman { + /** Page can be read */ + public final static int PROT_READ = 0x1; + + /** Page can be written */ + public final static int PROT_WRITE = 0x2; + + /** Page can be executed */ + public final static int PROT_EXEC = 0x4; + + /** Map pages that are shared between processes */ + public final static int MAP_SHARED = 0x1; + + /** Map pages without sharing them */ + public final static int MAP_PRIVATE = 0x2; + + /** Don't use a file */ + public final static int MAP_ANONYMOUS = 0x20; + } + + /** + * Class capturing file control (fcntl) constants + */ + static interface fcntl { + 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; + } + +} Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-26 20:27:47 UTC (rev 94) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-27 15:03:23 UTC (rev 95) @@ -19,6 +19,7 @@ import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; import org.binarytranslator.generic.os.abi.linux.files.WriteableFile; import org.binarytranslator.generic.os.abi.linux.files.OpenFileList.InvalidFileDescriptor; +import org.binarytranslator.generic.os.abi.linux.LinuxConstants.*; import java.io.File; import java.io.FileNotFoundException; @@ -35,13 +36,13 @@ * The source of the system calls */ protected LinuxSystemCallGenerator src; - + /** Allows access to the system call's arguments */ protected LinuxSystemCallGenerator.CallArgumentIterator arguments; - + /** Allows access to a number of operating-system specific structures. */ protected LinuxStructureFactory structures; - + /** List of currently opened files. */ private OpenFileList openFiles; @@ -54,7 +55,7 @@ * Array to de-multiplex Linux system calls. NB we will have to * handle IA32 call gates entry at some point */ - protected SystemCall systemCallTable[]; + protected SystemCall systemCallTable[] = new SystemCall[MAX_SYSCALLS]; /** * The name for this system given by uname @@ -62,33 +63,35 @@ protected String getSysName() { return "Linux"; } + /** * The release for this system given by uname */ protected String getRelease() { return "2.6.13"; } + /** * The version for this system given by uname */ protected String getVersion() { return "#1"; } + /** * The machine for this system given by uname */ protected abstract String getMachine(); - /** - * Load an ASCIIZ string from the memory of the system call - * generator and return it as a Java String. - * @param address where to read - * @return the String read - */ + * Load an ASCIIZ string from the memory of the system call + * generator and return it as a Java String. + * @param address where to read + * @return the String read + */ private String memoryReadString(int address) { Memory m = src.getProcessSpace().memory; - + StringBuffer str = new StringBuffer(); char c; @@ -97,20 +100,20 @@ return str.toString(); } - + /** - * Store an ASCIIZ string to the memory of the system call generator - * @param address where to read - * @param data the String to write - */ + * Store an ASCIIZ string to the memory of the system call generator + * @param address where to read + * @param data the String to write + */ public void memoryWriteString(int address, String data) { Memory m = src.getProcessSpace().memory; - + if (data != null) { for (int i = 0; i < data.length(); i++) { - m.store8(address + i, (byte) data.charAt(i)); + m.store8(address + i, (byte) data.charAt(i)); } - + m.store8(address + data.length(), (byte) 0); } } @@ -120,19 +123,19 @@ */ public LinuxSystemCalls(LinuxSystemCallGenerator src) { this.src = src; - systemCallTable = new SystemCall[MAX_SYSCALLS]; UnknownSystemCall USC = new UnknownSystemCall(); - for(int i=0; i < MAX_SYSCALLS; i++) { + for (int i = 0; i < MAX_SYSCALLS; i++) { systemCallTable[i] = USC; } - + openFiles = new OpenFileList(); - - if (openFiles.open(new ConsoleIn(), 0) != 0 || - openFiles.open(new ConsoleOut(System.out), 1) != 1 || - openFiles.open(new ConsoleOut(System.err), 2) != 2) { - - throw new RuntimeException("File descriptors for standard streams could not be assigned correctly."); + + if (openFiles.open(new ConsoleIn(), 0) != 0 + || openFiles.open(new ConsoleOut(System.out), 1) != 1 + || openFiles.open(new ConsoleOut(System.err), 2) != 2) { + + throw new RuntimeException( + "File descriptors for standard streams could not be assigned correctly."); } structures = new LinuxStructureFactory(); @@ -144,328 +147,21 @@ */ public void doSysCall() { int sysCallNumber = src.getSysCallNumber(); - System.err.println("Syscall "+ sysCallToString(sysCallNumber)); + System.err.println("Syscall " + sysCallToString(sysCallNumber)); arguments = src.getSysCallArguments(); systemCallTable[sysCallNumber].doSysCall(); } - + /** * Turn the given system call number into a string describing its * function */ abstract public String sysCallToString(int syscall); - /** - * Class capturing errno constants - */ - private final static class errno { - /** Operation not permitted */ - final static int EPERM=1; - /** No such file or directory */ - final static int ENOENT=2; - /** No such process */ - final static int ESRCH=3; - /** Interrupted system call */ - final static int EINTR=4; - /** I/O error */ - final static int EIO=5; - /** No such device or address */ - final static int ENXIO=6; - /** Argument list too long */ - final static int E2BIG=7; - /** Exec format error */ - final static int ENOEXEC=8; - /** Bad file number */ - final static int EBADF=9; - /** No child processes */ - final static int ECHILD=10; - /** Try again */ - final static int EAGAIN=11; - /** Out of memory */ - final static int ENOMEM=12; - /** Permission denied */ - final static int EACCES=13; - /** Bad address */ - final static int EFAULT=14; - /** Block device required */ - final static int ENOTBLK=15; - /** Device or resource busy */ - final static int EBUSY=16; - /** File exists */ - final static int EEXIST=17; - /** Cross-device link */ - final static int EXDEV=18; - /** No such device */ - final static int ENODEV=19; - /** Not a directory */ - final static int ENOTDIR=20; - /** Is a directory */ - final static int EISDIR=21; - /** Invalid argument */ - final static int EINVAL=22; - /** File table overflow */ - final static int ENFILE=23; - /** Too many open files */ - final static int EMFILE=24; - /** Not a typewriter */ - final static int ENOTTY=25; - /** Text file busy */ - final static int ETXTBSY=26; - /** File too large */ - final static int EFBIG=27; - /** No space left on device */ - final static int ENOSPC=28; - /** Illegal seek */ - final static int ESPIPE=29; - /** Read-only file system */ - final static int EROFS=30; - /** Too many links */ - final static int EMLINK=31; - /** Broken pipe */ - final static int EPIPE=32; - /** Math argument out of domain of func */ - final static int EDOM=33; - /** Math result not representable */ - final static int ERANGE=34; - - /** Resource deadlock would occur */ - final static int EDEADLK=35; - final static int EDEADLOCK=EDEADLK; - /** File name too long */ - final static int ENAMETOOLONG=36; - /** No record locks available */ - final static int ENOLCK=37; - /** Function not implemented */ - final static int ENOSYS=38; - /** Directory not empty */ - final static int ENOTEMPTY=39; - /** Too many symbolic links encountered */ - final static int ELOOP=40; - /** Operation would block */ - final static int EWOULDBLOCK=EAGAIN; - /** No message of desired type */ - final static int ENOMSG=42; - /** Identifier removed */ - final static int EIDRM=43; - /** Channel number out of range */ - final static int ECHRNG=44; - /** Level 2 not synchronized */ - final static int EL2NSYNC=45; - /** Level 3 halted */ - final static int EL3HLT=46; - /** Level 3 reset */ - final static int EL3RST=47; - /** Link number out of range */ - final static int ELNRNG=48; - /** Protocol driver not attached */ - final static int EUNATCH=49; - /** No CSI structure available */ - final static int ENOCSI=50; - /** Level 2 halted */ - final static int EL2HLT=51; - /** Invalid exchange */ - final static int EBADE=52; - /** Invalid request descriptor */ - final static int EBADR=53; - /** Exchange full */ - final static int EXFULL=54; - /** No anode */ - final static int ENOANO=55; - /** Invalid request code */ - final static int EBADRQC=56; - /** Invalid slot */ - final static int EBADSLT=57; - - /** Bad font file format */ - final static int EBFONT=59; - /** Device not a stream */ - final static int ENOSTR=60; - /** No data available */ - final static int ENODATA=61; - /** Timer expired */ - final static int ETIME=62; - /** Out of streams resources */ - final static int ENOSR=63; - /** Machine is not on the network */ - final static int ENONET=64; - /** Package not installed */ - final static int ENOPKG=65; - /** Object is remote */ - final static int EREMOTE=66; - /** Link has been severed */ - final static int ENOLINK=67; - /** Advertise error */ - final static int EADV=68; - /** Srmount error */ - final static int ESRMNT=69; - /** Communication error on send */ - final static int ECOMM=70; - /** Protocol error */ - final static int EPROTO=71; - /** Multihop attempted */ - final static int EMULTIHOP=72; - /** RFS specific error */ - final static int EDOTDOT=73; - /** Not a data message */ - final static int EBADMSG=74; - /** Value too large for defined data type */ - final static int EOVERFLOW=75; - /** Name not unique on network */ - final static int ENOTUNIQ=76; - /** File descriptor in bad state */ - final static int EBADFD=77; - /** Remote address changed */ - final static int EREMCHG=78; - /** Can not access a needed shared library */ - final static int ELIBACC=79; - /** Accessing a corrupted shared library */ - final static int ELIBBAD=80; - /** .lib section in a.out corrupted */ - final static int ELIBSCN=81; - /** Attempting to link in too many shared libraries */ - final static int ELIBMAX=82; - /** Cannot exec a shared library directly */ - final static int ELIBEXEC=83; - /** Illegal byte sequence */ - final static int EILSEQ=84; - /** Interrupted system call should be restarted */ - final static int ERESTART=85; - /** Streams pipe error */ - final static int ESTRPIPE=86; - /** Too many users */ - final static int EUSERS=87; - /** Socket operation on non-socket */ - final static int ENOTSOCK=88; - /** Destination address required */ - final static int EDESTADDRREQ=89; - /** Message too long */ - final static int EMSGSIZE=90; - /** Protocol wrong type for socket */ - final static int EPROTOTYPE=91; - /** Protocol not available */ - final static int ENOPROTOOPT=92; - /** Protocol not supported */ - final static int EPROTONOSUPPORT=93; - /** Socket type not supported */ - final static int ESOCKTNOSUPPORT=94; - /** Operation not supported on transport endpoint */ - final static int EOPNOTSUPP=95; - /** Protocol family not supported */ - final static int EPFNOSUPPORT=96; - /** Address family not supported by protocol */ - final static int EAFNOSUPPORT=97; - /** Address already in use */ - final static int EADDRINUSE=98; - /** Cannot assign requested address */ - final static int EADDRNOTAVAIL=99; - /** Network is down */ - final static int ENETDOWN=100; - /** Network is unreachable */ - final static int ENETUNREACH=101; - /** Network dropped connection because of reset */ - final static int ENETRESET=102; - /** Software caused connection abort */ - final static int ECONNABORTED=103; - /** Connection reset by peer */ - final static int ECONNRESET=104; - /** No buffer space available */ - final static int ENOBUFS=105; - /** Transport endpoint is already connected */ - final static int EISCONN=106; - /** Transport endpoint is not connected */ - final static int ENOTCONN=107; - /** Cannot send after transport endpoint shutdown */ - final static int ESHUTDOWN=108; - /** Too many references: cannot splice */ - final static int ETOOMANYREFS=109; - /** Connection timed out */ - final static int ETIMEDOUT=110; - /** Connection refused */ - final static int ECONNREFUSED=111; - /** Host is down */ - final static int EHOSTDOWN=112; - /** No route to host */ - final static int EHOSTUNREACH=113; - /** Operation already in progress */ - final static int EALREADY=114; - /** Operation now in progress */ - final static int EINPROGRESS=115; - /** Stale NFS file handle */ - final static int ESTALE=116; - /** Structure needs cleaning */ - final static int EUCLEAN=117; - /** Not a XENIX named type file */ - final static int ENOTNAM=118; - /** No XENIX semaphores available */ - final static int ENAVAIL=119; - /** Is a named type file */ - final static int EISNAM=120; - /** Remote I/O error */ - final static int EREMOTEIO=121; - /** Quota exceeded */ - final static int EDQUOT=122; - - /** No medium found */ - final static int ENOMEDIUM=123; - /** Wrong medium type */ - final static int EMEDIUMTYPE=124; - /** Operation Canceled */ - final static int ECANCELED=125; - /** Required key not available */ - final static int ENOKEY=126; - /** Key has expired */ - final static int EKEYEXPIRED=127; - /** Key has been revoked */ - final static int EKEYREVOKED=128; - /** Key was rejected by service */ - final static int EKEYREJECTED=129; - - /** Owner died */ - final static int EOWNERDEAD=130; - /** State not recoverable */ - final static int ENOTRECOVERABLE=131; - } - - /** - * Class capturing file control (fcntl) constants - */ - private final static class fcntl { - 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; - } - - /** - * Class capturing memory management constants - */ - private final static class mman { - /** Page can be read */ - public final static int PROT_READ=0x1; - /** Page can be written */ - public final static int PROT_WRITE=0x2; - /** Page can be executed */ - public final static int PROT_EXEC=0x4; - /** Map pages that are shared between processes */ - public final static int MAP_SHARED = 0x1; - /** Map pages without sharing them */ - public final static int MAP_PRIVATE = 0x2; - /** Don't use a file */ - public final static int MAP_ANONYMOUS=0x20; - } - - /** - * Define the system call interface - */ + /** Base class for all system calls. */ public abstract class SystemCall { - /** - * Handle a system call - */ + + /** Handle a system call */ public abstract void doSysCall(); } @@ -479,10 +175,10 @@ public void doSysCall() { if (!DBT_Options.unimplementedSystemCallsFatal) { src.setSysCallError(errno.ENOSYS); + } else { + throw new Error("System Call " + + sysCallToString(src.getSysCallNumber()) + " Unknown"); } - else { - throw new Error("System Call " + sysCallToString(src.getSysCallNumber()) + " Unknown"); - } } } @@ -504,27 +200,25 @@ int fd = arguments.nextInt(); int buf = arguments.nextInt(); int count = arguments.nextInt(); - + Memory mem = src.getProcessSpace().memory; - + try { //get the file from the file descriptor table ReadableFile file = openFiles.getRead(fd); byte[] buffer = new byte[count]; - + //try to fill the buffer from the file int readBytes = file.read(buffer); - + //copy the filled buffer into the memory for (int i = 0; i < readBytes; i++) mem.store8(buf++, buffer[i]); - + src.setSysCallReturn(readBytes); - } - catch (InvalidFileDescriptor e) { + } catch (InvalidFileDescriptor e) { src.setSysCallError(errno.EBADF); - } - catch (Exception e) { + } catch (Exception e) { src.setSysCallError(errno.EIO); } } @@ -538,26 +232,24 @@ int fd = arguments.nextInt(); int buf = arguments.nextInt(); int count = arguments.nextInt(); - + Memory mem = src.getProcessSpace().memory; - + try { //get the file from the file descriptor table WriteableFile file = openFiles.getWrite(fd); - + //load the supplied buffer from memory byte[] buffer = new byte[count]; for (int i = 0; i < count; i++) - buffer[i] = (byte)mem.loadUnsigned8(buf++); - + buffer[i] = (byte) mem.loadUnsigned8(buf++); + //write that buffer to the file file.write(buffer); src.setSysCallReturn(count); - } - catch (InvalidFileDescriptor e) { + } catch (InvalidFileDescriptor e) { src.setSysCallError(errno.EBADF); - } - catch (Exception e) { + } catch (Exception e) { src.setSysCallError(errno.EIO); } } @@ -567,40 +259,38 @@ * Write data into multiple buffers */ public class SysWriteV extends SystemCall { - public void doSysCall() { + public void doSysCall() { int fd = arguments.nextInt(); int vector = arguments.nextInt(); int count = arguments.nextInt(); Memory mem = src.getProcessSpace().memory; - + try { //get the file from the file descriptor table WriteableFile file = openFiles.getWrite(fd); int bytesWritten = 0; - + //for each of the supplied buffers... for (int n = 0; n < count; n++) { //get the base address & length for the current buffer int base = mem.load32(vector); - int len = mem.load32(vector + 4); + int len = mem.load32(vector + 4); vector += 8; - + //read the buffer from memory byte[] buffer = new byte[len]; for (int i = 0; i < count; i++) - buffer[i] = (byte)mem.loadUnsigned8(base + i); - + buffer[i] = (byte) mem.loadUnsigned8(base + i); + //and write it to the file file.write(buffer); bytesWritten += len; } - + src.setSysCallReturn(bytesWritten); - } - catch (InvalidFileDescriptor e) { + } catch (InvalidFileDescriptor e) { src.setSysCallError(errno.EBADF); - } - catch (Exception e) { + } catch (Exception e) { src.setSysCallError(errno.EIO); } } @@ -614,20 +304,18 @@ // Examine the flags argument and open read or read-write // accordingly. args[0] points to the file name. String fileName = memoryReadString(pathname); - + // Create a File object so we can test for the existance and // properties of the file. File testFile = new File(fileName); - - if(((flags & fcntl.O_CREAT) != 0) && - ((flags & fcntl.O_EXCL) != 0) && - testFile.exists()) { + + if (((flags & fcntl.O_CREAT) != 0) && ((flags & fcntl.O_EXCL) != 0) + && testFile.exists()) { // O_CREAT specified. If O_EXCL also specified, we require // that the file does not already exist src.setSysCallError(errno.EEXIST); return; - } - else if(((flags & fcntl.O_CREAT) != 0) && !testFile.exists()) { + } else if (((flags & fcntl.O_CREAT) != 0) && !testFile.exists()) { // O_CREAT not specified. We require that the file exists. src.setSysCallError(errno.ENOENT); return; @@ -637,19 +325,17 @@ try { RandomAccessFile raFile; int fd; - - if((flags & 0x3) == fcntl.O_RDONLY) { + + if ((flags & 0x3) == fcntl.O_RDONLY) { raFile = new RandomAccessFile(fileName, "r"); - fd = openFiles.open( HostFile.forReading(raFile) ); - } - else { + fd = openFiles.open(HostFile.forReading(raFile)); + } else { // NB Java RandomAccessFile has no write only - raFile = new RandomAccessFile(fileName, "rw"); - fd = openFiles.open( HostFile.forWriting(raFile) ); + raFile = new RandomAccessFile(fileName, "rw"); + fd = openFiles.open(HostFile.forWriting(raFile)); } src.setSysCallReturn(fd); - } - catch(FileNotFoundException e) { + } catch (FileNotFoundException e) { System.err.println("Open tried to open non-existent file: " + fileName); src.setSysCallError(errno.ENOENT); return; @@ -657,27 +343,29 @@ // 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 | 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)); + 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)); } } } - + public class SysClose extends SystemCall { public void doSysCall() { int fd = arguments.nextInt(); - + try { OpenFile f = openFiles.get(fd); f.close(); - } - catch (InvalidFileDescriptor e) { + } catch (InvalidFileDescriptor e) { src.setSysCallError(errno.EBADF); - } - catch (IOException e) { + } catch (IOException e) { src.setSysCallError(errno.EIO); } } @@ -710,56 +398,56 @@ public class SysBrk extends SystemCall { public void doSysCall() { int brk = arguments.nextInt(); - if(brk != 0) { + if (brk != 0) { // Request to set the current top of bss. src.setBrk(brk); } - src.setSysCallReturn(src.getBrk()); + src.setSysCallReturn(src.getBrk()); } } public class SysFstat64 extends SystemCall { public void doSysCall() { int fd = arguments.nextInt(); - + LinuxStructureFactory.stat64 buf = structures.new_stat64(); - + if (fd == 0 || fd == 1 || fd == 2) { buf.st_mode = 0x2180; - buf.st_rdev = (short)0x8800; + buf.st_rdev = (short) 0x8800; buf.__st_ino = buf.st_ino = 2; buf.st_blksize = 0x400; - } - else + } else throw new RuntimeException("Unimplemented system call."); - + buf.write(src.getProcessSpace().memory, arguments.nextInt()); src.setSysCallReturn(0); } } - + public class SysStat64 extends SystemCall { @Override public void doSysCall() { int ptrFilename = arguments.nextInt(); int ptrStruct64 = arguments.nextInt(); - + String filename = memoryReadString(ptrFilename); - - if (DBT_Options.debugSyscallMore) System.err.println("Stat64() denies existance of file: " + filename); + + if (DBT_Options.debugSyscallMore) + System.err.println("Stat64() denies existance of file: " + filename); src.setSysCallError(errno.ENOENT); } - + } - + 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."); @@ -770,36 +458,33 @@ public void doSysCall() { // Simple uname support int addr = arguments.nextInt(); - + if (addr != 0) { String localhostString, domainName, hostName; try { InetAddress localhost = InetAddress.getLocalHost(); localhostString = localhost.getHostName(); - } - catch (UnknownHostException e) { + } catch (UnknownHostException e) { localhostString = "localhost.localdomain"; } int index = localhostString.indexOf('.'); if (index == -1) { domainName = null; hostName = localhostString; - } - else { + } else { domainName = localhostString.substring(index + 1); - hostName = localhostString.substring(0,index); + hostName = localhostString.substring(0, index); } - + // Fill in utsname struct - see /usr/include/sys/utsname.h - memoryWriteString (addr, getSysName()); // sysname - memoryWriteString (addr+65, hostName); // nodename - memoryWriteString (addr+130, getRelease()); // release - memoryWriteString (addr+195, getVersion()); // version - memoryWriteString (addr+260, getMachine()); // machine - memoryWriteString (addr+325, domainName); // __domainname + memoryWriteString(addr, getSysName()); // sysname + memoryWriteString(addr + 65, hostName); // nodename + memoryWriteString(addr + 130, getRelease()); // release + memoryWriteString(addr + 195, getVersion()); // version + memoryWriteString(addr + 260, getMachine()); // machine + memoryWriteString(addr + 325, domainName); // __domainname src.setSysCallReturn(0); - } - else { + } else { // attempt to write to address 0 src.setSysCallError(errno.EFAULT); } @@ -815,31 +500,28 @@ int flags = arguments.nextInt(); int fd = arguments.nextInt(); int offset = arguments.nextInt(); - - if((flags & mman.MAP_ANONYMOUS) != 0 ) { - + + if ((flags & mman.MAP_ANONYMOUS) != 0) { + if ((flags & mman.MAP_SHARED) != 0) throw new Error("Mapping of shared pages is currently not supported."); - + //Anonymous private mappings just request memory. //Ignore the file descriptor and offset, map the required amount of memory and //return the address of the mapped memory; addr = 0; - + try { Memory mem = src.getProcessSpace().memory; - addr = mem.map(addr, length, - (prot & mman.PROT_READ) != 0, - (prot & mman.PROT_WRITE) != 0, - (prot & mman.PROT_EXEC) != 0); - + addr = mem.map(addr, length, (prot & mman.PROT_READ) != 0, + (prot & mman.PROT_WRITE) != 0, (prot & mman.PROT_EXEC) != 0); + src.setSysCallReturn(addr); - } - catch (MemoryMapException e) { + } catch (MemoryMapException e) { throw new Error("Error in mmap", e); } } else { - throw new Error("Non-anonymous sys_mmap not yet implemented."); + throw new Error("Non-anonymous sys_mmap not yet implemented."); } } } @@ -849,7 +531,7 @@ int start = arguments.nextInt(); int length = arguments.nextInt(); - + src.getProcessSpace().memory.unmap(start, length); src.setSysCallReturn(0); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-26 20:27:45
|
Revision: 94 http://svn.sourceforge.net/pearcolator/?rev=94&view=rev Author: michael_baer Date: 2007-04-26 13:27:47 -0700 (Thu, 26 Apr 2007) Log Message: ----------- - Introduced processor mode handling to the ARM interpreter - Fixed decoder bug related to BLX - Several minor ARM fixes - First interpreter version that can run an ARM monitor 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/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.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/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/memory/AutoMappingMemory.java src/org/binarytranslator/generic/memory/DebugMemory.java src/org/binarytranslator/generic/memory/MemoryMapException.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-26 20:27:47 UTC (rev 94) @@ -357,7 +357,7 @@ public void visit(BranchExchange instr) { String mnemonic = instr.link ? "BLX" : "BX"; - setResult(String.format("%s%s #%d", mnemonic, cond(instr), operand(instr + setResult(String.format("%s%s #%s", mnemonic, cond(instr), operand(instr .target()))); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-26 20:27:47 UTC (rev 94) @@ -69,7 +69,8 @@ return factory.createMoveFromStatusRegister(instr); } - if (bits_7_4 == 1 && ((instr & 0x01F00000) == 0x01200000)) { + if (((bits_7_4 & 0xD) == 1) && ((instr & 0x01F00000) == 0x01200000)) { + //bits 7-4 == 1 || bits 7-4 == 3 //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 22) == false && Utils.getBit(instr, 21) == true && Utils.getBit(instr, 20) == false return factory.createBranchExchange(instr); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-26 20:27:47 UTC (rev 94) @@ -1157,7 +1157,7 @@ sourceOperand = OperandWrapper.decodeDataProcessingOperand(instr); } - /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ + /** Identifies the PSR that is to be overwritten: true for the SPSR, false for the CPSR. */ public final boolean transferSavedPSR() { return transferSavedPSR; } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-26 20:27:47 UTC (rev 94) @@ -7,6 +7,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; import org.binarytranslator.generic.decoder.Interpreter; import com.sun.org.apache.bcel.internal.generic.InstructionFactory; @@ -48,6 +49,288 @@ return instruction; } + + private abstract static class ResolvedOperand { + + protected int value; + + public static ResolvedOperand resolveWithShifterCarryOut(ARM_Registers regs, OperandWrapper operand) { + ResolvedOperand result = new ResolvedOperand_WithShifterCarryOut(regs, operand); + return result; + } + + public static int resolve(ARM_Registers regs, OperandWrapper operand) { + ResolvedOperand result = new ResolvedOperand_WithoutShifterCarryOut(regs, operand); + return result.getValue(); + } + + public final int getValue() { + return value; + } + + public abstract boolean getShifterCarryOut(); + + private static class ResolvedOperand_WithoutShifterCarryOut + extends ResolvedOperand{ + + private ResolvedOperand_WithoutShifterCarryOut(ARM_Registers regs, OperandWrapper operand) { + _resolve(regs, operand); + } + + public boolean getShifterCarryOut() { + throw new RuntimeException("This class does not provide a shifter carry out value."); + } + + private void _resolve(ARM_Registers regs, OperandWrapper operand) { + + switch (operand.getType()) { + case Immediate: + value = operand.getImmediate(); + return; + + case Register: + int reg = operand.getRegister(); + + //mind the arm pc offset + value = regs.get(reg); + + if (reg == 15) + value += 8; + + return; + + case RegisterShiftedRegister: + case ImmediateShiftedRegister: + value = resolveShift(regs, operand); + return; + + case PcRelative: + value = regs.get(ARM_Registers.PC) + 8 + operand.getOffset(); + break; + + default: + throw new RuntimeException("Unexpected wrapped operand type: " + + operand.getType()); + } + } + + /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift + * and set the result of the barrel shifter accordingly. */ + private final int resolveShift(ARM_Registers regs, OperandWrapper operand) { + if (DBT.VerifyAssertions) + DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || + operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); + + int value = regs.get(operand.getRegister()); + + //consider the "usual" ARM program counter offset + if (operand.getRegister() == ARM_Registers.PC) + value += 8; + + 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) { + return Utils.getBit(value, 31) ? 0xFFFFFFFF : 0; + } + return value >> shiftAmount; + + case LSL: + + if (shiftAmount >= 32) { + return 0; + } + + return value << shiftAmount; + + case LSR: + + if (shiftAmount >= 32) { + return 0; + } + + return value >>> shiftAmount; + + case ROR: + return Integer.rotateRight(value, shiftAmount); + + case RRE: + if (regs.isCarrySet()) + return (value >> 1) | 0x80000000; + else + return value >> 1; + + default: + throw new RuntimeException("Unexpected shift type: " + + operand.getShiftType()); + } + } + } + + private static class ResolvedOperand_WithShifterCarryOut + extends ResolvedOperand{ + + private boolean shifterCarryOut; + + private ResolvedOperand_WithShifterCarryOut(ARM_Registers regs, OperandWrapper operand) { + _resolve(regs, operand); + } + + public boolean getShifterCarryOut() { + return shifterCarryOut; + } + + private void _resolve(ARM_Registers regs, OperandWrapper operand) { + + switch (operand.getType()) { + case Immediate: + value = operand.getImmediate(); + + if (operand.getShiftAmount() == 0) + shifterCarryOut = regs.isCarrySet(); + else + shifterCarryOut = (value & 0x80000000) != 0; + + return; + + case Register: + shifterCarryOut = regs.isCarrySet(); + int reg = operand.getRegister(); + + //mind the arm pc offset + value = regs.get(reg); + + if (reg == 15) + value += 8; + + return; + + case RegisterShiftedRegister: + case ImmediateShiftedRegister: + value = resolveShift(regs, operand); + return; + + case PcRelative: + throw new RuntimeException("This operand type does not produce a shifter carry out."); + + default: + throw new RuntimeException("Unexpected wrapped operand type: " + + operand.getType()); + } + } + + /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift + * and set the result of the barrel shifter accordingly. */ + private final int resolveShift(ARM_Registers regs, OperandWrapper operand) { + if (DBT.VerifyAssertions) + DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || + operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); + + int value = regs.get(operand.getRegister()); + + //consider the "usual" ARM program counter offset + if (operand.getRegister() == ARM_Registers.PC) + value += 8; + + 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) { + shifterCarryOut = Utils.getBit(value, 31); + return shifterCarryOut ? 0xFFFFFFFF : 0; + } + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } + + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >> shiftAmount; + + case LSL: + + if (shiftAmount > 32) { + shifterCarryOut = false; + return 0; + } + + if (shiftAmount == 32) { + shifterCarryOut = Utils.getBit(value, 31); + return 0; + } + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } + + shifterCarryOut = Utils.getBit(value, 32 - shiftAmount); + return value << shiftAmount; + + case LSR: + + if (shiftAmount > 32) { + shifterCarryOut = false; + return 0; + } + + if (shiftAmount == 32) { + shifterCarryOut = Utils.getBit(value, 31); + return 0; + } + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } + + 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()); + } + } + } + } + /** All ARM interpreter instructions implement this interface. */ private interface ARM_Instruction extends Interpreter.Instruction { /** Returns the condition, under which the given instruction will be executed. */ @@ -164,105 +447,8 @@ /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift * and set the result of the barrel shifter accordingly. */ - private final int resolveShift(OperandWrapper operand) { - if (DBT.VerifyAssertions) - DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || - operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); - int value = regs.get(operand.getRegister()); - - //consider the "usual" ARM program counter offset - if (operand.getRegister() == ARM_Registers.PC) - value += 8; - - 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) { - shifterCarryOut = Utils.getBit(value, 31); - return shifterCarryOut ? 0xFFFFFFFF : 0; - } - - if (shiftAmount == 0) { - shifterCarryOut = regs.isCarrySet(); - return value; - } - - shifterCarryOut = Utils.getBit(value, shiftAmount - 1); - return value >> shiftAmount; - - case LSL: - - if (shiftAmount > 32) { - shifterCarryOut = false; - return 0; - } - - if (shiftAmount == 32) { - shifterCarryOut = Utils.getBit(value, 31); - return 0; - } - - if (shiftAmount == 0) { - shifterCarryOut = regs.isCarrySet(); - return value; - } - - shifterCarryOut = Utils.getBit(value, 32 - shiftAmount); - return value << shiftAmount; - - case LSR: - - if (shiftAmount > 32) { - shifterCarryOut = false; - return 0; - } - - if (shiftAmount == 32) { - shifterCarryOut = Utils.getBit(value, 31); - return 0; - } - - if (shiftAmount == 0) { - shifterCarryOut = regs.isCarrySet(); - return value; - } - - 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()); - } - } - /** Returns the value of operand 1 of the data processing instruction. This is always a register value. * However, deriving classes may alter this behavior, for example to return a negative register * value for a RSB instruction. */ @@ -277,38 +463,9 @@ /** Returns the value of the rhs-operand of the data processing instruction. */ 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; - - return value; - - case Register: - shifterCarryOut = regs.isCarrySet(); - int reg = operand2.getRegister(); - - //mind the arm pc offset - if (reg == 15) - return regs.get(reg) + 8; - else - return regs.get(operand2.getRegister()); - - case RegisterShiftedRegister: - case ImmediateShiftedRegister: - return resolveShift(operand2); - - case PcRelative: - default: - throw new RuntimeException("Unexpected wrapped operand type: " - + operand2.getType()); - } + ResolvedOperand resolvedOperand2 = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); + shifterCarryOut = resolvedOperand2.getShifterCarryOut(); + return resolvedOperand2.getValue(); } public abstract void execute(); @@ -675,17 +832,26 @@ 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)); + if (swapByte) { + int tmp = ps.memory.load32(memAddr); + ps.memory.store32(memAddr, regs.get(Rm)); + + //according to the ARM architecture reference, the value loaded from a memory address is rotated + //by the number of ones in the first two bits of the address + regs.set(Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); + } + else { + int tmp = ps.memory.loadUnsigned8(memAddr); + ps.memory.store8(memAddr, regs.get(Rm) & 0xFF); + regs.set(Rm, tmp); + } } public int getSuccessor(int pc) { + //according to the ARM Architecture reference, using the pc as Rd yields an undefined + //result. Therefore, we can safely assume that this instruction never equals a branch return pc + 4; } } @@ -740,10 +906,18 @@ } else { //pre-indexing, forward reading //no need to adjust the start address - } } int nextAddress = startAddress; + + OperatingMode previousMode = ps.registers.getOperatingMode(); + + //if we should transfer the user mode registers... + if (forceUser) { + //... then change the current register map, but do NOT change the current processor mode + ps.registers.switchOperatingMode(OperatingMode.USR); + ps.registers.setOperatingModeWithoutRegisterLayout(previousMode); + } //are we supposed to load or store multiple registers? if (isLoad) { @@ -761,8 +935,22 @@ int newpc = ps.memory.load32(nextAddress); regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); - //shall we switch to thumb mode - regs.setThumbMode((newpc & 0x1) != 0); + if (forceUser) { + //when we are transferring the PC with a forced-user transfer, then we also want to + //restore the CPSR from the SPSR. + //However, at the moment our register layout is different from our operating mode. + //Therefore, sync both first by switching the operating mode to user (which is what our register layout + //is anyway). + regs.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); + regs.restoreSPSR2CPSR(); + + //there is no write-back for this instruction. + return; + } + else { + //shall we switch to thumb mode + regs.setThumbMode((newpc & 0x1) != 0); + } } } else { int nextReg = 0; @@ -780,6 +968,12 @@ } } + //restore the register layout, if we were transferring the user mode registers + if (forceUser) { + ps.registers.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); + ps.registers.switchOperatingMode(previousMode); + } + if (writeBack) { //write the last address we read from back to a register if (!incrementBase) { @@ -961,7 +1155,69 @@ return pc + 4; } } + + private final class MoveToStatusRegister extends + ARM_Instructions.MoveToStatusRegister implements + ARM_Instruction { + public MoveToStatusRegister(int instr) { + super(instr); + } + + public void execute() { + //this variable is going to receive the new psr, which we will set + int new_psr = ResolvedOperand.resolve(regs, sourceOperand); + + //are we currently in a privileged mode? + boolean inPrivilegedMode = (regs.getOperatingMode() != ARM_Registers.OperatingMode.USR); + + //this variable receives the psr that we're replacing + int old_psr; + + //get the currect value for old_psr + if (transferSavedPSR) { + //if the current mode does not have a SPSR, then do nothing + if (inPrivilegedMode && regs.getOperatingMode() != ARM_Registers.OperatingMode.SYS) + return; + + old_psr = regs.getSPSR(); + } + else { + old_psr = regs.getCPSR(); + } + + //create a new CPSR value according to what pieces of the CPSR we are actually required to set + if (!transferControl || !inPrivilegedMode) { + new_psr &= 0xFFFFFF00; + new_psr |= (old_psr & 0xFF); + } + + if (!transferExtension || !inPrivilegedMode) { + new_psr &= 0xFFFF00FF; + new_psr |= (old_psr & 0xFF00); + } + + if (!transferStatus || !inPrivilegedMode) { + new_psr &= 0xFF00FFFF; + new_psr |= (old_psr & 0xFF0000); + } + + if (!transferFlags) { + new_psr &= 0x00FFFFFF; + new_psr |= (old_psr & 0xFF000000); + } + + if (transferSavedPSR) + regs.setSPSR(new_psr); + else + regs.setCPSR(new_psr); + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + /** Invoke a software interrupt. */ private final class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt implements ARM_Instruction { @@ -992,63 +1248,8 @@ /** Resolves the offset, which is (when post-indexing is not used) to be added to the * base address to create the final address. */ private int resolveOffset() { - int addrOffset; + int addrOffset = ResolvedOperand.resolve(regs, offset); - switch (offset.getType()) { - case Immediate: - addrOffset = offset.getImmediate(); - break; - - case Register: - addrOffset = regs.get(offset.getRegister()); - if (offset.getRegister() == ARM_Registers.PC) { - addrOffset += 8; - } - break; - - case ImmediateShiftedRegister: - addrOffset = regs.get(offset.getRegister()); - - if (offset.getRegister() == 15) - addrOffset += 8; - - switch (offset.getShiftType()) { - case ASR: - addrOffset = addrOffset >> offset.getShiftAmount(); - break; - - case LSL: - addrOffset = addrOffset << offset.getShiftAmount(); - break; - - case LSR: - addrOffset = addrOffset >>> offset.getShiftAmount(); - break; - - case ROR: - addrOffset = Integer.rotateRight(addrOffset, offset.getShiftAmount()); - break; - - case RRE: - if (regs.isCarrySet()) - addrOffset = (addrOffset >> 1) | 0x80000000; - else - addrOffset = addrOffset >> 1; - break; - - default: - throw new RuntimeException("Unexpected shift type: " - + offset.getShiftType()); - } - break; - - case PcRelative: - case RegisterShiftedRegister: - default: - throw new RuntimeException("Unexpected operand type: " - + offset.getType()); - } - if (positiveOffset) return addrOffset; else @@ -1073,11 +1274,12 @@ } public void execute() { - //should we simulate a user-mode memory access? + //should we simulate a user-mode memory access? If yes, store the current mode and fake a switch + //to user mode. + OperatingMode previousMode = null; if (forceUserMode) { - //TODO: Implement user mode memory access - throw new RuntimeException( - "Forced user mode memory access is not yet supported."); + previousMode = ps.registers.getOperatingMode(); + ps.registers.setOperatingModeWithoutRegisterLayout(ARM_Registers.OperatingMode.USR); } //get the address of the memory, that we're supposed access @@ -1088,11 +1290,12 @@ int value; switch (size) { - case Byte: - if (signExtend) - value = ps.memory.loadSigned8(address); - else - value = ps.memory.loadUnsigned8(address); + + case Word: + value = ps.memory.load32(address); + + //according to the ARM reference, the last two bits cause the value to be right-rotated + value = Integer.rotateRight(value, (address & 0x3) * 8); break; case HalfWord: @@ -1102,8 +1305,11 @@ value = ps.memory.loadUnsigned16(address); break; - case Word: - value = ps.memory.load32(address); + case Byte: + if (signExtend) + value = ps.memory.loadSigned8(address); + else + value = ps.memory.loadUnsigned8(address); break; default: @@ -1112,27 +1318,33 @@ //finally, write the variable into a register regs.set(Rd, value); - } else { + } + else { //we are store a value from a register to memory. int value = regs.get(Rd); switch (size) { - case Byte: - ps.memory.store8(address, value); + case Word: + ps.memory.store32(address & 0xFFFFFFFE, value); break; - + case HalfWord: - ps.memory.store16(address, value); + ps.memory.store16(address, value & 0xFFFF); break; - - case Word: - ps.memory.store32(address, value); + + case Byte: + ps.memory.store8(address, value & 0xFF); break; default: throw new RuntimeException("Unexpected memory size: " + size); } } + + //if we were writing in user mode, then switch back to our previous operating mode + if (forceUserMode) { + ps.registers.setOperatingModeWithoutRegisterLayout(previousMode); + } //should the memory address, which we accessed, be written back into a register? //This is used for continuous memory accesses @@ -1160,14 +1372,11 @@ * is executed. */ private final class UndefinedInstruction implements ARM_Instruction { - private final int instruction; - public UndefinedInstruction(int instr) { - this.instruction = instr; } public void execute() { - throw new RuntimeException("Undefined instruction: " + instruction); + ps.doUndefinedInstruction(); } public int getSuccessor(int pc) { @@ -1235,7 +1444,6 @@ return new DataProcessing_Teq(instr); case TST: return new DataProcessing_Tst(instr); - case CLZ: return new DataProcessing_Clz(instr); @@ -1283,6 +1491,7 @@ } public ARM_Instruction createLongMultiply(int instr) { + //TODO: Implement multiplications with longs throw new RuntimeException("Long Multiplications are not yet supported."); } @@ -1291,9 +1500,7 @@ } public ARM_Instruction createMoveToStatusRegister(int instr) { - //TODO: Implement Register -> CPSR transfers - throw new RuntimeException( - "Modifying the status register using MSR is not yet supported."); + return new MoveToStatusRegister(instr); } public ARM_Instruction createSingleDataTransfer(int instr) { 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-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-04-26 20:27:47 UTC (rev 94) @@ -6,8 +6,7 @@ public class ARM_LinuxSystemCalls extends LinuxSystemCalls { - private final ARM_LinuxProcessSpace ps; - + public ARM_LinuxSystemCalls(ARM_LinuxProcessSpace ps, LinuxSystemCallGenerator src) { super(src); @@ -25,6 +24,7 @@ systemCallTable[91] = new LinuxSystemCalls.SysMunmap(); systemCallTable[122] = new LinuxSystemCalls.SysUname(); systemCallTable[146] = new LinuxSystemCalls.SysWriteV(); + systemCallTable[195] = new LinuxSystemCalls.SysStat64(); systemCallTable[197] = new LinuxSystemCalls.SysFstat64(); systemCallTable[199] = new LinuxSystemCalls.SysGetEUID(); systemCallTable[200] = new LinuxSystemCalls.SysGetEGID(); @@ -32,8 +32,7 @@ systemCallTable[202] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[221] = new LinuxSystemCalls.SysFcntl64(); systemCallTable[252] = new LinuxSystemCalls.SysExitGroup(); - - this.ps = ps; + } @Override Modified: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-04-26 20:27:47 UTC (rev 94) @@ -167,7 +167,7 @@ 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"; + previousInputLine += "\n"; } if (DBT.VerifyAssertions) DBT._assert(previousInputLine != null); @@ -344,7 +344,10 @@ char output = (char)ps.memory.loadUnsigned8(ptrOutput++); while (output != 0) { - consoleOutput.print(output); + + if (output != 13) + consoleOutput.print(output); + output = (char)ps.memory.loadUnsigned8(ptrOutput++); } } @@ -428,6 +431,10 @@ try { int value = consoleInput.read(); + //skip #13, because that's what Angel seems to do. + while (value == 13) + value = consoleInput.read(); + if (value == -1) throw new RuntimeException("Unable to read further characters from console"); Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-26 20:27:47 UTC (rev 94) @@ -111,4 +111,15 @@ public String toString() { return registers.toString(); } + + /** + * ARM undefined instruction handler. This method is called when the ARM processor + * is asked to execute an undefined instruction. By default, this throws a runtime exception. + * + * However, derived classes may re-implement this behaviour to achieve full system emulation. + * + */ + public void doUndefinedInstruction() { + throw new RuntimeException("Undefined instruction at 0x" + Integer.toHexString(getCurrentInstructionAddress())); + } } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-26 20:27:47 UTC (rev 94) @@ -58,13 +58,13 @@ * This flag from the CPSR denotes whether IRQs are currently accepted by the * processor. */ - private boolean flagIRQsDisabled = false; + private boolean flagIRQsDisabled = true; /** * This flag from the CPSR denotes whether FIQs are currently accepted by the * processor. */ - private boolean flagFIQsDisabled = false; + private boolean flagFIQsDisabled = true; /** * The operating mode from the CPSR register. Note that only the bottom five @@ -119,18 +119,63 @@ regs[reg] = value; } - public void switchOperatingMode(OperatingMode newMode) { + /** + * Switches the current processor operating mode to <code>newMode</code>, by loading the appropriate + * register layout for the mode and changing the processor's OperatingMode flag. + * During this process, the SPSR of the newMode is replaced with the CPSR of the current mode. + * + * @param newMode + * The operating mode that shall switch to. + */ + public void switchOperatingModeAndStoreSPSR(OperatingMode newMode) { + //get the previous SPSR int previous_cpsr = getCPSR(); + //change the current operating mode + switchOperatingMode(newMode); + + setSPSR(previous_cpsr); + } + + /** + * Sets the current operating mode and loads the register layout for that mode. + * However, the CPSR is not pushed into the new mode's SPSR. + * + * @param newMode + * The operating mode to switch to. + */ + public void switchOperatingMode(OperatingMode newMode) { + //perform the actual mode switch + setRegisterLayout(newMode); + operatingMode = newMode; + } + + /** + * Sets the processor's operating mode without changing the register layout. + * This is useful in certain situations, where a command just "fakes" to be in another mode + * so that the memory is fooled. + * + * @param newMode + */ + public void setOperatingModeWithoutRegisterLayout(OperatingMode newMode) { + operatingMode = newMode; + } + + /** + * Sets the layout of the ARM registers to the layout expected in <code>newMode</code>. + * + * @param newMode + * The mode for which the register layout shall be constructed. + */ + private void setRegisterLayout(OperatingMode newMode) { + //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); + //we don't need to do anything in this case return; } @@ -196,7 +241,7 @@ regs[11] = shadowRegisters[shadowOffset++]; regs[12] = shadowRegisters[shadowOffset++]; } - else if (operatingMode == OperatingMode.USR) { + else if (newMode == OperatingMode.USR) { //skip these shadow registers for now shadowOffset += 5; } @@ -204,14 +249,30 @@ //now load the remaining r13 and r14 registers regs[13] = shadowRegisters[shadowOffset++]; regs[14] = shadowRegisters[shadowOffset]; + } + + /** + * Overwrites the SPSR of the current mode with the supplied value. + * + * @param newSPSR + * The new value, which will replace the current SPSR. + */ + public void setSPSR(int newSPSR) { + //save the previous CPSR as the current SPSR + if (operatingMode == OperatingMode.USR || operatingMode == OperatingMode.SYS) { + //these modes don't have a SPSR, so ignore them + return; + } - //perform the actual mode switch - operatingMode = newMode; - - //save the previous CPSR as the current SPSR - setSPSR(previous_cpsr); + shadowRegisters[operatingMode.SHADOW_OFFSET + SPSR_OFFSET] = newSPSR; } + /** + * Returns the current operating mode. + */ + public OperatingMode getOperatingMode() { + return operatingMode; + } /** * Restores the saved program status register of the current operating mode to the CPSR, @@ -220,8 +281,18 @@ public void restoreSPSR2CPSR() { if (VM.VerifyAssertions) VM._assert(operatingMode != OperatingMode.USR); - setFlagsFromCPSR(getSPSR()); + setCPSR(getSPSR()); } + + /** + * Used to control the processor flag which says if the the processor is accepting interrupt requests. + * + * @param enabled + * Set to true to enable interrupts or false otherwise. + */ + public void setInterruptsEnabled(boolean enabled) { + flagIRQsDisabled = !enabled; + } /** * Returns the content of ARM's Current Program Status Register. @@ -246,20 +317,6 @@ 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. @@ -267,9 +324,9 @@ * @param cpsr * ARM CPSR register content */ - public void setFlagsFromCPSR(int cpsr) { + public void setCPSR(int cpsr) { - //extract teh differnet flags from the PSR + //extract the different flags from the PSR flagNegative = (cpsr & 0x80000000) != 0; //bit 31 flagZero = (cpsr & 0x40000000) != 0; //bit 30 flagCarry = (cpsr & 0x20000000) != 0; //bit 29 @@ -285,6 +342,7 @@ for (OperatingMode opMode : OperatingMode.values()) if (opMode.PSR_IDENTIFIER == mode) { switchOperatingMode(opMode); + break; } if (DBT.VerifyAssertions) DBT._assert(operatingMode.PSR_IDENTIFIER == mode); 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-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-26 20:27:47 UTC (rev 94) @@ -53,11 +53,37 @@ setCurrentInstructionAddress(getCurrentInstructionAddress() + 4); } else { - throw new RuntimeException("Non-Angel system calls are not yet supported."); + //switch the operating mode to Supervisor + registers.switchOperatingModeAndStoreSPSR(ARM_Registers.OperatingMode.SVC); + registers.setInterruptsEnabled(false); + + //put the return address into the link register + registers.set(ARM_Registers.LR, getCurrentInstructionAddress() + 4); + + //jump to the respective SWI handler + setCurrentInstructionAddress(0x8); } } + /** + * This implementation of the undefined instruction handler behaves as + * the ARM processor would: It switches the operating mode, + * jumps to the undefined instruction handler and tries to execute the instruction + * stored there. + */ @Override + public void doUndefinedInstruction() { + registers.switchOperatingModeAndStoreSPSR(ARM_Registers.OperatingMode.SVC); + registers.setInterruptsEnabled(false); + + //put the return address into the link register + registers.set(ARM_Registers.LR, getCurrentInstructionAddress() + 4); + + //jump to the respective SWI handler + setCurrentInstructionAddress(0x4); + } + + @Override public GdbTarget getGdbTarget() { throw new UnsupportedOperationException("GDB not implemented."); } 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-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-26 20:27:47 UTC (rev 94) @@ -71,6 +71,24 @@ registers.set(ARM_Registers.SP, LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector)); } + @Override + protected String[] getEnvironmentVariables() { + return new String[] { "PWD=/root", + "PS1=\\h:\\w\\$", + "USER=root", + "MAIL=/var/mail/root", + "LANG=C", + "SSH_CLIENT=130.88.199.8 54342 22", + "LOGNAME=root", + "SHLVL=1", + "SHELL=/bin/bash", + "HOME=/root", + "TERM=xterm", + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11", + "SSH_TTY=/dev/pts/1", + "_=/usr/bin/env" }; + } + public void dumpStack() { //grab the current frame pointer int fp = registers.get(ARM_Registers.FP); Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-26 20:27:47 UTC (rev 94) @@ -68,13 +68,11 @@ } public void setSysCallError(int r) { - // TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + ps.registers.set(0, -r); } public void setSysCallReturn(int r) { - // TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + ps.registers.set(0, r); } /** An argument iterator that hides the layout of syscall arguments on the ARM architecture */ Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-26 20:27:47 UTC (rev 94) @@ -84,8 +84,7 @@ } public void setSysCallError(int r) { -// TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + ps.registers.set(0, -r); } public void setSysCallReturn(int value) { Modified: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-04-26 20:27:47 UTC (rev 94) @@ -18,10 +18,10 @@ 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(String.format("[0x%x] %s", pc, instruction.toString())); instruction.execute(); + pc = instruction.getSuccessor(pc); if (pc == -1) pc = ps.getCurrentInstructionAddress(); Modified: src/org/binarytranslator/generic/memory/AutoMappingMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-04-26 20:27:47 UTC (rev 94) @@ -60,8 +60,8 @@ return mem.load32(addr); } catch (Exception e) { - ensureMapped(addr, addr + 4); - return load32(addr); + mem.ensureMapped(addr, addr + 4); + return mem.load32(addr); } } @@ -70,8 +70,8 @@ return mem.loadInstruction32(addr); } catch (Exception e) { - ensureMapped(addr, addr + 4); - return loadInstruction32(addr); + mem.ensureMapped(addr, addr + 4); + return mem.loadInstruction32(addr); } } @@ -80,7 +80,7 @@ return mem.loadInstruction8(addr); } catch (Exception e) { - ensureMapped(addr, addr + 1); + mem.ensureMapped(addr, addr + 1); return mem.loadInstruction8(addr); } } @@ -90,7 +90,7 @@ return mem.loadSigned16(addr); } catch (Exception e) { - ensureMapped(addr, addr + 2); + mem.ensureMapped(addr, addr + 2); return mem.loadSigned16(addr); } } @@ -100,7 +100,7 @@ return mem.loadSigned8(addr); } catch (Exception e) { - ensureMapped(addr, addr + 1); + mem.ensureMapped(addr, addr + 1); return mem.loadSigned8(addr); } } @@ -110,7 +110,7 @@ return mem.loadUnsigned16(addr); } catch (Exception e) { - ensureMapped(addr, addr + 2); + mem.ensureMapped(addr, addr + 2); return mem.loadUnsigned16(addr); } } @@ -120,7 +120,7 @@ return mem.loadUnsigned8(addr); } catch (Exception e) { - ensureMapped(addr, addr + 1); + mem.ensureMapped(addr, addr + 1); return mem.loadUnsigned8(addr); } } @@ -138,7 +138,7 @@ mem.store16(addr, value); } catch (Exception e) { - ensureMapped(addr, addr + 2); + mem.ensureMapped(addr, addr + 2); mem.store16(addr, value); } } @@ -148,7 +148,7 @@ mem.store32(addr, value); } catch (Exception e) { - ensureMapped(addr, addr + 4); + mem.ensureMapped(addr, addr + 4); mem.store32(addr, value); } } @@ -158,7 +158,7 @@ mem.store8(addr, value); } catch (Exception e) { - ensureMapped(addr, addr + 1); + mem.ensureMapped(addr, addr + 1); mem.store8(addr, value); } } Modified: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-26 20:27:47 UTC (rev 94) @@ -11,7 +11,6 @@ import java.io.RandomAccessFile; import java.nio.channels.FileChannel; -import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.vmInterface.TranslationHelper; import org.jikesrvm.compilers.opt.ir.OPT_Operand; @@ -79,6 +78,22 @@ private static final int getPTE(int address) { return address >>> OFFSET_BITS; } + + /** + * Ensure memory between start and end is mapped + * @param startAddr starting address for mapped memory + * @param endAddr ending address for mapped memory + */ + @Override + 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, true); + } + } + } /** * Find free consecutive pages @@ -120,11 +135,16 @@ * is the page writable * @param exec * is the page executable + * @return + * The start address of the mapped memory. */ public int map(int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException { // Check that the address is page aligned if ((addr % PAGE_SIZE) != 0) { + MemoryMapException.unalignedAddress(addr); + + /* // if it is not, truncate the address down to the next page boundary and // start mapping from there int validPageCount = addr / PAGE_SIZE; @@ -135,7 +155,7 @@ DBT._assert(oldStartAddress > addr); // we have to map more more memory now to reach the same end address - len += (oldStartAddress - addr); + len += (oldStartAddress - addr);*/ } // Create memory @@ -196,12 +216,6 @@ if ((addr % PAGE_SIZE) != 0) { MemoryMapException.unalignedAddress(addr); } - // Check file offset is page aligned - /* - if ((offset % PAGE_SIZE) != 0) { - MemoryMapException.unalignedFileOffset(offset); - } - */ // Calculate number of pages int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; @@ -257,31 +271,25 @@ throw new Error("Memory map of already mapped location addr=0x" + Integer.toHexString(addr) + " len=" + len); } - // Allocate page - if (read && write) { - readableMemory[pte + i] = file.getChannel().map( - FileChannel.MapMode.READ_WRITE, offset + (i * PAGE_SIZE), - PAGE_SIZE).array(); - writableMemory[pte + i] = readableMemory[pte + i]; - if (exec) { - executableMemory[pte + i] = readableMemory[pte + i]; - } - } else if (read) { - readableMemory[pte + i] = file.getChannel().map( - FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE), - PAGE_SIZE).array(); - if (exec) { - executableMemory[pte + i] = readableMemory[pte + i]; - } - } else if (exec) { - executableMemory[pte + i] = file.getChannel().map( - FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE), - PAGE_SIZE).array(); - } else { - throw new Error("Unable to map address 0x" - + Integer.toHexString(addr) + " with permissions " - + (read ? "r" : "-") + (write ? "w" : "-") + (exec ? "x" : "-")); + + byte[] page; + + if (write) + page = file.getChannel().map(FileChannel.MapMode.READ_WRITE, offset + (i * PAGE_SIZE), PAGE_SIZE).array(); + else + page = file.getChannel().map(FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE), PAGE_SIZE).array(); + + if (write) { + writableMemory[pte + i] = page; } + + if (read) { + readableMemory[pte + 1] = page; + } + + if (exec) { + executableMemory[pte + i] = page; + } } } return addr; Modified: src/org/binarytranslator/generic/memory/MemoryMapException.java =================================================================== --- src/org/binarytranslator/generic/memory/MemoryMapException.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/generic/memory/MemoryMapException.java 2007-04-26 20:27:47 UTC (rev 94) @@ -13,21 +13,20 @@ /** * Captures exceptions that can occur during memory mangement */ -final public class MemoryMapException extends RuntimeException { - /** - * Attempt to allocate on a non-page boundary - */ - private static final int UNALIGNED_ADDRESS = 1; +final public class MemoryMapException + extends RuntimeException { + + public enum Reason { + /** Attempt to allocate on a non-page boundary */ + UNALIGNED_ADDRESS, + /** Attempt to allocate from a file on an unaligned file offset */ + UNALIGNED_FILE_OFFSET + } /** - * Attempt to allocate from a file on an unaligned file offset - */ - private static final int UNALIGNED_FILE_OFFSET = 2; - - /** * The type of this memory map exception */ - private int type; + private Reason reason; /** * The file offset or address that was unaligned @@ -38,36 +37,37 @@ * Throw an unaligned address memory map exception */ static void unalignedAddress(int addr) throws MemoryMapException { - throw new MemoryMapException((long) addr, UNALIGNED_ADDRESS); + throw new MemoryMapException((long) addr, Reason.UNALIGNED_ADDRESS); } /** * Throw an unaligned file offset memory map exception */ static void unalignedFileOffset(long offset) throws MemoryMapException { - throw new MemoryMapException(offset, UNALIGNED_FILE_OFFSET); + throw new MemoryMapException(offset, Reason.UNALIGNED_FILE_OFFSET); } /** * Constructor */ - private MemoryMapException(long addr, int type) { + private MemoryMapException(long addr, Reason reason) { offsetOrAddress = addr; - this.type = type; + this.reason = reason; } /** * String representation of exception */ public String toString() { - switch (type) { + switch (reason) { case UNALIGNED_ADDRESS: - return "Unaligned memory map address: 0x" - + Integer.toHexString((int) offsetOrAddress); + return String.format("Unaligned memory map address: 0x%x", offsetOrAddress); + case UNALIGNED_FILE_OFFSET: - return "Unaligned file offset: " + offsetOrAddress; + return String.format("Unaligned file offset: 0x%x", offsetOrAddress); + + default: + throw new RuntimeException("Unexpected MemoryMapException Reason: " + reason); } - DBT_OptimizingCompilerException.UNREACHABLE(); - return null; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-26 20:26:02
|
Revision: 93 http://svn.sourceforge.net/pearcolator/?rev=93&view=rev Author: michael_baer Date: 2007-04-26 13:26:01 -0700 (Thu, 26 Apr 2007) Log Message: ----------- - Moved file handling into separate package. - Introduced abstractions for linux files, so that we can later add sockets etc. - Introduced dummy for the stat64 syscall Modified Paths: -------------- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Added Paths: ----------- src/org/binarytranslator/generic/os/abi/linux/files/ src/org/binarytranslator/generic/os/abi/linux/files/ConsoleIn.java src/org/binarytranslator/generic/os/abi/linux/files/ConsoleOut.java src/org/binarytranslator/generic/os/abi/linux/files/HostFile.java src/org/binarytranslator/generic/os/abi/linux/files/OpenFile.java src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java src/org/binarytranslator/generic/os/abi/linux/files/ReadableFile.java src/org/binarytranslator/generic/os/abi/linux/files/WriteableFile.java Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-25 19:15:36 UTC (rev 92) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-26 20:26:01 UTC (rev 93) @@ -1,902 +1,864 @@ -/* - * This file is part of binarytranslator.org. The binarytranslator.org - * 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 Ian Rogers, The University of Manchester 2003-2006 - */ -package org.binarytranslator.generic.os.abi.linux; - -import java.io.*; -import org.binarytranslator.DBT_Options; -import org.binarytranslator.generic.memory.Memory; -import org.binarytranslator.generic.memory.MemoryMapException; -import java.util.ArrayList; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * Linux system call handling class - */ -abstract public class LinuxSystemCalls { - /** - * The source of the system calls - */ - protected LinuxSystemCallGenerator src; - - /** Allows access to the system call's arguments */ - protected LinuxSystemCallGenerator.CallArgumentIterator arguments; - - /** Allows access to a number of operating-system specific structures. */ - protected LinuxStructureFactory structures; - - /** - * Maximum number of system calls - */ - private static final int MAX_SYSCALLS = 294; - - /** - * Array to de-multiplex Linux system calls. NB we will have to - * handle IA32 call gates entry at some point - */ - protected SystemCall systemCallTable[]; - - /** - * The name for this system given by uname - */ - protected String getSysName() { - return "Linux"; - } - /** - * The release for this system given by uname - */ - protected String getRelease() { - return "2.6.13"; - } - /** - * The version for this system given by uname - */ - protected String getVersion() { - return "#1"; - } - /** - * The machine for this system given by uname - */ - protected abstract String getMachine(); - - /** - * List of (RandomAccessFile(s)) files currently open - */ - private ArrayList<Object> files; - - - /** - * Load an ASCIIZ string from the memory of the system call - * generator and return it as a Java String. - * @param address where to read - * @return the String read - */ - private String memoryReadString(int address) { - Memory m = src.getProcessSpace().memory; - - StringBuffer str = new StringBuffer(); - char c; - - while ((c = (char) m.loadUnsigned8(address++)) != 0) - str.append(c); - - return str.toString(); - } - - /** - * Store an ASCIIZ string to the memory of the system call generator - * @param address where to read - * @param data the String to write - */ - public void memoryWriteString(int address, String data) { - Memory m = src.getProcessSpace().memory; - - if (data != null) { - for (int i = 0; i < data.length(); i++) { - m.store8(address + i, (byte) data.charAt(i)); - } - - m.store8(address + data.length(), (byte) 0); - } - } - - /** - * Convert integer file descriptor into Java RandomAccessFile - */ - private RandomAccessFile getRAFile(int fd) { - return (RandomAccessFile)files.get(fd); - } - /** - * Append the given file to the files list returning the location - */ - private int appendRAFile(RandomAccessFile raFile) { - // replace an unused entry if possible - for (int i=3; i < files.size(); i++) { - if(files.get(i) == null) { - files.set(i, raFile); - return i; - } - } - // not possible so append to end - files.add(raFile); - return files.size() - 1; - } - /** - * Remove the file for the given file descriptor - */ - private void removeRAFile(int fd) { - // check descriptor is valid - if((fd > 0) && (fd < files.size())) { - // can we remove it from the end of the list? - if (fd == (files.size() - 1)) { - files.remove(fd); - } - else { - // no. set it to null - files.set(fd, null); - } - } - } - /** - * Constructor - */ - public LinuxSystemCalls(LinuxSystemCallGenerator src) { - this.src = src; - systemCallTable = new SystemCall[MAX_SYSCALLS]; - UnknownSystemCall USC = new UnknownSystemCall(); - for(int i=0; i < MAX_SYSCALLS; i++) { - systemCallTable[i] = USC; - } - files = new ArrayList<Object>(); - files.add(System.in); - files.add(System.out); - files.add(System.err); - } - - /** - * Handle a system call - * @param src the system call generator - */ - public void doSysCall() { - int sysCallNumber = src.getSysCallNumber(); - System.err.println("Syscall "+ sysCallToString(sysCallNumber)); - arguments = src.getSysCallArguments(); - systemCallTable[sysCallNumber].doSysCall(); - } - - /** - * Turn the given system call number into a string describing its - * function - */ - abstract public String sysCallToString(int syscall); - - /* - * ABI constants - */ - - /** - * Class capturing errno constants - */ - private final static class errno { - /** Operation not permitted */ - final static int EPERM=1; - /** No such file or directory */ - final static int ENOENT=2; - /** No such process */ - final static int ESRCH=3; - /** Interrupted system call */ - final static int EINTR=4; - /** I/O error */ - final static int EIO=5; - /** No such device or address */ - final static int ENXIO=6; - /** Argument list too long */ - final static int E2BIG=7; - /** Exec format error */ - final static int ENOEXEC=8; - /** Bad file number */ - final static int EBADF=9; - /** No child processes */ - final static int ECHILD=10; - /** Try again */ - final static int EAGAIN=11; - /** Out of memory */ - final static int ENOMEM=12; - /** Permission denied */ - final static int EACCES=13; - /** Bad address */ - final static int EFAULT=14; - /** Block device required */ - final static int ENOTBLK=15; - /** Device or resource busy */ - final static int EBUSY=16; - /** File exists */ - final static int EEXIST=17; - /** Cross-device link */ - final static int EXDEV=18; - /** No such device */ - final static int ENODEV=19; - /** Not a directory */ - final static int ENOTDIR=20; - /** Is a directory */ - final static int EISDIR=21; - /** Invalid argument */ - final static int EINVAL=22; - /** File table overflow */ - final static int ENFILE=23; - /** Too many open files */ - final static int EMFILE=24; - /** Not a typewriter */ - final static int ENOTTY=25; - /** Text file busy */ - final static int ETXTBSY=26; - /** File too large */ - final static int EFBIG=27; - /** No space left on device */ - final static int ENOSPC=28; - /** Illegal seek */ - final static int ESPIPE=29; - /** Read-only file system */ - final static int EROFS=30; - /** Too many links */ - final static int EMLINK=31; - /** Broken pipe */ - final static int EPIPE=32; - /** Math argument out of domain of func */ - final static int EDOM=33; - /** Math result not representable */ - final static int ERANGE=34; - - /** Resource deadlock would occur */ - final static int EDEADLK=35; - final static int EDEADLOCK=EDEADLK; - /** File name too long */ - final static int ENAMETOOLONG=36; - /** No record locks available */ - final static int ENOLCK=37; - /** Function not implemented */ - final static int ENOSYS=38; - /** Directory not empty */ - final static int ENOTEMPTY=39; - /** Too many symbolic links encountered */ - final static int ELOOP=40; - /** Operation would block */ - final static int EWOULDBLOCK=EAGAIN; - /** No message of desired type */ - final static int ENOMSG=42; - /** Identifier removed */ - final static int EIDRM=43; - /** Channel number out of range */ - final static int ECHRNG=44; - /** Level 2 not synchronized */ - final static int EL2NSYNC=45; - /** Level 3 halted */ - final static int EL3HLT=46; - /** Level 3 reset */ - final static int EL3RST=47; - /** Link number out of range */ - final static int ELNRNG=48; - /** Protocol driver not attached */ - final static int EUNATCH=49; - /** No CSI structure available */ - final static int ENOCSI=50; - /** Level 2 halted */ - final static int EL2HLT=51; - /** Invalid exchange */ - final static int EBADE=52; - /** Invalid request descriptor */ - final static int EBADR=53; - /** Exchange full */ - final static int EXFULL=54; - /** No anode */ - final static int ENOANO=55; - /** Invalid request code */ - final static int EBADRQC=56; - /** Invalid slot */ - final static int EBADSLT=57; - - /** Bad font file format */ - final static int EBFONT=59; - /** Device not a stream */ - final static int ENOSTR=60; - /** No data available */ - final static int ENODATA=61; - /** Timer expired */ - final static int ETIME=62; - /** Out of streams resources */ - final static int ENOSR=63; - /** Machine is not on the network */ - final static int ENONET=64; - /** Package not installed */ - final static int ENOPKG=65; - /** Object is remote */ - final static int EREMOTE=66; - /** Link has been severed */ - final static int ENOLINK=67; - /** Advertise error */ - final static int EADV=68; - /** Srmount error */ - final static int ESRMNT=69; - /** Communication error on send */ - final static int ECOMM=70; - /** Protocol error */ - final static int EPROTO=71; - /** Multihop attempted */ - final static int EMULTIHOP=72; - /** RFS specific error */ - final static int EDOTDOT=73; - /** Not a data message */ - final static int EBADMSG=74; - /** Value too large for defined data type */ - final static int EOVERFLOW=75; - /** Name not unique on network */ - final static int ENOTUNIQ=76; - /** File descriptor in bad state */ - final static int EBADFD=77; - /** Remote address changed */ - final static int EREMCHG=78; - /** Can not access a needed shared library */ - final static int ELIBACC=79; - /** Accessing a corrupted shared library */ - final static int ELIBBAD=80; - /** .lib section in a.out corrupted */ - final static int ELIBSCN=81; - /** Attempting to link in too many shared libraries */ - final static int ELIBMAX=82; - /** Cannot exec a shared library directly */ - final static int ELIBEXEC=83; - /** Illegal byte sequence */ - final static int EILSEQ=84; - /** Interrupted system call should be restarted */ - final static int ERESTART=85; - /** Streams pipe error */ - final static int ESTRPIPE=86; - /** Too many users */ - final static int EUSERS=87; - /** Socket operation on non-socket */ - final static int ENOTSOCK=88; - /** Destination address required */ - final static int EDESTADDRREQ=89; - /** Message too long */ - final static int EMSGSIZE=90; - /** Protocol wrong type for socket */ - final static int EPROTOTYPE=91; - /** Protocol not available */ - final static int ENOPROTOOPT=92; - /** Protocol not supported */ - final static int EPROTONOSUPPORT=93; - /** Socket type not supported */ - final static int ESOCKTNOSUPPORT=94; - /** Operation not supported on transport endpoint */ - final static int EOPNOTSUPP=95; - /** Protocol family not supported */ - final static int EPFNOSUPPORT=96; - /** Address family not supported by protocol */ - final static int EAFNOSUPPORT=97; - /** Address already in use */ - final static int EADDRINUSE=98; - /** Cannot assign requested address */ - final static int EADDRNOTAVAIL=99; - /** Network is down */ - final static int ENETDOWN=100; - /** Network is unreachable */ - final static int ENETUNREACH=101; - /** Network dropped connection because of reset */ - final static int ENETRESET=102; - /** Software caused connection abort */ - final static int ECONNABORTED=103; - /** Connection reset by peer */ - final static int ECONNRESET=104; - /** No buffer space available */ - final static int ENOBUFS=105; - /** Transport endpoint is already connected */ - final static int EISCONN=106; - /** Transport endpoint is not connected */ - final static int ENOTCONN=107; - /** Cannot send after transport endpoint shutdown */ - final static int ESHUTDOWN=108; - /** Too many references: cannot splice */ - final static int ETOOMANYREFS=109; - /** Connection timed out */ - final static int ETIMEDOUT=110; - /** Connection refused */ - final static int ECONNREFUSED=111; - /** Host is down */ - final static int EHOSTDOWN=112; - /** No route to host */ - final static int EHOSTUNREACH=113; - /** Operation already in progress */ - final static int EALREADY=114; - /** Operation now in progress */ - final static int EINPROGRESS=115; - /** Stale NFS file handle */ - final static int ESTALE=116; - /** Structure needs cleaning */ - final static int EUCLEAN=117; - /** Not a XENIX named type file */ - final static int ENOTNAM=118; - /** No XENIX semaphores available */ - final static int ENAVAIL=119; - /** Is a named type file */ - final static int EISNAM=120; - /** Remote I/O error */ - final static int EREMOTEIO=121; - /** Quota exceeded */ - final static int EDQUOT=122; - - /** No medium found */ - final static int ENOMEDIUM=123; - /** Wrong medium type */ - final static int EMEDIUMTYPE=124; - /** Operation Canceled */ - final static int ECANCELED=125; - /** Required key not available */ - final static int ENOKEY=126; - /** Key has expired */ - final static int EKEYEXPIRED=127; - /** Key has been revoked */ - final static int EKEYREVOKED=128; - /** Key was rejected by service */ - final static int EKEYREJECTED=129; - - /** Owner died */ - final static int EOWNERDEAD=130; - /** State not recoverable */ - final static int ENOTRECOVERABLE=131; - } - - /** - * Class capturing file control (fcntl) constants - */ - private final static class fcntl { - 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; - } - - /** - * Class capturing memory management constants - */ - private final static class mman { - /** Page can be read */ - public final static int PROT_READ=0x1; - /** Page can be written */ - public final static int PROT_WRITE=0x2; - /** Page can be executed */ - public final static int PROT_EXEC=0x4; - - /** Don't use a file */ - public final static int MAP_ANONYMOUS=0x20; - } - /* - * Local classes - */ - - /** - * Define the system call interface - */ - public abstract class SystemCall { - /** - * Handle a system call - */ - public abstract void doSysCall(); - } - - /** - * Unknown System Call - */ - private class UnknownSystemCall extends SystemCall { - /** - * Handle a system call - */ - public void doSysCall() { - if (!DBT_Options.unimplementedSystemCallsFatal) { - src.setSysCallError(errno.ENOSYS); - } - else { - throw new Error("System Call " + sysCallToString(src.getSysCallNumber()) + " Unknown"); - } - } - } - - /** - * Exit system call - */ - public class SysExit extends SystemCall { - public void doSysCall() { - int status = arguments.nextInt(); - System.exit(status); - } - } - - /** - * Read from a file - */ - public class SysRead extends SystemCall { - public void doSysCall() { - int fd = arguments.nextInt(); - int buf = arguments.nextInt(); - int count = arguments.nextInt(); - - Memory mem = src.getProcessSpace().memory; - - if(fd == 0) { // read from stdin - byte[] b = new byte[256]; - try { - int len = System.in.read(b); - for (int i=0; i < len; i++) { - mem.store32(buf + i, b[i]); - } - src.setSysCallReturn(len); - } - catch(IOException e) { - src.setSysCallError(errno.EIO); - //cr |= PPC_errno.CR0_SO; - } - } - else { - RandomAccessFile raFile = getRAFile(fd); - if(raFile == null) { - src.setSysCallError(errno.EBADF); - } else { - // Where to put the data - int addr = buf; - // Copy from file into buffer. - int b = 0; // Number of bytes read. - int i; - try { - while((b < count) && ((i = raFile.read()) != -1)) { - byte by = (byte)i; - b++; - mem.store8(addr++, by); - } - src.setSysCallReturn(b); // Return number of bytes read. - } - catch(IOException e) { - src.setSysCallReturn(errno.EIO); - } - } - } - } - } - - /** - * Write to a file - */ - public class SysWrite extends SystemCall { - public void doSysCall() { - int fd = arguments.nextInt(); - int buf = arguments.nextInt(); - int count = arguments.nextInt(); - - Memory mem = src.getProcessSpace().memory; - - if(fd == 1) { // stdout - for(int c = 0 ; c < count; c++) { - System.out.print((char) mem.loadUnsigned8(buf + c)); - } - src.setSysCallReturn(count); - } else if(fd == 2) { // sterr - for(int c = 0 ; c < count ; c++) { - System.err.print((char) mem.loadUnsigned8(buf + c)); - } - src.setSysCallReturn(count); - } else { - // Check that fd is a valid file descriptor. - RandomAccessFile raFile = getRAFile(fd); - if(raFile == null) { - src.setSysCallReturn(errno.EBADF); - } else { - // Where to get the data. - int addr = buf; - - // Copy from buffer into file. - int b; // Number of bytes written. - byte by; - - try { - for(b = 1 ; b <= count ; b++) { - by = (byte) mem.loadUnsigned8(addr++); - raFile.write(by); - } - // Return number of bytes written, having accounted for b - // being incremented once too many at the end of the - // writing - src.setSysCallReturn(b-1); - } - catch(IOException e) { - src.setSysCallReturn(errno.EIO); - } - } - } - } - } - - /** - * Write data into multiple buffers - */ - public class SysWriteV extends SystemCall { - public void doSysCall() { - int fd = arguments.nextInt(); - int vector = arguments.nextInt(); - int count = arguments.nextInt(); - 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; - 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.print((char) mem.loadUnsigned8(base + curVectorPos)); - curVectorPos++; - } - src.setSysCallReturn(count); - } else { - 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); - } - } - } - } - - public class SysOpen extends SystemCall { - public void doSysCall() { - 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. - String fileName = memoryReadString(pathname); - - // Create a File object so we can test for the existance and - // properties of the file. - File testFile = new File(fileName); - - if(((flags & fcntl.O_CREAT) != 0) && - ((flags & fcntl.O_EXCL) != 0) && - testFile.exists()) { - // O_CREAT specified. If O_EXCL also specified, we require - // that the file does not already exist - src.setSysCallError(errno.EEXIST); - } - else if(((flags & fcntl.O_CREAT) != 0) && !testFile.exists()) { - // O_CREAT not specified. We require that the file exists. - src.setSysCallError(errno.ENOENT); - } - else { - // we have not found an error, so we go ahead and try to open the file - try { - RandomAccessFile raFile; - if((flags & 0x3) == fcntl.O_RDONLY) { - raFile = new RandomAccessFile(fileName, "r"); - } - else { - // NB Java RandomAccessFile has no write only - raFile = new RandomAccessFile(fileName, "rw"); - } - src.setSysCallReturn(appendRAFile(raFile)); - } - catch(FileNotFoundException e) { - throw new Error("File not found: " + fileName + " " + e); - } - } - // 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 | 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)); - } - } - } - - public class SysClose extends SystemCall { - public void doSysCall() { - int fd = arguments.nextInt(); - RandomAccessFile raFile = getRAFile(fd); - // Check that fd is a valid file descriptor - if(raFile == null) { - src.setSysCallError(errno.EBADF); - } else { - try { - raFile.close(); - - src.setSysCallReturn(0); // return success code - } catch(IOException e) { - src.setSysCallReturn(errno.EIO); - //cr |= PPC_errno.CR0_SO; - } - } - } - } - - public class SysGetEUID extends SystemCall { - public void doSysCall() { - src.setSysCallReturn(DBT_Options.UID); - } - } - - public class SysGetUID extends SystemCall { - public void doSysCall() { - src.setSysCallReturn(DBT_Options.UID); - } - } - - public class SysGetEGID extends SystemCall { - public void doSysCall() { - src.setSysCallReturn(DBT_Options.GID); - } - } - - public class SysGetGID extends SystemCall { - public void doSysCall() { - src.setSysCallReturn(DBT_Options.GID); - } - } - - public class SysBrk extends SystemCall { - public void doSysCall() { - int brk = arguments.nextInt(); - if(brk != 0) { - // Request to set the current top of bss. - src.setBrk(brk); - } - src.setSysCallReturn(src.getBrk()); - } - } - - public class SysFstat64 extends SystemCall { - public void doSysCall() { - int fd = arguments.nextInt(); - - LinuxStructureFactory.stat64 buf = structures.new_stat64(); - - if (fd == 1) { - buf.st_mode = 0x2180; - buf.st_rdev = (short)0x8800; - buf.__st_ino = buf.st_ino = 2; - buf.st_blksize = 0x400; - } - else - throw new RuntimeException("Unimplemented system call."); - - buf.write(src.getProcessSpace().memory, arguments.nextInt()); - src.setSysCallReturn(0); - } - } - - 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) ) - src.setSysCallReturn(0); - else - throw new Error("Unrecognised system call."); - } - } - - public class SysUname extends SystemCall { - public void doSysCall() { - // Simple uname support - int addr = arguments.nextInt(); - - if (addr != 0) { - String localhostString, domainName, hostName; - try { - InetAddress localhost = InetAddress.getLocalHost(); - localhostString = localhost.getHostName(); - } - catch (UnknownHostException e) { - localhostString = "localhost.localdomain"; - } - int index = localhostString.indexOf('.'); - if (index == -1) { - domainName = null; - hostName = localhostString; - } - else { - 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 - memoryWriteString (addr+130, getRelease()); // release - memoryWriteString (addr+195, getVersion()); // version - memoryWriteString (addr+260, getMachine()); // machine - memoryWriteString (addr+325, domainName); // __domainname - src.setSysCallReturn(0); - } - else { - // attempt to write to address 0 - src.setSysCallError(errno.EFAULT); - } - } - } - - public class SysMmap extends SystemCall { - public void doSysCall() { - - 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 { - Memory mem = src.getProcessSpace().memory; - - src.setSysCallReturn( mem.map(start, length, - (prot & mman.PROT_READ) != 0, - (prot & mman.PROT_WRITE) != 0, - (prot & mman.PROT_EXEC) != 0)); - } - catch (MemoryMapException e) { - throw new Error("Error in mmap", e); - } - } else { - throw new Error("Non-anonymous sys_mmap not yet implemented."); - } - } - } - - public class SysMunmap extends SystemCall { - public void doSysCall() { - - int start = arguments.nextInt(); - int length = arguments.nextInt(); - - src.getProcessSpace().memory.unmap(start, length); - src.setSysCallReturn(0); - } - } - - public class SysExitGroup extends SystemCall { - public void doSysCall() { - // For now, equivalent to SysExit - System.exit(arguments.nextInt()); - } - } -} +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * 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 Ian Rogers, The University of Manchester 2003-2006 + */ +package org.binarytranslator.generic.os.abi.linux; + +import org.binarytranslator.DBT_Options; +import org.binarytranslator.generic.memory.Memory; +import org.binarytranslator.generic.memory.MemoryMapException; +import org.binarytranslator.generic.os.abi.linux.files.ConsoleIn; +import org.binarytranslator.generic.os.abi.linux.files.ConsoleOut; +import org.binarytranslator.generic.os.abi.linux.files.HostFile; +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; +import org.binarytranslator.generic.os.abi.linux.files.OpenFileList; +import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; +import org.binarytranslator.generic.os.abi.linux.files.WriteableFile; +import org.binarytranslator.generic.os.abi.linux.files.OpenFileList.InvalidFileDescriptor; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Linux system call handling class + */ +abstract public class LinuxSystemCalls { + /** + * The source of the system calls + */ + protected LinuxSystemCallGenerator src; + + /** Allows access to the system call's arguments */ + protected LinuxSystemCallGenerator.CallArgumentIterator arguments; + + /** Allows access to a number of operating-system specific structures. */ + protected LinuxStructureFactory structures; + + /** List of currently opened files. */ + private OpenFileList openFiles; + + /** + * Maximum number of system calls + */ + private static final int MAX_SYSCALLS = 294; + + /** + * Array to de-multiplex Linux system calls. NB we will have to + * handle IA32 call gates entry at some point + */ + protected SystemCall systemCallTable[]; + + /** + * The name for this system given by uname + */ + protected String getSysName() { + return "Linux"; + } + /** + * The release for this system given by uname + */ + protected String getRelease() { + return "2.6.13"; + } + /** + * The version for this system given by uname + */ + protected String getVersion() { + return "#1"; + } + /** + * The machine for this system given by uname + */ + protected abstract String getMachine(); + + + /** + * Load an ASCIIZ string from the memory of the system call + * generator and return it as a Java String. + * @param address where to read + * @return the String read + */ + private String memoryReadString(int address) { + Memory m = src.getProcessSpace().memory; + + StringBuffer str = new StringBuffer(); + char c; + + while ((c = (char) m.loadUnsigned8(address++)) != 0) + str.append(c); + + return str.toString(); + } + + /** + * Store an ASCIIZ string to the memory of the system call generator + * @param address where to read + * @param data the String to write + */ + public void memoryWriteString(int address, String data) { + Memory m = src.getProcessSpace().memory; + + if (data != null) { + for (int i = 0; i < data.length(); i++) { + m.store8(address + i, (byte) data.charAt(i)); + } + + m.store8(address + data.length(), (byte) 0); + } + } + + /** + * Constructor + */ + public LinuxSystemCalls(LinuxSystemCallGenerator src) { + this.src = src; + systemCallTable = new SystemCall[MAX_SYSCALLS]; + UnknownSystemCall USC = new UnknownSystemCall(); + for(int i=0; i < MAX_SYSCALLS; i++) { + systemCallTable[i] = USC; + } + + openFiles = new OpenFileList(); + + if (openFiles.open(new ConsoleIn(), 0) != 0 || + openFiles.open(new ConsoleOut(System.out), 1) != 1 || + openFiles.open(new ConsoleOut(System.err), 2) != 2) { + + throw new RuntimeException("File descriptors for standard streams could not be assigned correctly."); + } + + structures = new LinuxStructureFactory(); + } + + /** + * Handle a system call + * @param src the system call generator + */ + public void doSysCall() { + int sysCallNumber = src.getSysCallNumber(); + System.err.println("Syscall "+ sysCallToString(sysCallNumber)); + arguments = src.getSysCallArguments(); + systemCallTable[sysCallNumber].doSysCall(); + } + + /** + * Turn the given system call number into a string describing its + * function + */ + abstract public String sysCallToString(int syscall); + + /** + * Class capturing errno constants + */ + private final static class errno { + /** Operation not permitted */ + final static int EPERM=1; + /** No such file or directory */ + final static int ENOENT=2; + /** No such process */ + final static int ESRCH=3; + /** Interrupted system call */ + final static int EINTR=4; + /** I/O error */ + final static int EIO=5; + /** No such device or address */ + final static int ENXIO=6; + /** Argument list too long */ + final static int E2BIG=7; + /** Exec format error */ + final static int ENOEXEC=8; + /** Bad file number */ + final static int EBADF=9; + /** No child processes */ + final static int ECHILD=10; + /** Try again */ + final static int EAGAIN=11; + /** Out of memory */ + final static int ENOMEM=12; + /** Permission denied */ + final static int EACCES=13; + /** Bad address */ + final static int EFAULT=14; + /** Block device required */ + final static int ENOTBLK=15; + /** Device or resource busy */ + final static int EBUSY=16; + /** File exists */ + final static int EEXIST=17; + /** Cross-device link */ + final static int EXDEV=18; + /** No such device */ + final static int ENODEV=19; + /** Not a directory */ + final static int ENOTDIR=20; + /** Is a directory */ + final static int EISDIR=21; + /** Invalid argument */ + final static int EINVAL=22; + /** File table overflow */ + final static int ENFILE=23; + /** Too many open files */ + final static int EMFILE=24; + /** Not a typewriter */ + final static int ENOTTY=25; + /** Text file busy */ + final static int ETXTBSY=26; + /** File too large */ + final static int EFBIG=27; + /** No space left on device */ + final static int ENOSPC=28; + /** Illegal seek */ + final static int ESPIPE=29; + /** Read-only file system */ + final static int EROFS=30; + /** Too many links */ + final static int EMLINK=31; + /** Broken pipe */ + final static int EPIPE=32; + /** Math argument out of domain of func */ + final static int EDOM=33; + /** Math result not representable */ + final static int ERANGE=34; + + /** Resource deadlock would occur */ + final static int EDEADLK=35; + final static int EDEADLOCK=EDEADLK; + /** File name too long */ + final static int ENAMETOOLONG=36; + /** No record locks available */ + final static int ENOLCK=37; + /** Function not implemented */ + final static int ENOSYS=38; + /** Directory not empty */ + final static int ENOTEMPTY=39; + /** Too many symbolic links encountered */ + final static int ELOOP=40; + /** Operation would block */ + final static int EWOULDBLOCK=EAGAIN; + /** No message of desired type */ + final static int ENOMSG=42; + /** Identifier removed */ + final static int EIDRM=43; + /** Channel number out of range */ + final static int ECHRNG=44; + /** Level 2 not synchronized */ + final static int EL2NSYNC=45; + /** Level 3 halted */ + final static int EL3HLT=46; + /** Level 3 reset */ + final static int EL3RST=47; + /** Link number out of range */ + final static int ELNRNG=48; + /** Protocol driver not attached */ + final static int EUNATCH=49; + /** No CSI structure available */ + final static int ENOCSI=50; + /** Level 2 halted */ + final static int EL2HLT=51; + /** Invalid exchange */ + final static int EBADE=52; + /** Invalid request descriptor */ + final static int EBADR=53; + /** Exchange full */ + final static int EXFULL=54; + /** No anode */ + final static int ENOANO=55; + /** Invalid request code */ + final static int EBADRQC=56; + /** Invalid slot */ + final static int EBADSLT=57; + + /** Bad font file format */ + final static int EBFONT=59; + /** Device not a stream */ + final static int ENOSTR=60; + /** No data available */ + final static int ENODATA=61; + /** Timer expired */ + final static int ETIME=62; + /** Out of streams resources */ + final static int ENOSR=63; + /** Machine is not on the network */ + final static int ENONET=64; + /** Package not installed */ + final static int ENOPKG=65; + /** Object is remote */ + final static int EREMOTE=66; + /** Link has been severed */ + final static int ENOLINK=67; + /** Advertise error */ + final static int EADV=68; + /** Srmount error */ + final static int ESRMNT=69; + /** Communication error on send */ + final static int ECOMM=70; + /** Protocol error */ + final static int EPROTO=71; + /** Multihop attempted */ + final static int EMULTIHOP=72; + /** RFS specific error */ + final static int EDOTDOT=73; + /** Not a data message */ + final static int EBADMSG=74; + /** Value too large for defined data type */ + final static int EOVERFLOW=75; + /** Name not unique on network */ + final static int ENOTUNIQ=76; + /** File descriptor in bad state */ + final static int EBADFD=77; + /** Remote address changed */ + final static int EREMCHG=78; + /** Can not access a needed shared library */ + final static int ELIBACC=79; + /** Accessing a corrupted shared library */ + final static int ELIBBAD=80; + /** .lib section in a.out corrupted */ + final static int ELIBSCN=81; + /** Attempting to link in too many shared libraries */ + final static int ELIBMAX=82; + /** Cannot exec a shared library directly */ + final static int ELIBEXEC=83; + /** Illegal byte sequence */ + final static int EILSEQ=84; + /** Interrupted system call should be restarted */ + final static int ERESTART=85; + /** Streams pipe error */ + final static int ESTRPIPE=86; + /** Too many users */ + final static int EUSERS=87; + /** Socket operation on non-socket */ + final static int ENOTSOCK=88; + /** Destination address required */ + final static int EDESTADDRREQ=89; + /** Message too long */ + final static int EMSGSIZE=90; + /** Protocol wrong type for socket */ + final static int EPROTOTYPE=91; + /** Protocol not available */ + final static int ENOPROTOOPT=92; + /** Protocol not supported */ + final static int EPROTONOSUPPORT=93; + /** Socket type not supported */ + final static int ESOCKTNOSUPPORT=94; + /** Operation not supported on transport endpoint */ + final static int EOPNOTSUPP=95; + /** Protocol family not supported */ + final static int EPFNOSUPPORT=96; + /** Address family not supported by protocol */ + final static int EAFNOSUPPORT=97; + /** Address already in use */ + final static int EADDRINUSE=98; + /** Cannot assign requested address */ + final static int EADDRNOTAVAIL=99; + /** Network is down */ + final static int ENETDOWN=100; + /** Network is unreachable */ + final static int ENETUNREACH=101; + /** Network dropped connection because of reset */ + final static int ENETRESET=102; + /** Software caused connection abort */ + final static int ECONNABORTED=103; + /** Connection reset by peer */ + final static int ECONNRESET=104; + /** No buffer space available */ + final static int ENOBUFS=105; + /** Transport endpoint is already connected */ + final static int EISCONN=106; + /** Transport endpoint is not connected */ + final static int ENOTCONN=107; + /** Cannot send after transport endpoint shutdown */ + final static int ESHUTDOWN=108; + /** Too many references: cannot splice */ + final static int ETOOMANYREFS=109; + /** Connection timed out */ + final static int ETIMEDOUT=110; + /** Connection refused */ + final static int ECONNREFUSED=111; + /** Host is down */ + final static int EHOSTDOWN=112; + /** No route to host */ + final static int EHOSTUNREACH=113; + /** Operation already in progress */ + final static int EALREADY=114; + /** Operation now in progress */ + final static int EINPROGRESS=115; + /** Stale NFS file handle */ + final static int ESTALE=116; + /** Structure needs cleaning */ + final static int EUCLEAN=117; + /** Not a XENIX named type file */ + final static int ENOTNAM=118; + /** No XENIX semaphores available */ + final static int ENAVAIL=119; + /** Is a named type file */ + final static int EISNAM=120; + /** Remote I/O error */ + final static int EREMOTEIO=121; + /** Quota exceeded */ + final static int EDQUOT=122; + + /** No medium found */ + final static int ENOMEDIUM=123; + /** Wrong medium type */ + final static int EMEDIUMTYPE=124; + /** Operation Canceled */ + final static int ECANCELED=125; + /** Required key not available */ + final static int ENOKEY=126; + /** Key has expired */ + final static int EKEYEXPIRED=127; + /** Key has been revoked */ + final static int EKEYREVOKED=128; + /** Key was rejected by service */ + final static int EKEYREJECTED=129; + + /** Owner died */ + final static int EOWNERDEAD=130; + /** State not recoverable */ + final static int ENOTRECOVERABLE=131; + } + + /** + * Class capturing file control (fcntl) constants + */ + private final static class fcntl { + 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; + } + + /** + * Class capturing memory management constants + */ + private final static class mman { + /** Page can be read */ + public final static int PROT_READ=0x1; + /** Page can be written */ + public final static int PROT_WRITE=0x2; + /** Page can be executed */ + public final static int PROT_EXEC=0x4; + /** Map pages that are shared between processes */ + public final static int MAP_SHARED = 0x1; + /** Map pages without sharing them */ + public final static int MAP_PRIVATE = 0x2; + /** Don't use a file */ + public final static int MAP_ANONYMOUS=0x20; + } + + /** + * Define the system call interface + */ + public abstract class SystemCall { + /** + * Handle a system call + */ + public abstract void doSysCall(); + } + + /** + * Unknown System Call + */ + private class UnknownSystemCall extends SystemCall { + /** + * Handle a system call + */ + public void doSysCall() { + if (!DBT_Options.unimplementedSystemCallsFatal) { + src.setSysCallError(errno.ENOSYS); + } + else { + throw new Error("System Call " + sysCallToString(src.getSysCallNumber()) + " Unknown"); + } + } + } + + /** + * Exit system call + */ + public class SysExit extends SystemCall { + public void doSysCall() { + int status = arguments.nextInt(); + System.exit(status); + } + } + + /** + * Read from a file + */ + public class SysRead extends SystemCall { + public void doSysCall() { + int fd = arguments.nextInt(); + int buf = arguments.nextInt(); + int count = arguments.nextInt(); + + Memory mem = src.getProcessSpace().memory; + + try { + //get the file from the file descriptor table + ReadableFile file = openFiles.getRead(fd); + byte[] buffer = new byte[count]; + + //try to fill the buffer from the file + int readBytes = file.read(buffer); + + //copy the filled buffer into the memory + for (int i = 0; i < readBytes; i++) + mem.store8(buf++, buffer[i]); + + src.setSysCallReturn(readBytes); + } + catch (InvalidFileDescriptor e) { + src.setSysCallError(errno.EBADF); + } + catch (Exception e) { + src.setSysCallError(errno.EIO); + } + } + } + + /** + * Write to a file + */ + public class SysWrite extends SystemCall { + public void doSysCall() { + int fd = arguments.nextInt(); + int buf = arguments.nextInt(); + int count = arguments.nextInt(); + + Memory mem = src.getProcessSpace().memory; + + try { + //get the file from the file descriptor table + WriteableFile file = openFiles.getWrite(fd); + + //load the supplied buffer from memory + byte[] buffer = new byte[count]; + for (int i = 0; i < count; i++) + buffer[i] = (byte)mem.loadUnsigned8(buf++); + + //write that buffer to the file + file.write(buffer); + src.setSysCallReturn(count); + } + catch (InvalidFileDescriptor e) { + src.setSysCallError(errno.EBADF); + } + catch (Exception e) { + src.setSysCallError(errno.EIO); + } + } + } + + /** + * Write data into multiple buffers + */ + public class SysWriteV extends SystemCall { + public void doSysCall() { + int fd = arguments.nextInt(); + int vector = arguments.nextInt(); + int count = arguments.nextInt(); + Memory mem = src.getProcessSpace().memory; + + try { + //get the file from the file descriptor table + WriteableFile file = openFiles.getWrite(fd); + int bytesWritten = 0; + + //for each of the supplied buffers... + for (int n = 0; n < count; n++) { + //get the base address & length for the current buffer + int base = mem.load32(vector); + int len = mem.load32(vector + 4); + vector += 8; + + //read the buffer from memory + byte[] buffer = new byte[len]; + for (int i = 0; i < count; i++) + buffer[i] = (byte)mem.loadUnsigned8(base + i); + + //and write it to the file + file.write(buffer); + bytesWritten += len; + } + + src.setSysCallReturn(bytesWritten); + } + catch (InvalidFileDescriptor e) { + src.setSysCallError(errno.EBADF); + } + catch (Exception e) { + src.setSysCallError(errno.EIO); + } + } + } + + public class SysOpen extends SystemCall { + public void doSysCall() { + 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. + String fileName = memoryReadString(pathname); + + // Create a File object so we can test for the existance and + // properties of the file. + File testFile = new File(fileName); + + if(((flags & fcntl.O_CREAT) != 0) && + ((flags & fcntl.O_EXCL) != 0) && + testFile.exists()) { + // O_CREAT specified. If O_EXCL also specified, we require + // that the file does not already exist + src.setSysCallError(errno.EEXIST); + return; + } + else if(((flags & fcntl.O_CREAT) != 0) && !testFile.exists()) { + // O_CREAT not specified. We require that the file exists. + src.setSysCallError(errno.ENOENT); + return; + } + + // we have not found an error, so we go ahead and try to open the file + try { + RandomAccessFile raFile; + int fd; + + if((flags & 0x3) == fcntl.O_RDONLY) { + raFile = new RandomAccessFile(fileName, "r"); + fd = openFiles.open( HostFile.forReading(raFile) ); + } + else { + // NB Java RandomAccessFile has no write only + raFile = new RandomAccessFile(fileName, "rw"); + fd = openFiles.open( HostFile.forWriting(raFile) ); + } + src.setSysCallReturn(fd); + } + catch(FileNotFoundException e) { + System.err.println("Open tried to open non-existent file: " + fileName); + src.setSysCallError(errno.ENOENT); + return; + } + + // 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 | 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)); + } + } + } + + public class SysClose extends SystemCall { + public void doSysCall() { + int fd = arguments.nextInt(); + + try { + OpenFile f = openFiles.get(fd); + f.close(); + } + catch (InvalidFileDescriptor e) { + src.setSysCallError(errno.EBADF); + } + catch (IOException e) { + src.setSysCallError(errno.EIO); + } + } + } + + public class SysGetEUID extends SystemCall { + public void doSysCall() { + src.setSysCallReturn(DBT_Options.UID); + } + } + + public class SysGetUID extends SystemCall { + public void doSysCall() { + src.setSysCallReturn(DBT_Options.UID); + } + } + + public class SysGetEGID extends SystemCall { + public void doSysCall() { + src.setSysCallReturn(DBT_Options.GID); + } + } + + public class SysGetGID extends SystemCall { + public void doSysCall() { + src.setSysCallReturn(DBT_Options.GID); + } + } + + public class SysBrk extends SystemCall { + public void doSysCall() { + int brk = arguments.nextInt(); + if(brk != 0) { + // Request to set the current top of bss. + src.setBrk(brk); + } + src.setSysCallReturn(src.getBrk()); + } + } + + public class SysFstat64 extends SystemCall { + public void doSysCall() { + int fd = arguments.nextInt(); + + LinuxStructureFactory.stat64 buf = structures.new_stat64(); + + if (fd == 0 || fd == 1 || fd == 2) { + buf.st_mode = 0x2180; + buf.st_rdev = (short)0x8800; + buf.__st_ino = buf.st_ino = 2; + buf.st_blksize = 0x400; + } + else + throw new RuntimeException("Unimplemented system call."); + + buf.write(src.getProcessSpace().memory, arguments.nextInt()); + src.setSysCallReturn(0); + } + } + + public class SysStat64 extends SystemCall { + + @Override + public void doSysCall() { + int ptrFilename = arguments.nextInt(); + int ptrStruct64 = arguments.nextInt(); + + String filename = memoryReadString(ptrFilename); + + if (DBT_Options.debugSyscallMore) System.err.println("Stat64() denies existance of file: " + filename); + src.setSysCallError(errno.ENOENT); + } + + } + + 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) ) + src.setSysCallReturn(0); + else + throw new Error("Unrecognised system call."); + } + } + + public class SysUname extends SystemCall { + public void doSysCall() { + // Simple uname support + int addr = arguments.nextInt(); + + if (addr != 0) { + String localhostString, domainName, hostName; + try { + InetAddress localhost = InetAddress.getLocalHost(); + localhostString = localhost.getHostName(); + } + catch (UnknownHostException e) { + localhostString = "localhost.localdomain"; + } + int index = localhostString.indexOf('.'); + if (index == -1) { + domainName = null; + hostName = localhostString; + } + else { + 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 + memoryWriteString (addr+130, getRelease()); // release + memoryWriteString (addr+195, getVersion()); // version + memoryWriteString (addr+260, getMachine()); // machine + memoryWriteString (addr+325, domainName); // __domainname + src.setSysCallReturn(0); + } + else { + // attempt to write to address 0 + src.setSysCallError(errno.EFAULT); + } + } + } + + public class SysMmap extends SystemCall { + public void doSysCall() { + + int addr = 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 ) { + + if ((flags & mman.MAP_SHARED) != 0) + throw new Error("Mapping of shared pages is currently not supported."); + + //Anonymous private mappings just request memory. + //Ignore the file descriptor and offset, map the required amount of memory and + //return the address of the mapped memory; + addr = 0; + + try { + Memory mem = src.getProcessSpace().memory; + addr = mem.map(addr, length, + (prot & mman.PROT_READ) != 0, + (prot & mman.PROT_WRITE) != 0, + (prot & mman.PROT_EXEC) != 0); + + src.setSysCallReturn(addr); + } + catch (MemoryMapException e) { + throw new Error("Error in mmap", e); + } + } else { + throw new Error("Non-anonymous sys_mmap not yet implemented."); + } + } + } + + public class SysMunmap extends SystemCall { + public void doSysCall() { + + int start = arguments.nextInt(); + int length = arguments.nextInt(); + + src.getProcessSpace().memory.unmap(start, length); + src.setSysCallReturn(0); + } + } + + public class SysExitGroup extends SystemCall { + public void doSysCall() { + // For now, equivalent to SysExit + System.exit(arguments.nextInt()); + } + } +} Added: src/org/binarytranslator/generic/os/abi/linux/files/ConsoleIn.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/ConsoleIn.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/files/ConsoleIn.java 2007-04-26 20:26:01 UTC (rev 93) @@ -0,0 +1,18 @@ +package org.binarytranslator.generic.os.abi.linux.files; + +import java.io.IOException; + +/** + * An open linux file that represents the console input. + */ +public class ConsoleIn implements ReadableFile { + + public int read(byte[] bytes) throws IOException { + return System.in.read(bytes); + } + + public void close() throws IOException { + //no-op + } + +} Added: src/org/binarytranslator/generic/os/abi/linux/files/ConsoleOut.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/ConsoleOut.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/files/ConsoleOut.java 2007-04-26 20:26:01 UTC (rev 93) @@ -0,0 +1,24 @@ +package org.binarytranslator.generic.os.abi.linux.files; + +import java.io.IOException; +import java.io.PrintStream; + +/** + * An open linux file that represents the console ouput streams (stdout and stderr). + */ +public class ConsoleOut implements WriteableFile { + + private final PrintStream stream; + + public ConsoleOut(PrintStream stream) { + this.stream = stream; + } + + public void write(byte[] bytes) throws IOException { + stream.write(bytes); + } + + public void close() throws IOException { + //no-op + } +} Added: src/org/binarytranslator/generic/os/abi/linux/files/HostFile.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/HostFile.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/files/HostFile.java 2007-04-26 20:26:01 UTC (rev 93) @@ -0,0 +1,50 @@ +package org.binarytranslator.generic.os.abi.linux.files; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * A linux file that represents an open file on the host file system. + */ +public class HostFile implements OpenFile { + + protected final RandomAccessFile file; + + public static HostFile forReading(RandomAccessFile file) { + return new ReadableHostFile(file); + } + + public static HostFile forWriting(RandomAccessFile file) { + return new WriteableHostFile(file); + } + + protected HostFile(RandomAccessFile file) { + this.file = file; + } + + public void close() throws IOException { + file.close(); + } + + private static class ReadableHostFile extends HostFile implements ReadableFile { + + protected ReadableHostFile(RandomAccessFile file) { + super(file); + } + + public int read(byte[] buffer) throws IOException { + return file.read(buffer); + } + } + + private static class WriteableHostFile extends ReadableHostFile implements WriteableFile { + + protected WriteableHostFile(RandomAccessFile file) { + super(file); + } + + public void write(byte[] bytes) throws IOException { + file.write(bytes); + } + } +} Added: src/org/binarytranslator/generic/os/abi/linux/files/OpenFile.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/OpenFile.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/files/OpenFile.java 2007-04-26 20:26:01 UTC (rev 93) @@ -0,0 +1,10 @@ +package org.binarytranslator.generic.os.abi.linux.files; + +import ja... [truncated message content] |
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. |
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-24 18:16:44
|
Revision: 90 http://svn.sourceforge.net/pearcolator/?rev=90&view=rev Author: michael_baer Date: 2007-04-24 11:16:44 -0700 (Tue, 24 Apr 2007) Log Message: ----------- - First version that runs ARM "Hello World" (compiled with libc) - Fixed several bugs related to ARM flags - Introduced the munmap system call within for the ARM ABI - Calls to memory.map may provide non-page aligned memory addresses - Introduced the stat64 structure Modified Paths: -------------- src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.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/abi/EABI.java src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.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/LinuxStructureFactory.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/Main.java 2007-04-24 18:16:44 UTC (rev 90) @@ -10,6 +10,7 @@ import java.io.File; +import org.binarytranslator.arch.arm.decoder.Utils; import org.binarytranslator.generic.execution.DynamicTranslationController; import org.binarytranslator.generic.execution.ExecutionController; import org.binarytranslator.generic.execution.GdbController; @@ -93,17 +94,19 @@ System.out.println("***** INITIAL PROCESS SPACE *****\n"); System.out.println(ps); } - + //Create an execution controller and pass execution on to it ExecutionController controller; - if (DBT_Options.gdbStub) { + /*if (DBT_Options.gdbStub) { controller = new GdbController(DBT_Options.gdbStubPort, ps); } else { controller = new DynamicTranslationController(ps); - } + }*/ + controller = new InterpreterController(ps); + controller.run(); } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-24 18:16:44 UTC (rev 90) @@ -107,13 +107,13 @@ return regs.isNegativeSet() == regs.isOverflowSet(); case GT: - return (regs.isNegativeSet() == regs.isOverflowSet()) && regs.isZeroSet(); + return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet(); case HI: return regs.isCarrySet() && !regs.isZeroSet(); case LE: - return regs.isZeroSet() || (regs.isNegativeSet() == regs.isOverflowSet()); + return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet()); case LS: return !regs.isCarrySet() || regs.isZeroSet(); @@ -347,8 +347,8 @@ if (updateConditionCodes) { if (Rd != 15) { int result = lhs - rhs; - boolean carry = !(lhs < rhs); - boolean overflow = Utils.signedAddOverflow(lhs, -rhs); + boolean carry = !Utils.unsignedSubOverflow(lhs, rhs); + boolean overflow = Utils.signedSubOverflow(lhs, rhs); regs.setFlags(result < 0, result == 0, carry, overflow); } else { Modified: src/org/binarytranslator/arch/arm/decoder/Utils.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-04-24 18:16:44 UTC (rev 90) @@ -2,7 +2,7 @@ import org.binarytranslator.DBT; -class Utils { +public class Utils { /** * Checks if a bit is set within a word. @@ -54,33 +54,124 @@ /** * 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>. + * At the moment, this converts both values to longs and checks if the 33rd bit (which actually represents the carry) + * overflows. */ - static boolean unsignedAddOverflow(int operand1, int operand2) { - return operand1 > Integer.MAX_VALUE - operand2; + public static boolean unsignedAddOverflow(int operand1, int operand2) { + long value1 = (long)operand1 & 0xFFFFFFFFL; + long value2 = (long)operand2 & 0xFFFFFFFFL; + + return ((value1 + value2) & 0x100000000L) != 0; } /** - * Returns true, if the subtraction of both operand1 - operand2 (both unsigned) will be a negative number. - * That only happens when <code>operand1 < operand2</code> + * Returns true, if the subtraction of both operand1 - operand2 (both unsigned) will issue a borrow. */ - static boolean unsignedSubOverflow(int operand1, int operand2) { + public static boolean unsignedSubOverflow(int operand1, int operand2) { + operand1 += Integer.MIN_VALUE; + operand2 += Integer.MIN_VALUE; + 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. + * Returns true, if the addition of both operands as signed integers will cause an overflow. + * This basically checks <code>operand1 + operand2 > Integer.MAX_VALUE</code>. */ - static boolean signedAddOverflow(int operand1, int operand2) { - //overflow can only occur when both signs differ - if ((operand1 ^ operand2) >= 0) { - return false; + public static boolean signedAddOverflow(int operand1, int operand2) { + return operand1 > Integer.MAX_VALUE - operand2; + } + + /** + * Returns true, if the subtraction of operand1 from operand (as signed integers) + * will cause an overflow. + * This basically checks <code>operand1 - operand2 < Integer.MIN_VALUE</code>. + */ + public static boolean signedSubOverflow(int operand1, int operand2) { + // if the MSB is already set in any of the operands, then no overflow can + // occur + if (operand1 >= 0) { + return (operand2 < 0) && ((operand1-operand2) < 0); } + else { + return (operand2 > 0) && ((operand1-operand2) > 0); + } + } + + /** + * Performs a number of sanity tests that make sure that the above functions are working the + * manner described before.*/ + public static void runSanityTests() { + if (!Utils.unsignedAddOverflow(1, -1)) { + throw new RuntimeException("Error"); + } - if (operand1 < 0) - return operand1 < Integer.MIN_VALUE - operand2; - else - return Integer.MAX_VALUE - operand1 < operand2; + if (!Utils.unsignedAddOverflow(-1, -1)) { + throw new RuntimeException("Error"); + } + + if (!Utils.unsignedAddOverflow(-1, 1)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedAddOverflow(10000, 10000)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedSubOverflow(-1, 1)) { + throw new RuntimeException("Error"); + } + + if (!Utils.unsignedSubOverflow(1, -1)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedSubOverflow(-1, -1)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedSubOverflow(10, 0)) { + throw new RuntimeException("Error"); + } + + if (!Utils.unsignedSubOverflow(0, 10)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedAddOverflow(0x70000000, 0x10000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedAddOverflow(0x90000000, 0x10000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedAddOverflow(0x50000000, 0x50000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedAddOverflow(0x60000000, 0x10000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedAddOverflow(0x10000000, 0x60000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedSubOverflow(0x80000000, 0x30000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedSubOverflow(0x30000000, 0x80000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedSubOverflow(0, 0x80000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedSubOverflow(0, 0x70000000)) { + throw new RuntimeException("Error"); + } } } 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-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-04-24 18:16:44 UTC (rev 90) @@ -1,11 +1,14 @@ package org.binarytranslator.arch.arm.os.abi.linux; +import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; 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) { + private final ARM_LinuxProcessSpace ps; + + public ARM_LinuxSystemCalls(ARM_LinuxProcessSpace ps, LinuxSystemCallGenerator src) { super(src); systemCallTable[1] = new LinuxSystemCalls.SysExit(); @@ -19,6 +22,7 @@ systemCallTable[49] = new LinuxSystemCalls.SysGetEUID(); systemCallTable[50] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[90] = new LinuxSystemCalls.SysMmap(); + systemCallTable[91] = new LinuxSystemCalls.SysMunmap(); systemCallTable[122] = new LinuxSystemCalls.SysUname(); systemCallTable[146] = new LinuxSystemCalls.SysWriteV(); systemCallTable[197] = new LinuxSystemCalls.SysFstat64(); @@ -28,8 +32,16 @@ systemCallTable[202] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[221] = new LinuxSystemCalls.SysFcntl64(); systemCallTable[252] = new LinuxSystemCalls.SysExitGroup(); + + this.ps = ps; } + + @Override + public void doSysCall() { + super.doSysCall(); + } + @Override protected String getMachine() { //TODO: Grab this from a real machine Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-24 18:16:44 UTC (rev 90) @@ -4,6 +4,7 @@ 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; 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-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-24 18:16:44 UTC (rev 90) @@ -28,18 +28,13 @@ private static final int STACK_TOP = 0xC0000000; /** - * The top of the bss segment - */ - private int brk; - - /** * Auxiliary vector */ private int[] auxVector; public ARM_LinuxProcessSpace() { - sysCallGenerator = new Legacy(this); - sysCalls = new ARM_LinuxSystemCalls(sysCallGenerator); + sysCallGenerator = new Legacy(this, 0xEBADADD); + sysCalls = new ARM_LinuxSystemCalls(this, sysCallGenerator); } @Override @@ -54,31 +49,52 @@ @Override public void initialise(Loader loader, int pc, int brk) { registers.set(ARM_Registers.PC, pc); - this.brk = brk; + sysCallGenerator.setBrk(brk); // initialize the stack - auxVector = new int[]{//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, ((ELF_Loader)loader).getProgramHeaderAddress(), - LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, ((ELF_Loader)loader).elfHeader.getNumberOfProgramSegmentHeaders(), - LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, + auxVector = new int[] { + LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x97, + LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 4096, //0x100 + LinuxStackInitializer.AuxiliaryVectorType.AT_CLKTCK, 0x17, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, 0x8034, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHENT, 0x20, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, 0x6, + LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x40000000, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, - LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, pc, + LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, 0x82b4, + LinuxStackInitializer.AuxiliaryVectorType.AT_UID, 0x0, + LinuxStackInitializer.AuxiliaryVectorType.AT_EUID, 0x0, + LinuxStackInitializer.AuxiliaryVectorType.AT_GID, 0x0, + LinuxStackInitializer.AuxiliaryVectorType.AT_EGID, 0x0, + LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, 0xbffffecd }; - 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_PLATFORM, LinuxStackInitializer.AuxiliaryVectorType.STACK_TOP - getPlatformString().length, - LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0}; - registers.set(ARM_Registers.SP, LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector)); } + + public void dumpStack() { + //grab the current frame pointer + int fp = registers.get(ARM_Registers.FP); + + //print the current position + System.out.println("PC: 0x" + Integer.toHexString(registers.get(ARM_Registers.PC))); + + //we might be in a leaf function which did not create a stack frame. Check that by + //comparing the current link register with the one saved on the first stack frame + int saved_lr = memory.load32(fp - 4); + int processor_lr = registers.get(ARM_Registers.LR); + + if (saved_lr != processor_lr) { + //we are in a leaf function that did not generate a stack frame. Print out the function address + System.out.println("Called from 0x" + Integer.toHexString(processor_lr - 4) + " (Function did not create a stack frame)."); + } + + do { + saved_lr = memory.load32(fp - 4); //load the link register, so we know where we're called from + fp = memory.load32(fp - 12); //load the previous frame pointer + System.out.println("Called from 0x" + Integer.toHexString(saved_lr - 4)); + } + while (fp != 0); + } @Override public GdbTarget getGdbTarget() { Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-24 18:16:44 UTC (rev 90) @@ -1,6 +1,7 @@ package org.binarytranslator.arch.arm.os.process.linux.abi; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; +import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -28,15 +29,16 @@ /** The process space that we're running on. */ private final ARM_LinuxProcessSpace ps; private final ArgumentIterator args; + private int brk; - public EABI(ARM_LinuxProcessSpace ps) { + public EABI(ARM_LinuxProcessSpace ps, int brk) { this.ps = ps; + this.brk = brk; this.args = new ArgumentIterator(); } public int getBrk() { - // TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + return brk; } public ProcessSpace getProcessSpace() { @@ -53,8 +55,16 @@ } public void setBrk(int address) { -// TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + + try { + ps.memory.ensureMapped(brk, address); + } catch (MemoryMapException e) { + throw new Error(String.format( + "Error changing top of BSS from 0x%x to address 0x%x", brk, address), + e); + } + + brk = address; } public void setSysCallError(int r) { Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-24 18:16:44 UTC (rev 90) @@ -4,6 +4,7 @@ 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.memory.MemoryMapException; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -30,21 +31,29 @@ /** A re-used iterator that allows enumerating the argument of the current * system call */ private final ArgumentIterator syscallArgs; + + private int brk; - public Legacy(ARM_LinuxProcessSpace ps) { + public Legacy(ARM_LinuxProcessSpace ps, int brk) { this.ps = ps; + this.brk = brk; syscallArgs = new ArgumentIterator(); } public int getBrk() { -// TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + return brk; } public void setBrk(int address) { -// TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + try { + ps.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; } public ProcessSpace getProcessSpace() { Modified: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-24 18:16:44 UTC (rev 90) @@ -10,6 +10,8 @@ import java.io.RandomAccessFile; import java.nio.channels.FileChannel; + +import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.vmInterface.TranslationHelper; import org.jikesrvm.compilers.opt.ir.OPT_Operand; @@ -121,10 +123,21 @@ */ public int map(int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException { - // Check address is page aligned + // Check that the address is page aligned if ((addr % PAGE_SIZE) != 0) { - MemoryMapException.unalignedAddress(addr); + // if it is not, truncate the address down to the next page boundary and + // start mapping from there + int validPageCount = addr / PAGE_SIZE; + int oldStartAddress = addr; + addr = validPageCount * PAGE_SIZE; + + if (DBT.VerifyAssertions) + DBT._assert(oldStartAddress > addr); + + // we have to map more more memory now to reach the same end address + len += (oldStartAddress - addr); } + // Create memory int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; byte pages[][] = new byte[num_pages][PAGE_SIZE]; Modified: src/org/binarytranslator/generic/memory/IntAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-04-24 18:16:44 UTC (rev 90) @@ -10,6 +10,7 @@ import java.io.RandomAccessFile; +import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.jikesrvm.VM_Configuration; @@ -191,10 +192,21 @@ */ public int map(int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException { - // Check address is page aligned + // Check that the address is page aligned if ((addr % PAGE_SIZE) != 0) { - MemoryMapException.unalignedAddress(addr); + // if it is not, truncate the address down to the next page boundary and + // start mapping from there + int validPageCount = addr / PAGE_SIZE; + int oldStartAddress = addr; + addr = validPageCount * PAGE_SIZE; + + if (DBT.VerifyAssertions) + DBT._assert(oldStartAddress > addr); + + // we have to map more more memory now to reach the same end address + len += (oldStartAddress - addr); } + // Calculate number of pages int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; // Create memory Modified: src/org/binarytranslator/generic/memory/Memory.java =================================================================== --- src/org/binarytranslator/generic/memory/Memory.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/generic/memory/Memory.java 2007-04-24 18:16:44 UTC (rev 90) @@ -251,4 +251,41 @@ throw new Error("Error linking method at " + callAddress + " for memory model " + this.getClass()); } + + /** + * Helper function that prints a hexadecimal version of a memory region. + * Quite useful for debugging. + * @param address + * The address to start printing from. + * @param length + * The number of bytes to print from <code>address</code>. + * @return + * A string with a hexdecimal representation of that memory region. + * The string is only useful for printing, no assumptions about its format + * shall be made. + */ + public String hexDump(int address, int length) { + + StringBuilder output = new StringBuilder(); + int printed = 0; + + while (printed != length) { + + //make a line break and print the current address every 8 bytes + if (printed % 8 == 0) { + if (printed != 0) + output.append('\n'); + + output.append("[0x"); + output.append(Integer.toHexString(address)); + output.append("] "); + } + + output.append(String.format("%02x", loadUnsigned8(address++))); + output.append(' '); + printed++; + } + + return output.toString(); + } } \ No newline at end of file Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java 2007-04-24 18:16:44 UTC (rev 90) @@ -5,17 +5,28 @@ import org.binarytranslator.generic.memory.Memory; -/** Namespace for all structures. */ +/** + * Linux heavily uses certain c-structs when to pass parameters for system calls. + * To allow the pearcolator linux ABIs to share a common set of structure definitions, this + * namespace provides a factory for Java representations of the most commonly used structures. + * Each structure provides methods to read the structure from or write it to memory. + * + * @author Michael Baer + */ public class LinuxStructureFactory { + /** A factory method which will create a stat64 structure.*/ public final stat64 new_stat64() { return new stat64(); } + /** + * The stat64 structure, as defined in <code>include\linux\stat64.h</code>. + */ public class stat64 extends Structure { @_unsigned short st_dev; @_unsigned @_padding(10) byte __pad0; - @_unsigned @_long long __st_ino; + @_unsigned long __st_ino; @_unsigned int st_mode; @_unsigned int st_nlink; @_unsigned long st_uid; @@ -34,11 +45,80 @@ @_unsigned @_padding(1) long __pad7; @_unsigned @_long long st_ino; - public stat64() { + /** + * At the moment, we have to enumerate the members of a structure in the constructor + * (in the order of definition within the c file), because the JVM specs say that no code shall + * rely on the order of the fields returned by reflection methods (namely {@link Class#getFields()}. + * + * Therefore, we have to persist the order of fields, which is why we are enumerating them again. + * However, this is not necessary the final solution. Possibly we're going to introduce a + * Java annotation that keeps the information about the order - or we might even solve the problem + * completely differently. + * + */ + protected stat64() { super(new String[]{ "st_dev", "__pad0", "__st_ino", "st_mode", "st_nlink", "st_uid", "st_gid", "st_rdev", "__pad3", "st_size", "st_blksize", "st_blocks", "__pad4", "st_atime", "__pad5", "st_mtime", "__pad6", "st_ctime", "__pad7", "st_ino"}); } + + /** This overriden structure enables Michael to debug the pearcolator in windows. + * Otherwise, it should not be used, which is why it is deprecated. */ + @Override + @Deprecated + public void read(Memory mem, int addr) { + StructureAdapter reader = createStructureAdapter(mem, addr); + + st_dev = reader.loadShort(); + reader.skipPadding(10); + __st_ino = reader.loadLong(); + st_mode = reader.loadInt(); + st_nlink = reader.loadInt(); + st_uid = reader.loadLong(); + st_gid = reader.loadLong(); + st_rdev = reader.loadShort(); + reader.skipPadding(10); + st_size = reader.loadLongLong(); + st_blksize = reader.loadLong(); + st_blocks = reader.loadLong(); + __pad4 = reader.loadLong(); + st_atime = reader.loadLong(); + __pad5 = reader.loadLong(); + st_mtime = reader.loadLong(); + __pad6 = reader.loadLong(); + st_ctime = reader.loadLong(); + __pad7 = reader.loadLong(); + st_ino = reader.loadLongLong(); + } + + /** + * This overriden structure enables Michael to debug the pearcolator in windows. + * Otherwise, it should not be used, which is why it is deprecated. */ + @Override + @Deprecated + public void write(Memory mem, int addr) { + StructureAdapter writer = createStructureAdapter(mem, addr); + writer.storeShort(st_dev); + writer.skipPadding(10); + writer.storeLong(__st_ino); + writer.storeInt(st_mode); + writer.storeInt(st_nlink); + writer.storeLong(st_uid); + writer.storeLong(st_gid); + writer.storeShort(st_rdev); + writer.skipPadding(10); + writer.storeLongLong(st_size); + writer.storeLong(st_blksize); + writer.storeLong(st_blocks); + writer.storeLong(__pad4); + writer.storeLong(st_atime); + writer.storeLong(__pad5); + writer.storeLong(st_mtime); + writer.storeLong(__pad6); + writer.storeLong(st_ctime); + writer.storeLong(__pad7); + writer.storeLongLong(st_ino); + } } private @interface _long {} @@ -50,9 +130,18 @@ /** A list of all structure members in the order that they appear in the source code. */ protected Field[] members; + /** + * This constructor is uncommented because reflection does not work when debugging pearcolator + * under windows, which is what I (=Michael Baer) am currently doing. + * + * However, as soon as this is done, the deprecated-tag shall be removed and the code in this + * function be uncommented. + * @param memberNames + */ + @Deprecated protected Structure(String[] memberNames) { - Class myType = getClass(); + /*Class myType = getClass(); members = new Field[memberNames.length]; for (int i = 0; i < memberNames.length; i++) { @@ -63,9 +152,17 @@ catch (NoSuchFieldException e) { throw new RuntimeException("Invalid field: " + memberNames[i] + " in struct: " + myType.getSimpleName(), e); } - } + }*/ } + /** + * Read all members of this structure from memory into the structure. + * + * @param mem + * The memory that the structure is read from. + * @param addr + * The address of the structure's beginning in the memory. + */ public void read(Memory mem, int addr) { // get a structure writer, which will keep track of the object offsets @@ -112,6 +209,14 @@ } } + /** + * Writes the contents of the structure from its members into memory. + * + * @param mem + * The Memory into which the structure shall be written. + * @param addr + * The address, to which the structure is written. + */ public void write(Memory mem, int addr) { // get a structure writer, which will keep track of the object offsets @@ -165,6 +270,8 @@ } } + /** + * Converts a structure into a c-like, human readable format */ @Override public String toString() { @@ -193,10 +300,32 @@ } } + /** + * A factory method that creates a {@link StructureAdapter}. StructureAdapters are used to + * encapsulate the architecture specifics (like <code>sizeof(int)</code> and padding) when + * reading a structure. + * + * Implement your own StructureAdapter when you need to override the default implementations of + * how a structure is being read, while still keeping the default structures defined here. + * + * @param mem + * @param addr + * @return + */ protected final StructureAdapter createStructureAdapter(Memory mem, int addr) { - return new DefaultStructureAdapter(mem, addr); + return new StructureAdapter_32Bit(mem, addr); } + /** + * A StructureAdapter abstracts the properties (size, padding, maybe endianess) of the elements + * within a structure. Provide an own implementation of this class when the default data sizes + * and member alignments are not suitable for your architecture. + * + * Structures are always being read in the order of element definition. Therefore, any implementation + * of StructureAdapter can rely on the load/store functions being called in order, from the first + * to the last structure element. + * + */ protected static abstract class StructureAdapter { public abstract byte loadByte(); @@ -211,15 +340,51 @@ public abstract void storeLong(long value); public abstract void storeLongLong(long value); + /** + * Some structures contain rather large padding fields. To prevent use from reading these from + * memory byte-by-byte, this function may be used to skip a padding of type <code>field</code> + * that occurs <code>count</code> times. + * + * For example, when skipping a member like this <code>char pad[10]</char> the <code>field</code> + * would identify this as a char field, while the <code>count</code> member would say that we want + * to skip the char 10 times. + * + * @param field + * The type of the field that is being skipped. + * @param count + * The number of times this field as a padding in the structure. + */ public abstract void skipPadding(Field field, int count); + + /** + * This function is used temporarly to debug pearcolator in windows. However, + * it should normally not be invoked and as soon as windows-debugging is done, this + * function shall be removed from the source (along with all invokations of it).*/ + @Deprecated + public abstract void skipPadding(int count); } - protected static class DefaultStructureAdapter extends StructureAdapter { + /** + * A default implementation of a structure adapter. It has the following properties: + * + * <ul> + * <li>Every member is memory aligned to its size (i.e. a 4-byte data type is aligned to 4-byte + * boundaries</li> + * <li>The minimal needed amount of padding is inserted where the member is not already + * aligned to its size.</li> + * <li><code>sizeof(int) == 4</code></li> + * <li><code>sizeof(long) == 4</code></li> + * <li><code>sizeof(long long) == 8</code></li> + * <li><code>sizeof(short) == 2</code></li> + * <li><code>sizeof(byte) == 1</code></li> + * </ul> + */ + protected static class StructureAdapter_32Bit extends StructureAdapter { private final Memory mem; private int addr; - public DefaultStructureAdapter(Memory mem, int addr) { + public StructureAdapter_32Bit(Memory mem, int addr) { this.mem = mem; this.addr = addr; } @@ -350,5 +515,10 @@ return; } } + + @Override + public void skipPadding(int count) { + addr += count; + } } } Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-24 18:16:44 UTC (rev 90) @@ -23,13 +23,13 @@ /** * The source of the system calls */ - private LinuxSystemCallGenerator src; + protected LinuxSystemCallGenerator src; /** Allows access to the system call's arguments */ - private LinuxSystemCallGenerator.CallArgumentIterator arguments; + protected LinuxSystemCallGenerator.CallArgumentIterator arguments; /** Allows access to a number of operating-system specific structures. */ - private LinuxStructureFactory structures; + protected LinuxStructureFactory structures; /** * Maximum number of system calls @@ -802,9 +802,18 @@ int fd = arguments.nextInt(); LinuxStructureFactory.stat64 buf = structures.new_stat64(); - buf.read(src.getProcessSpace().memory, arguments.nextInt()); - System.out.println(buf.toString()); + if (fd == 1) { + buf.st_mode = 0x2180; + buf.st_rdev = (short)0x8800; + buf.__st_ino = buf.st_ino = 2; + buf.st_blksize = 0x400; + } + else + throw new RuntimeException("Unimplemented system call."); + + buf.write(src.getProcessSpace().memory, arguments.nextInt()); + src.setSysCallReturn(0); } } @@ -893,8 +902,9 @@ int start = arguments.nextInt(); int length = arguments.nextInt(); - throw new Error("TODO!"); - //src.setSysCallReturn(src.munmap(start, length)); + + src.getProcessSpace().memory.unmap(start, length); + src.setSysCallReturn(0); } } 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: <mic...@us...> - 2007-04-23 21:57:27
|
Revision: 88 http://svn.sourceforge.net/pearcolator/?rev=88&view=rev Author: michael_baer Date: 2007-04-23 14:57:27 -0700 (Mon, 23 Apr 2007) Log Message: ----------- Fixed a bug with flag handling after subtractions on ARM Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-23 17:10:21 UTC (rev 87) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-23 21:57:27 UTC (rev 88) @@ -540,14 +540,21 @@ preIndexing = Utils.getBit(instr, 24); positiveOffset = Utils.getBit(instr, 23); - writeBack = Utils.getBit(instr, 21); isLoad = Utils.getBit(instr, 20); if (Utils.getBit(instr, 26)) { //this is an unsigned byte or word transfer signExtend = false; - forceUserMode = !preIndexing && writeBack; + //if post-indexing implies writeBack, so set the writeback flag when postindexing is used + if (!preIndexing) { + writeBack = true; + forceUserMode = Utils.getBit(instr, 21); + } + else { + writeBack = Utils.getBit(instr, 21); + forceUserMode = false; + } if (Utils.getBit(instr, 22)) size = TransferSize.Byte; @@ -567,6 +574,7 @@ size = TransferSize.Byte; signExtend = Utils.getBit(instr, 6); + writeBack = Utils.getBit(instr, 21); forceUserMode = false; if (Utils.getBit(instr, 22)) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-23 17:10:21 UTC (rev 87) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-23 21:57:27 UTC (rev 88) @@ -340,7 +340,23 @@ } } } + + /** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/ + protected final void setFlagsForSub(int lhs, int rhs) { + if (updateConditionCodes) { + if (Rd != 15) { + int result = lhs - rhs; + boolean carry = !(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; @@ -380,7 +396,7 @@ } /** Add. <code>Rd = op1 + op2 </code>.*/ - private class DataProcessing_Add extends DataProcessing { + private final class DataProcessing_Add extends DataProcessing { public DataProcessing_Add(int instr) { super(instr); @@ -397,127 +413,125 @@ } /** Subtract. <code>Rd = op1 - op2 </code>.*/ - private final class DataProcessing_Sub extends DataProcessing_Add { + private final class DataProcessing_Sub extends DataProcessing { public DataProcessing_Sub(int instr) { super(instr); } + + @Override + public void execute() { + int operand1 = resolveOperand1(); + int operand2 = resolveOperand2(); + int result = operand1 - operand2; - @Override - protected int resolveOperand2() { - return -super.resolveOperand2(); + regs.set(Rd, result); + setFlagsForSub(operand1, operand2); } } - /** Reverse subtract. <code>Rd = - op1 + op2</code>.*/ - private final class DataProcessing_Rsb extends DataProcessing_Add { + /** Reverse subtract. <code>Rd = op2 - op1</code>.*/ + private final class DataProcessing_Rsb extends DataProcessing { protected DataProcessing_Rsb(int instr) { super(instr); } @Override - protected int resolveOperand1() { - return -super.resolveOperand1(); + public void execute() { + int operand1 = resolveOperand1(); + int operand2 = resolveOperand2(); + int result = operand2 - operand1; + + regs.set(Rd, result); + setFlagsForSub(operand2, operand1); } } /** Add with carry. <code>Rd = op1 + op2 + CARRY</code>. * If the carry flag is set, the instruction will add 1 to one of the operands (whichever operands would - * not cause an overflow). Then, the normal add-routine is being invoked. - * The class is also used as a base class for the subtract with carry (SBC) and reverse subtract with - * carry (RSC) instructions. Therefore, it provides added functionality to optionally negate one or both - * of the operands.*/ - private class DataProcessing_Adc extends DataProcessing_Add { + * not cause an overflow). Then, the normal add-routine is being invoked. */ + private final class DataProcessing_Adc extends DataProcessing { - /** A cached version of the first operand. A carry might be added to this operand. */ - protected int cachedOperand1; - - /** A cached version of the second operand. A carry might be added to this operand, if no carry could - * be added to the first operand.. */ - protected int cachedOperand2; - protected DataProcessing_Adc(int instr) { super(instr); } @Override - protected final int resolveOperand1() { - return cachedOperand1; - } - - @Override - protected final int resolveOperand2() { - return cachedOperand2; - } - - /** Shall be overwritten by deriving classes, if they wish the first operand to be negated before - * the addition. */ - protected boolean negateOperand1() { - return false; - } - - /** Shall be overwritten by deriving classes, if they wish the second operand to be negated before - * the addition. */ - protected boolean negateOperand2() { - return false; - } - - @Override public void execute() { - cachedOperand1 = super.resolveOperand1(); - cachedOperand2 = super.resolveOperand2(); - - if (negateOperand1()) - cachedOperand1 = -cachedOperand1; - - if (negateOperand2()) - cachedOperand2 = -cachedOperand2; + int operand1 = resolveOperand1(); + int operand2 = resolveOperand2(); if (regs.isCarrySet()) { - if (cachedOperand1 != Integer.MAX_VALUE) { - cachedOperand1++; - } else if (cachedOperand2 != Integer.MAX_VALUE) { - cachedOperand2++; + if (operand1 != Integer.MAX_VALUE) { + operand1++; + } else if (operand2 != Integer.MAX_VALUE) { + operand2++; } else { - regs.setFlags(cachedOperand1 > 0, cachedOperand1 != 0, true, true); + regs.setFlags(operand1 > 0, operand1 != 0, true, true); return; } } - super.execute(); + int result = operand1 + operand2; + + regs.set(Rd, result); + setFlagsForAdd(operand1, operand2); } } /** Subtract with carry. <code>Rd = op1 - op2 + CARRY</code>.*/ - private class DataProcessing_Sbc extends DataProcessing_Adc { + private class DataProcessing_Sbc extends DataProcessing { protected DataProcessing_Sbc(int instr) { super(instr); } + + public void execute() { + int operand1 = resolveOperand1(); + int operand2 = resolveOperand2(); - @Override - protected boolean negateOperand2() { - return true; + if (!regs.isCarrySet()) { + if (operand1 != Integer.MIN_VALUE) { + operand1--; + } else if (operand2 != Integer.MIN_VALUE) { + operand2--; + } else { + //TODO: Remove this exception, when the correct behavior has been verified. + throw new RuntimeException("I'm interested in finding a case where this occurs, so this exception is sooner or later going to 'notify' me.."); + //regs.setFlags(operand1 > 0, operand1 != 0, true, true); + //return; + } + } + + int result = operand1 - operand2; + + regs.set(Rd, result); + setFlagsForSub(operand1, operand2); } } /** Reserve subtract with carry. <code>Rd = -op1 + op2 + CARRY</code>.*/ - private class DataProcessing_Rsc extends DataProcessing_Adc { + private final class DataProcessing_Rsc extends DataProcessing_Sbc { protected DataProcessing_Rsc(int instr) { super(instr); } - + @Override - protected boolean negateOperand1() { - return true; + protected int resolveOperand1() { + return super.resolveOperand2(); } + + @Override + protected int resolveOperand2() { + return super.resolveOperand1(); + } } /** Set the flags according to the logical-and of two values. * <code>Flags = op1 & op2</code>*/ - private class DataProcessing_Tst extends DataProcessing { + private final class DataProcessing_Tst extends DataProcessing { protected DataProcessing_Tst(int instr) { super(instr); @@ -531,7 +545,7 @@ /** Sets the flags according to the exclusive-or of two values. * <code>Flags = op1 ^ op2</code> */ - private class DataProcessing_Teq extends DataProcessing { + private final class DataProcessing_Teq extends DataProcessing { protected DataProcessing_Teq(int instr) { super(instr); @@ -545,7 +559,7 @@ /** Set the flags according to the comparison of two values. * <code>Flags = op1 - op2</code> */ - private class DataProcessing_Cmp extends DataProcessing { + private final class DataProcessing_Cmp extends DataProcessing { protected DataProcessing_Cmp(int instr) { super(instr); @@ -553,13 +567,13 @@ @Override public void execute() { - setFlagsForAdd(resolveOperand1(), -resolveOperand2()); + setFlagsForSub(resolveOperand1(), resolveOperand2()); } } /** Set the flags according to the comparison of two values, negating the 2nd value on the way. * <code>Flags = op1 + op2</code>. */ - private class DataProcessing_Cmn extends DataProcessing { + private final class DataProcessing_Cmn extends DataProcessing { protected DataProcessing_Cmn(int instr) { super(instr); @@ -572,7 +586,7 @@ } /** Binary or. <code>Rd = op1 | op2</code>. */ - private class DataProcessing_Orr extends DataProcessing { + private final class DataProcessing_Orr extends DataProcessing { protected DataProcessing_Orr(int instr) { super(instr); @@ -586,7 +600,7 @@ } } - private class DataProcessing_Mov extends DataProcessing { + private final class DataProcessing_Mov extends DataProcessing { protected DataProcessing_Mov(int instr) { super(instr); @@ -603,7 +617,7 @@ /** Bit clear. Clear bits in a register by a mask given by a second operand. * <code>Rd = op1 & (~op2)</code>.*/ - private class DataProcessing_Bic extends DataProcessing { + private final class DataProcessing_Bic extends DataProcessing { protected DataProcessing_Bic(int instr) { super(instr); @@ -620,7 +634,7 @@ /** Move and negate. Moves an integer between two registers, negating it on the way. * <code>Rd = -op2</code>.*/ - private class DataProcessing_Mvn extends DataProcessing { + private final class DataProcessing_Mvn extends DataProcessing { protected DataProcessing_Mvn(int instr) { super(instr); @@ -636,7 +650,7 @@ /** Count the number of leading zeros in an integer. * <code>Rd = Number_Of_Leading_Zeroes(op2) </code> */ - private class DataProcessing_Clz extends DataProcessing { + private final class DataProcessing_Clz extends DataProcessing { protected DataProcessing_Clz(int instr) { super(instr); @@ -652,7 +666,7 @@ /** Swap a register and a memory value. * TODO: At the moment, Pearcolator does not support any way of locking the memory. However, once it does * any other memory accesses should be pending until the swap instruction succeeds.*/ - private class Swap extends ARM_Instructions.Swap implements + private final class Swap extends ARM_Instructions.Swap implements ARM_Instruction { public Swap(int instr) { @@ -677,7 +691,7 @@ } /** Transfer multiple registers at once between the register bank and the memory. */ - private class BlockDataTransfer extends ARM_Instructions.MultipleDataTransfer + private final class BlockDataTransfer extends ARM_Instructions.MultipleDataTransfer implements ARM_Instruction { /** the lowest address that we're reading a register from / writing a register to */ @@ -799,7 +813,7 @@ } /** Branch to another instruction address. */ - private class Branch extends ARM_Instructions.Branch implements + private final class Branch extends ARM_Instructions.Branch implements ARM_Instruction { public Branch(int instr) { @@ -821,7 +835,7 @@ } /** Branch to another instruction address and switch between ARM32 and Thumb code on the way.*/ - private class BranchExchange extends ARM_Instructions.BranchExchange + private final class BranchExchange extends ARM_Instructions.BranchExchange implements ARM_Instruction { public BranchExchange(int instr) { @@ -876,7 +890,7 @@ } /** Multiply two integers into a register, possibly adding the value of a third register on the way. */ - private class IntMultiply extends ARM_Instructions.IntMultiply implements + private final class IntMultiply extends ARM_Instructions.IntMultiply implements ARM_Instruction { protected IntMultiply(int instr) { @@ -923,7 +937,7 @@ } /** Move the value of the program status register into a register. */ - private class MoveFromStatusRegister extends + private final class MoveFromStatusRegister extends ARM_Instructions.MoveFromStatusRegister implements ARM_Instruction { @@ -949,7 +963,7 @@ } /** Invoke a software interrupt. */ - private class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt + private final class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt implements ARM_Instruction { public SoftwareInterrupt(int instr) { @@ -968,27 +982,16 @@ /** Transfers a single data item (either a byte, half-byte or word) between a register and memory. * This operation can either be a load from or a store to memory. */ - private class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer + private final class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer implements ARM_Instruction { public SingleDataTransfer(int instr) { super(instr); } - - /** Resolves the address of the memory slot, that is involved in the transfer. */ - private int resolveAddress() { - - //acquire the base address - int base = regs.get(Rn); - - //take ARM's PC offset into account - if (Rn == 15) - base += 8; - - //if we are not pre-indexing, then just use the base register for the memory access - if (!preIndexing) - return base; - + + /** Resolves the offset, which is (when post-indexing is not used) to be added to the + * base address to create the final address. */ + private int resolveOffset() { int addrOffset; switch (offset.getType()) { @@ -1005,7 +1008,7 @@ case ImmediateShiftedRegister: addrOffset = regs.get(offset.getRegister()); - + if (offset.getRegister() == 15) addrOffset += 8; @@ -1047,11 +1050,28 @@ } if (positiveOffset) - return base + addrOffset; + return addrOffset; else - return base - addrOffset; + return -1 * addrOffset; } + /** Resolves the address of the memory slot, that is involved in the transfer. */ + private int resolveAddress() { + + //acquire the base address + int base = regs.get(Rn); + + //take ARM's PC offset into account + if (Rn == 15) + base += 8; + + //if we are not pre-indexing, then just use the base register for the memory access + if (!preIndexing) + return base; + + return base + resolveOffset(); + } + public void execute() { //should we simulate a user-mode memory access? if (forceUserMode) { @@ -1114,15 +1134,15 @@ } } - //should the memory address, which we accessed, be written back into a register? This is used for continuos - //memory accesses + //should the memory address, which we accessed, be written back into a register? + //This is used for continuous memory accesses if (writeBack) { - if (preIndexing) + if (preIndexing) { regs.set(Rn, address); + } else { - //TODO: calculate the post-indexed address - //and set it to Rn - throw new RuntimeException("Not yet implemented."); + //add the offset to the base address and write the result back into Rn + regs.set(Rn, address + resolveOffset()); } } } @@ -1138,7 +1158,7 @@ /** Represents an undefined instruction, will throw a runtime error when this instruction * is executed. */ - private class UndefinedInstruction implements ARM_Instruction { + private final class UndefinedInstruction implements ARM_Instruction { private final int instruction; @@ -1159,7 +1179,7 @@ } } - private class DebugNopInstruction implements ARM_Instruction { + private final class DebugNopInstruction implements ARM_Instruction { public Condition getCondition() { return Condition.AL; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-23 17:11:39
|
Revision: 87 http://svn.sourceforge.net/pearcolator/?rev=87&view=rev Author: michael_baer Date: 2007-04-23 10:10:21 -0700 (Mon, 23 Apr 2007) Log Message: ----------- Testing a new way of accessing structs in system calls Modified Paths: -------------- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-23 16:37:12 UTC (rev 86) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-23 17:10:21 UTC (rev 87) @@ -27,6 +27,9 @@ /** Allows access to the system call's arguments */ private LinuxSystemCallGenerator.CallArgumentIterator arguments; + + /** Allows access to a number of operating-system specific structures. */ + private LinuxStructureFactory structures; /** * Maximum number of system calls @@ -154,6 +157,8 @@ files.add(System.in); files.add(System.out); files.add(System.err); + + structures = new LinuxStructureFactory(); } /** @@ -756,6 +761,12 @@ public class SysFstat64 extends SystemCall { public void doSysCall() { + int fd = arguments.nextInt(); + + LinuxStructureFactory.stat64 buf = structures.new_stat64(); + buf.read(src.getProcessSpace().memory, arguments.nextInt()); + + System.out.println(buf.toString()); } } @@ -795,6 +806,7 @@ 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-23 16:37:25
|
Revision: 86 http://svn.sourceforge.net/pearcolator/?rev=86&view=rev Author: michael_baer Date: 2007-04-23 09:37:12 -0700 (Mon, 23 Apr 2007) Log Message: ----------- New example of handling structures in java. Modified Paths: -------------- src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java 2007-04-23 14:09:57 UTC (rev 85) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java 2007-04-23 16:37:12 UTC (rev 86) @@ -1,101 +1,354 @@ package org.binarytranslator.generic.os.abi.linux; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + import org.binarytranslator.generic.memory.Memory; /** Namespace for all structures. */ public class LinuxStructureFactory { - public static class stat64_3 { - public int st_dev; - public short st_mode; + public final stat64 new_stat64() { + return new stat64(); + } + + public class stat64 extends Structure { + @_unsigned short st_dev; + @_unsigned @_padding(10) byte __pad0; + @_unsigned @_long long __st_ino; + @_unsigned int st_mode; + @_unsigned int st_nlink; + @_unsigned long st_uid; + @_unsigned long st_gid; + @_unsigned short st_rdev; + @_unsigned @_padding(10) byte __pad3; + @_long long st_size; + @_unsigned long st_blksize; + @_unsigned long st_blocks; + @_unsigned @_padding(1) long __pad4; + @_unsigned long st_atime; + @_unsigned @_padding(1) long __pad5; + @_unsigned long st_mtime; + @_unsigned @_padding(1) long __pad6; + @_unsigned long st_ctime; + @_unsigned @_padding(1) long __pad7; + @_unsigned @_long long st_ino; - /** Implemented with a reflection by a base class*/ - public void store(Memory m) {} - public void read(Memory m) {} + public stat64() { + super(new String[]{ "st_dev", "__pad0", "__st_ino", "st_mode", "st_nlink", "st_uid", + "st_gid", "st_rdev", "__pad3", "st_size", "st_blksize", "st_blocks", "__pad4", "st_atime", + "__pad5", "st_mtime", "__pad6", "st_ctime", "__pad7", "st_ino"}); + } } - /** Solution 2 - automatically generated class. Fast, but pretty unflexible.*/ - public static class stat64_2 { + private @interface _long {} + private @interface _unsigned {} + private @interface _padding { int value(); } + + private class Structure { - private Memory mem; - private int addr; + /** A list of all structure members in the order that they appear in the source code. */ + protected Field[] members; - void st_dev(int value) { - mem.store32(addr + 3, value); + protected Structure(String[] memberNames) { + + Class myType = getClass(); + members = new Field[memberNames.length]; + + for (int i = 0; i < memberNames.length; i++) { + try { + Field field = myType.getField(memberNames[i]); + members[i] = field; + } + catch (NoSuchFieldException e) { + throw new RuntimeException("Invalid field: " + memberNames[i] + " in struct: " + myType.getSimpleName(), e); + } + } } - int st_dev() { - return mem.load32(addr + 3); + public void read(Memory mem, int addr) { + + // get a structure writer, which will keep track of the object offsets + StructureAdapter reader = createStructureAdapter(mem, addr); + + // traverse all public fields + for (Field f : members) { + if (!Modifier.isPrivate(f.getModifiers())) { + try { + // store each public field one after the other + Class<?> type = f.getClass(); + + if (type == int.class) { + f.setInt(this, reader.loadInt()); + continue; + } + + if (type == long.class) { + + if (f.getAnnotation(_long.class) != null) + f.setLong(this, reader.loadLongLong()); + else + f.setLong(this, reader.loadLong()); + continue; + } + + if (type == short.class) { + f.setShort(this, reader.loadShort()); + continue; + } + + if (type == byte.class) { + f.setByte(this, reader.loadByte()); + continue; + } + + throw new RuntimeException( + "Unknown data type while persisting struct: " + this); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "Unknown data type while persisting struct: " + this, e); + } + } + } } + + public void write(Memory mem, int addr) { + + // get a structure writer, which will keep track of the object offsets + StructureAdapter writer = createStructureAdapter(mem, addr); + + // traverse all public fields + for (Field f : members) { + if (!Modifier.isPrivate(f.getModifiers())) { + try { + // store each public field one after the other + Class<?> type = f.getClass(); + + // check if that data type represents a certain amount of padding + _padding padding = f.getAnnotation(_padding.class); + if (padding != null) { + writer.skipPadding(f, padding.value()); + continue; + } + + if (type == int.class) { + writer.storeInt(f.getInt(this)); + continue; + } + + if (type == long.class) { + if (f.getAnnotation(_long.class) != null) + writer.storeLongLong(f.getLong(this)); + else + writer.storeLong(f.getLong(this)); + + continue; + } + + if (type == short.class) { + writer.storeShort(f.getShort(this)); + continue; + } + + if (type == byte.class) { + writer.storeByte(f.getByte(this)); + continue; + } + + throw new RuntimeException( + "Unknown data type while persisting struct: " + this); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "Unknown data type while persisting struct: " + this, e); + } + } + } + } + + @Override + public String toString() { + + StringBuilder struct = new StringBuilder(); + struct.append("struct "); + struct.append(getClass().getSimpleName()); + struct.append(" {\n"); + + // traverse all struct members + for (Field f : members) { + if (!Modifier.isPrivate(f.getModifiers())) { + try { + struct.append(f.getName()); + struct.append(" = "); + struct.append(f.get(this).toString()); + } + catch (IllegalAccessException e) {} + + struct.append('\n'); + } + } + + struct.append('}'); + + return struct.toString(); + } } - /** Solution 3 - class members created from factory method. More flexible, but higher overhead. */ - public static class stat64 extends Structure { - public final _Int st_dev = newInt(); - public final _Short st_mode = newShort(); + protected final StructureAdapter createStructureAdapter(Memory mem, int addr) { + return new DefaultStructureAdapter(mem, addr); } + protected static abstract class StructureAdapter { + + public abstract byte loadByte(); + public abstract short loadShort(); + public abstract int loadInt(); + public abstract long loadLong(); + public abstract long loadLongLong(); + + public abstract void storeByte(byte value); + public abstract void storeShort(short value); + public abstract void storeInt(int value); + public abstract void storeLong(long value); + public abstract void storeLongLong(long value); + + public abstract void skipPadding(Field field, int count); + } - - - protected static class Structure { + protected static class DefaultStructureAdapter extends StructureAdapter { - protected Memory memory; - private int curOffset = 0; + private final Memory mem; + private int addr; - public abstract class StructureElement<T> { - - protected int address; - public abstract T get(); - public abstract void set(T value); + public DefaultStructureAdapter(Memory mem, int addr) { + this.mem = mem; + this.addr = addr; } - protected _Int newInt() { - _Int i = new _Int(curOffset); - curOffset += 4; - - return i; + private final void shortAlignAddress() { + if ((addr & 0xFFFFFFFE) != addr) + addr = (addr & 0xFFFFFFFE) + 2; } - protected _Short newShort() { - _Short s = new _Short(curOffset); - curOffset += 2; + private final void intAlignAddress() { + if ((addr & 0xFFFFFFFC) != addr) + addr = (addr & 0xFFFFFFFC) + 4; + } + + private final void longAlignAddress() { + if ((addr & 0xFFFFFFFC) != addr) + addr = (addr & 0xFFFFFFFC) + 8; + } + + @Override + public void storeByte(byte value) { + mem.store8(addr, value); + addr++; + } + + @Override + public void storeInt(int value) { + //make sure that address is int aligned + intAlignAddress(); + mem.store32(addr, value); + addr += 4; + } + + @Override + public void storeLong(long value) { + //in a lot of C dialects, longs are treated as ints + storeInt((int)value); + } + + @Override + public void storeLongLong(long value) { + longAlignAddress(); - return s; + mem.store32(addr, (int)(value & 0xFFFFFFFF)); + mem.store32(addr, (int)(value >> 32)); + addr += 8; } - public class _Int extends StructureElement<Integer> { + @Override + public void storeShort(short value) { + shortAlignAddress(); + mem.store16(addr, value); + addr += 2; + } + + @Override + public byte loadByte() { + return (byte)mem.loadUnsigned8(addr++); + } + + @Override + public int loadInt() { + intAlignAddress(); + int value = mem.load32(addr); + addr += 4; - private _Int(int offset) { - this.address = offset; - } + return value; + } - @Override - public Integer get() { - return memory.load32(address); - } + @Override + public long loadLong() { + return loadInt(); + } - @Override - public void set(Integer value) { - memory.store32(address, value); - } + @Override + public long loadLongLong() { + longAlignAddress(); + long value = mem.load32(addr); + addr += 8; + value = value | (mem.load32(addr) << 32); + addr += 8; + + return value; } - public class _Short extends StructureElement<Short> { + @Override + public short loadShort() { + shortAlignAddress(); + short value = (short)mem.loadUnsigned16(addr); + addr += 2; - private _Short(int offset) { - this.address = offset; + return value; + } + + @Override + public void skipPadding(Field field, int count) { + + Class<?> type = field.getType(); + + if (type == byte.class) { + addr += count; + return; } - - @Override - public Short get() { - return (short) memory.loadUnsigned16(address); + + if (type == short.class) { + shortAlignAddress(); + addr += count * 2; + return; } - - @Override - public void set(Short value) { - memory.store16(address, value); + + if (type == int.class) { + intAlignAddress(); + addr += count * 4; + return; } + + if (type == long.class) { + + if (field.getAnnotation(_long.class) != null) { + longAlignAddress(); + addr += count * 8; + } + else { + intAlignAddress(); + addr += count * 4; + } + + return; + } } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-23 14:09:55
|
Revision: 85 http://svn.sourceforge.net/pearcolator/?rev=85&view=rev Author: michael_baer Date: 2007-04-23 07:09:57 -0700 (Mon, 23 Apr 2007) Log Message: ----------- For Ian, 2nd part Modified Paths: -------------- src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java 2007-04-23 14:02:09 UTC (rev 84) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java 2007-04-23 14:09:57 UTC (rev 85) @@ -5,9 +5,18 @@ /** Namespace for all structures. */ public class LinuxStructureFactory { - /** Solution 1 - automatically generated class. Fast, but pretty unflexible.*/ - public class stat64_2 { + public static class stat64_3 { + public int st_dev; + public short st_mode; + /** Implemented with a reflection by a base class*/ + public void store(Memory m) {} + public void read(Memory m) {} + } + + /** Solution 2 - automatically generated class. Fast, but pretty unflexible.*/ + public static class stat64_2 { + private Memory mem; private int addr; @@ -20,7 +29,7 @@ } } - /** Solution 2 - class members created from factory method. More flexible, but higher overhead. */ + /** Solution 3 - class members created from factory method. More flexible, but higher overhead. */ public static class stat64 extends Structure { public final _Int st_dev = newInt(); public final _Short st_mode = newShort(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-23 14:02:09
|
Revision: 84 http://svn.sourceforge.net/pearcolator/?rev=84&view=rev Author: michael_baer Date: 2007-04-23 07:02:09 -0700 (Mon, 23 Apr 2007) Log Message: ----------- Just to show something to Ian... Added Paths: ----------- src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java Added: src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java 2007-04-23 14:02:09 UTC (rev 84) @@ -0,0 +1,92 @@ +package org.binarytranslator.generic.os.abi.linux; + +import org.binarytranslator.generic.memory.Memory; + +/** Namespace for all structures. */ +public class LinuxStructureFactory { + + /** Solution 1 - automatically generated class. Fast, but pretty unflexible.*/ + public class stat64_2 { + + private Memory mem; + private int addr; + + void st_dev(int value) { + mem.store32(addr + 3, value); + } + + int st_dev() { + return mem.load32(addr + 3); + } + } + + /** Solution 2 - class members created from factory method. More flexible, but higher overhead. */ + public static class stat64 extends Structure { + public final _Int st_dev = newInt(); + public final _Short st_mode = newShort(); + } + + + + + protected static class Structure { + + protected Memory memory; + private int curOffset = 0; + + public abstract class StructureElement<T> { + + protected int address; + public abstract T get(); + public abstract void set(T value); + } + + protected _Int newInt() { + _Int i = new _Int(curOffset); + curOffset += 4; + + return i; + } + + protected _Short newShort() { + _Short s = new _Short(curOffset); + curOffset += 2; + + return s; + } + + public class _Int extends StructureElement<Integer> { + + private _Int(int offset) { + this.address = offset; + } + + @Override + public Integer get() { + return memory.load32(address); + } + + @Override + public void set(Integer value) { + memory.store32(address, value); + } + } + + public class _Short extends StructureElement<Short> { + + private _Short(int offset) { + this.address = offset; + } + + @Override + public Short get() { + return (short) memory.loadUnsigned16(address); + } + + @Override + public void set(Short value) { + memory.store16(address, value); + } + } + } +} 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 09:23:23
|
Revision: 82 http://svn.sourceforge.net/pearcolator/?rev=82&view=rev Author: captain5050 Date: 2007-04-23 02:23:22 -0700 (Mon, 23 Apr 2007) Log Message: ----------- Support for GDB auxv packet Modified Paths: -------------- 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/execution/GdbController.java tests/gcc_simple/x86/helloworld 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-22 17:03:27 UTC (rev 81) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-23 09:23:22 UTC (rev 82) @@ -32,6 +32,11 @@ */ private int brk; + /** + * Auxiliary vector + */ + private int[] auxVector; + public ARM_LinuxProcessSpace() { sysCallGenerator = new Legacy(this); sysCalls = new ARM_LinuxSystemCalls(sysCallGenerator); @@ -52,7 +57,7 @@ this.brk = brk; // initialize the stack - int[] auxVector = {//LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, 0xffffe400, + auxVector = new int[]{//LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, 0xffffe400, //LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO_EHDR, 0xffffe000, LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x78bfbff, LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 0x1000, @@ -80,4 +85,7 @@ return null; } + public int[] getAuxVector() { + return auxVector; + } } 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-22 17:03:27 UTC (rev 81) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-23 09:23:22 UTC (rev 82) @@ -50,6 +50,11 @@ private static final int STACK_TOP = 0x80000000; /** + * Auxiliary vector + */ + private int[] auxVector; + + /** * Constructor */ public PPC_LinuxProcessSpace(Loader loader) { @@ -77,7 +82,7 @@ * Initialise the stack */ private int initialiseStack(Loader loader, int pc) { - int[] auxVector = { + auxVector = new int[]{ LinuxStackInitializer.AuxiliaryVectorType.AT_IGNOREPPC, LinuxStackInitializer.AuxiliaryVectorType.AT_IGNOREPPC, LinuxStackInitializer.AuxiliaryVectorType.AT_IGNOREPPC, @@ -198,6 +203,10 @@ return this; } + public int[] getAuxVector() { + return auxVector; + } + public int getGDBFrameBaseRegister() { return -1; } 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-22 17:03:27 UTC (rev 81) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-23 09:23:22 UTC (rev 82) @@ -30,6 +30,11 @@ final LinuxSystemCalls syscalls; /** + * Experimental support for the Linux sysinfo page (use to present sysenter and sysexit system call entry) + */ + private static final boolean useSysInfoPage = false; + + /** * Allows uniform access to the arguments of a system call. We cache this object for reuse. */ private final X86_LinuxSyscallArgumentIterator syscallArgs; @@ -45,6 +50,11 @@ private static final int STACK_TOP = 0xC0000000; /** + * Auxiliary vector + */ + private int[] auxVector; + + /** * Constructor */ public X86_LinuxProcessSpace(Loader loader) { @@ -63,40 +73,46 @@ 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"); + if (useSysInfoPage) { + 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 } - 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, - LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x78bfbff, - LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 0x1000, - LinuxStackInitializer.AuxiliaryVectorType.AT_CLKTCK, 0x64, - 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, + auxVector = new int[] { + LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x078bfbff, + LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 0x1000, + LinuxStackInitializer.AuxiliaryVectorType.AT_CLKTCK, 0x64, + 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, - 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_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_PLATFORM, LinuxStackInitializer.AuxiliaryVectorType.STACK_TOP - getPlatformString().length, - LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0}; + LinuxStackInitializer.AuxiliaryVectorType.AT_SECURE, 0, + //LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, LinuxStackInitializer.AuxiliaryVectorType.STACK_TOP - getPlatformString().length, + LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0}; + if (useSysInfoPage) { +// LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, 0xffffe400, +// LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO_EHDR, 0xffffe000, + } + return LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector); } @@ -149,29 +165,8 @@ public void setStackPtr(int ptr) {} - public int[] getAuxVector() { //ELF_Header header, ELF_ProgramHeaderTable programHeaders) { - /* - return new int[] { - 32, 0xffffe400, - 33, 0xffffe000, - ELF_Constants.AT_HWCAP, 0x78bfbff, - ELF_Constants.AT_PAGESZ, 0x1000, - ELF_Constants.AT_CLKTCK, 0x64, - ELF_Constants.AT_PHDR, header.e_phoff - programHeaders.getSegment(0).p_offset + programHeaders.getSegment(0).p_vaddr, - ELF_Constants.AT_PHNUM, header.e_phnum, - ELF_Constants.AT_BASE, 0x0, - ELF_Constants.AT_FLAGS, 0x0, - ELF_Constants.AT_ENTRY, header.e_entry, - ELF_Constants.AT_UID, ELF_Constants.UID, - ELF_Constants.AT_EUID, ELF_Constants.UID, - ELF_Constants.AT_GID, ELF_Constants.GID, - ELF_Constants.AT_EGID, ELF_Constants.GID, - ELF_Constants.AT_SECURE, 0, - ELF_Constants.AT_PLATFORM, ELF_Constants.STACK_TOP - getPlatformString().length, - ELF_Constants.AT_NULL, 0x0, - }; - */ - throw new Error("TODO"); + public int[] getAuxVector() { + return auxVector; } public byte[] getPlatformString() { Modified: src/org/binarytranslator/generic/execution/GdbController.java =================================================================== --- src/org/binarytranslator/generic/execution/GdbController.java 2007-04-22 17:03:27 UTC (rev 81) +++ src/org/binarytranslator/generic/execution/GdbController.java 2007-04-23 09:23:22 UTC (rev 82) @@ -13,6 +13,7 @@ import java.net.*; import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.fault.SegmentationFault; import org.binarytranslator.generic.os.process.ProcessSpace; /** @@ -63,6 +64,11 @@ * Return the address of the current instruction. */ int getCurrentInstructionAddress(); + + /** + * Get the auxiliary vector + */ + int[] getAuxVector(); } @@ -480,6 +486,32 @@ ':', ':' })) { // GDB is telling us it will handle symbol queries for us - nice :-) replyOK(); + } else if (doesBufferMatch(2, new byte[] { 'P','a','r','t',':','a','u','x','v', + ':','r','e','a','d',':',':'})) { + String data = bufferToString(18, dataEnd); + int offset = Integer.parseInt(data.substring(0, data.indexOf(',')), 16); + int length = Integer.parseInt(data.substring(data.indexOf(',') + 1), 16); + int[] auxv = target.getAuxVector(); + byte[] auxv_asbytes = new byte[auxv.length * 4 * 2]; + for(int i=0; i < auxv.length; i++) { + auxv_asbytes[i*8+1] = intToHex (auxv[i] & 0xF); + auxv_asbytes[i*8+0] = intToHex((auxv[i] >> 4) & 0xF); + auxv_asbytes[i*8+3] = intToHex((auxv[i] >> 8) & 0xF); + auxv_asbytes[i*8+2] = intToHex((auxv[i] >> 12) & 0xF); + auxv_asbytes[i*8+5] = intToHex((auxv[i] >> 16) & 0xF); + auxv_asbytes[i*8+4] = intToHex((auxv[i] >> 20) & 0xF); + auxv_asbytes[i*8+7] = intToHex((auxv[i] >> 24) & 0xF); + auxv_asbytes[i*8+6] = intToHex((auxv[i] >> 28) & 0xF); + } + byte[] command = new byte[Math.min(length*2,auxv_asbytes.length-(offset*2))]; + for (int i=0; i < command.length; i++) { + command[i] = auxv_asbytes[offset*2+i]; + } + if (command.length > 0) { + sendCommand(command); + } else { + replyOK(); + } } else { // unrecognized query sendCommand(null); @@ -609,6 +641,10 @@ // report that a SIGILL halted the debugger byte command[] = { 'S', '0', '4' }; sendCommand(command); + } catch (SegmentationFault e) { + // report that a SIGSEGV halted the debugger + byte command[] = { 'S', '0', 'b' }; + sendCommand(command); } break; case 'c': @@ -634,6 +670,10 @@ // report that a SIGILL halted the debugger byte command[] = { 'S', '0', '4' }; sendCommand(command); + } catch (SegmentationFault e) { + // report that a SIGSEGV halted the debugger + byte command[] = { 'S', '0', 'b' }; + sendCommand(command); } break; case 'S': Modified: tests/gcc_simple/x86/helloworld =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-22 17:03:26
|
Revision: 81 http://svn.sourceforge.net/pearcolator/?rev=81&view=rev Author: michael_baer Date: 2007-04-22 10:03:27 -0700 (Sun, 22 Apr 2007) Log Message: ----------- Added support for the ARM Angel semihosting system calls. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java Added Paths: ----------- src/org/binarytranslator/arch/arm/os/abi/semihosting/ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-22 10:26:02 UTC (rev 80) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-22 17:03:27 UTC (rev 81) @@ -219,13 +219,20 @@ String address = "[r" + instr.getRn(); if (instr.preIndexing()) { - address += ", "; - if (!instr.positiveOffset()) - address += '-'; + OperandWrapper offset = instr.getOffset(); + if (offset.getType() != OperandWrapper.Type.Immediate || offset.getImmediate() != 0) { + + address += ", "; + + if (!instr.positiveOffset()) + address += '-'; + + address += operand(instr.getOffset()); + } + + address += ']'; - address += operand(instr.getOffset()) + ']'; - if (instr.writeBack()) address += '!'; } else { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-22 10:26:02 UTC (rev 80) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-22 17:03:27 UTC (rev 81) @@ -4,8 +4,8 @@ /** * In the ARM decoder model, the decoding and usage (translating/interpreting/disassembling) of instructions - * is strictly separated. This class provides a namespace for all decoder classes. A decoder works like a - * mask than can be put upon a binary instruction to look at the different fields within that instruction. + * is separated. This class provides a namespace for all decoder classes. A decoder works like a + * mask that can be put upon a binary instruction to look at the different fields within that instruction. * * Application might derive from these decoders to implement instruction-specific functionality. * Then, implement a version of the generic {@link ARM_InstructionFactory} interface, which returns Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-22 10:26:02 UTC (rev 80) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-22 17:03:27 UTC (rev 81) @@ -292,7 +292,13 @@ case Register: shifterCarryOut = regs.isCarrySet(); - return regs.get(operand2.getRegister()); + int reg = operand2.getRegister(); + + //mind the arm pc offset + if (reg == 15) + return regs.get(reg) + 8; + else + return regs.get(operand2.getRegister()); case RegisterShiftedRegister: case ImmediateShiftedRegister: @@ -1152,7 +1158,22 @@ return Condition.AL; } } + + private class DebugNopInstruction implements ARM_Instruction { + public Condition getCondition() { + return Condition.AL; + } + + public void execute() { + } + + public int getSuccessor(int pc) { + return pc+4; + } + + } + /** This class will create instances of the different interpreter instructions. It is being "controlled" by * the ARM_InstructionDecoder, which uses an abstract factory pattern to decode an instruction. */ private class InterpreterFactory implements @@ -1218,20 +1239,23 @@ public ARM_Instruction createCoprocessorDataProcessing(int instr) { //TODO: Implement coprocessor instructions - throw new RuntimeException( - "Coprocessor instructions are not yet supported."); + /*throw new RuntimeException( + "Coprocessor instructions are not yet supported.");*/ + return new DebugNopInstruction(); } public ARM_Instruction createCoprocessorDataTransfer(int instr) { // TODO: Implement coprocessor instructions - throw new RuntimeException( - "Coprocessor instructions are not yet supported."); + /*throw new RuntimeException( + "Coprocessor instructions are not yet supported.");*/ + return new DebugNopInstruction(); } public ARM_Instruction createCoprocessorRegisterTransfer(int instr) { // TODO: Implement coprocessor instructions - throw new RuntimeException( - "Coprocessor instructions are not yet supported."); + /*throw new RuntimeException( + "Coprocessor instructions are not yet supported.");*/ + return new DebugNopInstruction(); } public ARM_Instruction createIntMultiply(int instr) { 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-22 10:26:02 UTC (rev 80) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-04-22 17:03:27 UTC (rev 81) @@ -21,6 +21,7 @@ systemCallTable[90] = new LinuxSystemCalls.SysMmap(); systemCallTable[122] = new LinuxSystemCalls.SysUname(); systemCallTable[146] = new LinuxSystemCalls.SysWriteV(); + systemCallTable[197] = new LinuxSystemCalls.SysFstat64(); systemCallTable[199] = new LinuxSystemCalls.SysGetEUID(); systemCallTable[200] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[201] = new LinuxSystemCalls.SysGetEUID(); Added: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-04-22 17:03:27 UTC (rev 81) @@ -0,0 +1,519 @@ +package org.binarytranslator.arch.arm.os.abi.semihosting; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.io.RandomAccessFile; +import java.util.HashMap; +import java.util.Map; + +import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; + +/** + * ARM Ltd. also defined a standard system call interface called Angel. + * It is usually used in small embedded environments and abstracts a number of basic system functions, + * among them + * + * <ul> + * <li>Character input / output + * <li>File access + * <li>Timer access + * </ul> + * + * This class implements the Angel system calls on Pearcolator. + * + * @author Michael Baer + */ +public class AngelSystemCalls { + + /** Angel calls requesting user input read it from this stream. */ + private final InputStream consoleInput = System.in; + + /** Angels calls that output characters to the console write it to this stream.*/ + private final PrintStream consoleOutput = System.out; + + /** The Processspace that we're operating on. */ + private final ARM_ProcessSpace ps; + + /** A mapping from file handles to open files. */ + private final Map<Integer, RandomAccessFile> files = new HashMap<Integer, RandomAccessFile>(); + + /** 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; + + /** */ + private AngelSystemCall[] sysCalls; + + public AngelSystemCalls(ARM_ProcessSpace ps) { + this.ps = ps; + sysCalls = new AngelSystemCall[0x31]; + + sysCalls[0x1] = new Sys_Open(); + sysCalls[0x2] = new Sys_Close(); + sysCalls[0x3] = new Sys_WriteC(); + sysCalls[0x4] = new Sys_Write0(); + sysCalls[0x5] = new Sys_Write(); + sysCalls[0x6] = new Sys_Read(); + sysCalls[0x7] = new Sys_ReadC(); + sysCalls[0x8] = new Sys_IsError(); + sysCalls[0x9] = new Sys_IsTty(); + sysCalls[0xA] = new Sys_Seek(); + sysCalls[0xB] = null; //Angel docs don't say what this call is supposed to be... + sysCalls[0xC] = new Sys_Flen(); + sysCalls[0xD] = new Sys_TmpNam(); + sysCalls[0xE] = new Sys_Remove(); + sysCalls[0xF] = new Sys_Rename(); + sysCalls[0x10] = new Sys_Clock(); + sysCalls[0x11] = new Sys_Time(); + sysCalls[0x12] = new Sys_System(); + sysCalls[0x13] = new Sys_Errno(); + sysCalls[0x14] = null; //Another undefined call + sysCalls[0x15] = new Sys_Get_CmdLine(); + sysCalls[0x16] = new Sys_HeapInfo(); + sysCalls[0x30] = new Sys_Elapsed(); + sysCalls[0x31] = new Sys_TickFreq(); + } + + public void doSysCall(int callNum) { + try { + sysCalls[callNum].execute(); + } + catch (NullPointerException e) { + throw new RuntimeException("Not implemented angel call number: " + callNum); + } + catch (ArrayIndexOutOfBoundsException e) { + throw new RuntimeException("Invalid angel call number: " + callNum); + } + } + + /** Add a file to the open file table and return its handle. */ + private int addFile(RandomAccessFile 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) { + return files.get(handle); + } + + private boolean closeFile(int handle) { + try { + RandomAccessFile file = files.get(handle); + file.close(); + return true; + } + catch (Exception e) { + return false; + } + finally { + files.remove(handle); + } + } + + abstract class AngelSystemCall { + public abstract void execute(); + + protected final void setReturn(int value) { + ps.registers.set(0, value); + } + + protected String readString(int ptrBuffer, int length) { + String s = ""; + + for (int i = 0; i < length; i++) { + s += (char)ps.memory.loadUnsigned8(ptrBuffer++); + } + + return s; + } + + protected void writeString(String text, int ptrBuffer) { + for (int i = 0; i < text.length(); i++) { + ps.memory.store8(ptrBuffer++, text.charAt(i)); + } + + ps.memory.store8(ptrBuffer, 0); + } + } + + class Sys_Open extends AngelSystemCall { + + @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); + + String fileName = readString(ptrBuffer, length); + + try { + String openMode = (fileMode >= 4) ? "rw" : "w"; + RandomAccessFile file = new RandomAccessFile(fileName, openMode); + + //return the file's index within this table as a file handle + setReturn(addFile(file)); + + } catch (FileNotFoundException e) { + + //return with an error + setReturn(-1); + } + } + } + + class Sys_Close extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + + setReturn(closeFile(fileHandle) ? 0 : -1); + } + } + + class Sys_WriteC extends AngelSystemCall { + + @Override + public void execute() { + int ptrCharToOutput = ps.registers.get(1); + char output = (char)ps.memory.loadUnsigned8(ptrCharToOutput); + consoleOutput.print(output); + } + } + + class Sys_Write0 extends AngelSystemCall { + + @Override + public void execute() { + int ptrOutput = ps.registers.get(1); + + char output = (char)ps.memory.loadUnsigned8(ptrOutput++); + + while (output != 0) { + consoleOutput.print(output); + output = (char)ps.memory.loadUnsigned8(ptrOutput++); + } + } + } + + class Sys_Write extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + int ptrBuffer = ps.memory.load32(ptrParamBlock + 4); + int length = ps.memory.load32(ptrParamBlock + 8); + + try { + RandomAccessFile file = getFile(fileHandle); + + while (length != 0) { + file.writeByte(ps.memory.loadUnsigned8(ptrBuffer++)); + length--; + } + } + catch (Exception e) {} + + //return the number of chars that have not been written + setReturn(length); + } + } + + class Sys_Read extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + int ptrBuffer = ps.memory.load32(ptrParamBlock + 4); + int length = ps.memory.load32(ptrParamBlock + 8); + + RandomAccessFile file = getFile(fileHandle); + + //fail with EOF if the handle is invalid. Angel does not provide any facilities to + //notify about an invalid handle + if (file == null) { + setReturn(length); + return; + } + + int leftToRead = length; + while (leftToRead-- != 0) { + try { + ps.memory.store8(ptrBuffer++, file.readByte()); + } + catch (Exception e) { + //did we read any values at all? + if (leftToRead == length) { + setReturn(length); //no, then fail with eof + return; + } + } + } + + setReturn(length + leftToRead); //otherwise return that we partially filled the buffer + } + } + + class Sys_ReadC extends AngelSystemCall { + + @Override + public void execute() { + try { + int value = consoleInput.read(); + + if (value == -1) + throw new RuntimeException("Unable to read further characters from console"); + + setReturn(value); + } + catch (IOException e) { + throw new RuntimeException("Error while reading character from console.", e); + } + } + } + + class Sys_IsError extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int statusWord = ps.memory.load32(ptrParamBlock); + + setReturn(statusWord < 0 ? -1 : 0); + } + } + + class Sys_IsTty extends AngelSystemCall { + + @Override + public void execute() { + + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + + RandomAccessFile file = getFile(fileHandle); + + if (file != null) { + //TODO: Check if the file is an interactive device and return 1 in that case. + setReturn(0); + } + else { + setReturn(-1); + } + } + } + + class Sys_Seek extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + int absolutePosition = ps.memory.load32(ptrParamBlock + 4); + + RandomAccessFile file = getFile(fileHandle); + try { + file.seek(absolutePosition); + setReturn(0); + } catch (Exception e) { + setReturn(-1); + } + } + } + + class Sys_Flen extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + + RandomAccessFile file = getFile(fileHandle); + + try { + setReturn((int)file.length()); + } + catch (Exception e) { + setReturn(-1); + } + } + } + + class Sys_TmpNam extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int ptrBuffer = ps.memory.load32(ptrParamBlock); + int identifier = ps.memory.load32(ptrParamBlock + 4); + int bufferLength = ps.memory.load32(ptrParamBlock + 8); + + String tmpFile = TEMP_FILE_DIR + "angel_" + identifier + ".tmp"; + + //do we have enough buffer space to write the tmp file? + if (bufferLength < tmpFile.length() + 1) { + setReturn(-1); + return; + } + + //write the name tmpFile to the buffer + writeString(tmpFile, ptrBuffer); + setReturn(0); + } + } + + class Sys_Remove extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int ptrBuffer = ps.memory.load32(ptrParamBlock); + int length = ps.memory.load32(ptrParamBlock + 4); + + String fileName = readString(ptrBuffer, length); + File f = new File(fileName); + + setReturn(f.delete() ? 0 : -1); + } + } + + class Sys_Rename extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int ptrOldFile = ps.memory.load32(ptrParamBlock); + int oldLength = ps.memory.load32(ptrParamBlock + 4); + + int ptrNewFile = ps.memory.load32(ptrParamBlock + 8); + int newLength = ps.memory.load32(ptrParamBlock + 12); + + String oldFile = readString(ptrOldFile, oldLength); + String newFile = readString(ptrNewFile, newLength); + + File f = new File(oldFile); + boolean success = f.renameTo(new File(newFile)); + + setReturn(success ? 0 : -1); + } + } + + class Sys_Clock extends AngelSystemCall { + + private final long startClock = System.currentTimeMillis(); + + @Override + public void execute() { + setReturn((int)(System.currentTimeMillis() - startClock) / 10); + } + } + + class Sys_Time extends AngelSystemCall { + + @Override + public void execute() { + setReturn((int)(System.currentTimeMillis() * 1000)); + } + } + + class Sys_System extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int ptrCommand = ps.memory.load32(ptrParamBlock); + int length = ps.memory.load32(ptrParamBlock + 4); + + String command = readString(ptrCommand, length); + + throw new RuntimeException("ARM Angel is supposed to execute command on host: " + command); + } + } + + class Sys_Errno extends AngelSystemCall { + + @Override + public void execute() { + setReturn(0); + } + } + + class Sys_Get_CmdLine extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int ptrBuffer = ps.memory.load32(ptrParamBlock); + int length = ps.memory.load32(ptrParamBlock + 4); + + String cmdLine = DBT_Options.executableFile; + + if (cmdLine.contains(" ")) + cmdLine = '"' + cmdLine + '"'; + + for(String s : DBT_Options.executableArguments) { + if (s.contains(" ")) { + s = '"' + s + '"'; + } + + cmdLine += " " + s; + } + + if (length < cmdLine.length() + 1) { + setReturn(-1); + return; + } + + writeString(cmdLine, ptrBuffer); + ps.memory.store32(ptrParamBlock + 4, cmdLine.length() + 1); + setReturn(0); + } + } + + class Sys_HeapInfo extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + + //return that we couldn't calculate any of the requested heap size values + ps.memory.store32(ptrParamBlock, 0); + ps.memory.store32(ptrParamBlock + 4, 0); + ps.memory.store32(ptrParamBlock + 8, 0); + ps.memory.store32(ptrParamBlock + 12, 0); + } + } + + class Sys_Elapsed extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + long elapsedTime = System.nanoTime(); + + ps.memory.store32(ptrParamBlock, (int)elapsedTime); + ps.memory.store32(ptrParamBlock + 4, (int)(elapsedTime >> 32)); + setReturn(0); + } + } + + class Sys_TickFreq extends AngelSystemCall { + + @Override + public void execute() { + setReturn(1000000000); //Return that ticks are measured in nanoseconds + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-22 10:26:02
|
Revision: 80 http://svn.sourceforge.net/pearcolator/?rev=80&view=rev Author: captain5050 Date: 2007-04-22 03:26:02 -0700 (Sun, 22 Apr 2007) Log Message: ----------- A couple of improvements to the GDB stub to enable it to walk past protocol errors on x86 Modified Paths: -------------- src/org/binarytranslator/generic/execution/GdbController.java Modified: src/org/binarytranslator/generic/execution/GdbController.java =================================================================== --- src/org/binarytranslator/generic/execution/GdbController.java 2007-04-21 19:44:59 UTC (rev 79) +++ src/org/binarytranslator/generic/execution/GdbController.java 2007-04-22 10:26:02 UTC (rev 80) @@ -74,7 +74,7 @@ /** * The stream to read from the socket */ - private final InputStream in; + private final PushbackInputStream in; /** * The stream to read from the socket @@ -92,6 +92,11 @@ private final GdbTarget target; /** + * If we get an unexpected packet should we fail or try to ignore it? + */ + private final boolean ignoreProtocolErrors = true; + + /** * Thread to continue or step, a value of -1 means all threads, 0 means any * thread. */ @@ -167,7 +172,7 @@ try { ServerSocket connectionSocket = new ServerSocket(port); socket = connectionSocket.accept(); - in = socket.getInputStream(); + in = new PushbackInputStream(socket.getInputStream()); out = socket.getOutputStream(); buffer = new byte[256]; getACK(); @@ -235,7 +240,12 @@ private void getACK() throws IOException { int command = in.read(); if (command != ACK) { - throw new IOException("Acknowledge expected but got " + (char) command); + if (ignoreProtocolErrors) { + in.unread(command); + report("Acknowledge expected but got \"" + (char) command + "\""); + } else { + throw new IOException("Acknowledge expected but got \"" + (char) command + "\""); + } } } @@ -254,11 +264,21 @@ private int readPacket() throws IOException { // Read the packet start int index = 0; - buffer[index] = (byte) in.read(); - if (buffer[index] != START) { - throw new IOException("Expected the start of a packet ($) but got " - + (char) buffer[index]); - } + boolean foundStart = false; + do { + buffer[index] = (byte) in.read(); + if (buffer[index] == START) { + foundStart = true; + } else { + if (!ignoreProtocolErrors) { + throw new IOException("Expected the start of a packet \"$\" but got \"" + + (char) buffer[index] + "\""); + } else { + report("Expected the start of a packet \"$\" but got \"" + + (char) buffer[index] + "\""); + } + } + } while(!foundStart); // Read the data int csum = 0; do { 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: <mic...@us...> - 2007-04-20 22:55:51
|
Revision: 78 http://svn.sourceforge.net/pearcolator/?rev=78&view=rev Author: michael_baer Date: 2007-04-20 15:55:52 -0700 (Fri, 20 Apr 2007) Log Message: ----------- Fixed various bugs in ARM disassembler and 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_InstructionVisitor.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-20 22:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-20 22:55:52 UTC (rev 78) @@ -1,7 +1,7 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction; -import org.binarytranslator.arch.arm.decoder.ARM_Instructions.BlockDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.MultipleDataTransfer; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Branch; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.BranchExchange; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CoprocessorDataProcessing; @@ -188,11 +188,18 @@ String mnemonic = instr.getOpcode().name(); mnemonic += cond(instr); + String parameters; + + if (instr.getOpcode() == DataProcessing.Opcode.CMN || + instr.getOpcode() == DataProcessing.Opcode.CMP) { + //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; + } + if (instr.updateConditionCodes()) mnemonic += 'S'; - String parameters; - // Filter instructions that only take one parameter if (instr.getOpcode() == DataProcessing.Opcode.MOV || instr.getOpcode() == DataProcessing.Opcode.MVN @@ -212,12 +219,22 @@ String address = "[r" + instr.getRn(); if (instr.preIndexing()) { - address += ", " + operand(instr.getOffset()) + "]"; + address += ", "; + + if (!instr.positiveOffset()) + address += '-'; + + address += operand(instr.getOffset()) + ']'; if (instr.writeBack()) address += '!'; } else { - address += "], " + operand(instr.getOffset()); + address += "], "; + + if (!instr.positiveOffset()) + address += '-'; + + address += operand(instr.getOffset()); } mnemonic += cond(instr); @@ -287,7 +304,7 @@ instr.getRd(), instr.getRm(), instr.getRn())); } - public void visit(BlockDataTransfer instr) { + public void visit(MultipleDataTransfer instr) { String mnemonic = instr.isLoad() ? "LDM" : "STM"; String baseRegister = "r" + instr.getBaseRegister(); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-20 22:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-20 22:55:52 UTC (rev 78) @@ -61,8 +61,8 @@ byte bits_7_4 = (byte)Utils.getBits(instr, 4, 7); - if (bits_7_4 == 0 && ((instr & 0x01900000) == 0x01100000)) { - //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 20) == true + if (bits_7_4 == 0 && ((instr & 0x01900000) == 0x01000000)) { + //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 20) == false if (Utils.getBit(instr, 21)) return factory.createMoveToStatusRegister(instr); else @@ -276,7 +276,7 @@ static class DefaultFactory implements ARM_InstructionFactory<ARM_Instructions.Instruction> { public Instruction createBlockDataTransfer(int instr) { - return new BlockDataTransfer(instr); + return new MultipleDataTransfer(instr); } public Instruction createBranch(int instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-20 22:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-20 22:55:52 UTC (rev 78) @@ -10,7 +10,7 @@ void visit(IntMultiply instr); void visit(LongMultiply instr); void visit(Swap instr); - void visit(BlockDataTransfer instr); + void visit(MultipleDataTransfer instr); void visit(SoftwareInterrupt instr); void visit(Branch instr); void visit(BranchExchange instr); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-20 22:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-20 22:55:52 UTC (rev 78) @@ -193,7 +193,7 @@ public static OperandWrapper decodeDataProcessingOperand(int instr) { if (Utils.getBit(instr, 25)) { //this is a right-rotated immediate value - byte shiftAmount = (byte)(Utils.getBits(instr, 8, 11) << 2); + byte shiftAmount = (byte)(Utils.getBits(instr, 8, 11) * 2); int value = instr & 0xFF; if (shiftAmount == 0) @@ -707,7 +707,7 @@ } /** Represents a LDM/STM instruction. */ - public static class BlockDataTransfer extends Instruction { + public static class MultipleDataTransfer extends Instruction { /** @see #postIndexing() */ protected final boolean postIndexing; @@ -730,10 +730,10 @@ /** Contains a set bit at position N if rN should be transferred using this instruction.*/ protected final int registerList; - public BlockDataTransfer(int instr) { + public MultipleDataTransfer(int instr) { super(instr); - postIndexing = Utils.getBit(instr, 24); + postIndexing = !Utils.getBit(instr, 24); incrementBase = Utils.getBit(instr, 23); forceUser = Utils.getBit(instr, 22); writeBack = Utils.getBit(instr, 21); @@ -820,7 +820,7 @@ public Branch(int instr) { super(instr); link = Utils.getBit(instr, 24); - offset = Utils.signExtend((instr & 0xFFF) << 2, 14); + offset = Utils.signExtend((instr & 0xFFFFFF) << 2, 26); } /** Should the current PC be put into the lr? */ Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-20 22:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-20 22:55:52 UTC (rev 78) @@ -68,8 +68,16 @@ } public void execute() { - if (isConditionTrue()) + if (isConditionTrue()) { conditionalInstruction.execute(); + + int nextInstruction = conditionalInstruction.getSuccessor(ps.getCurrentInstructionAddress()); + + if (nextInstruction != -1) + ps.setCurrentInstructionAddress(nextInstruction); + } + else + ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress()+4); } public int getSuccessor(int pc) { @@ -135,6 +143,11 @@ throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); } } + + @Override + public String toString() { + return conditionalInstruction.toString(); + } } /** A base class for all data processing interpreter instructions, including CLZ.*/ @@ -658,11 +671,11 @@ } /** Transfer multiple registers at once between the register bank and the memory. */ - private class BlockDataTransfer extends ARM_Instructions.BlockDataTransfer + private class BlockDataTransfer extends ARM_Instructions.MultipleDataTransfer implements ARM_Instruction { /** the lowest address that we're reading a register from / writing a register to */ - private final int startAddress; + private final int registerCount; /** An array that contains the registers to be transferd in ascending order. * The list is delimited by setting the entry after the last register index to -1. @@ -676,38 +689,40 @@ super(instr); transferPC = transferRegister(15); - int registerCount = 0; + int regCount = 0; for (int i = 0; i < 14; i++) if (transferRegister(i)) { - registersToTransfer[registerCount++] = i; + registersToTransfer[regCount++] = i; } - registersToTransfer[registerCount] = -1; + registersToTransfer[regCount] = -1; + + registerCount = regCount; + } + public void execute() { //build the address, which generally ignores the last two bits + int startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + if (!incrementBase) { if (postIndexing) { //post-indexing, backward reading - startAddress = regs.get(baseRegister) & 0xFFFFFFFC - - (registerCount + (transferPC ? -1 : 0)) * 4; + startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; } else { //pre-indexing, backward-reading - startAddress = regs.get(baseRegister) & 0xFFFFFFFC - - (registerCount + (transferPC ? 1 : 0)) * 4; + startAddress -= (registerCount + (transferPC ? 2 : 1)) * 4; } } else { if (postIndexing) { //post-indexing, forward reading - startAddress = regs.get(baseRegister) & 0xFFFFFFFC - 4; + startAddress -= 4; } else { //pre-indexing, forward reading - startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + //no need to adjust the start address + } } - } - - public void execute() { int nextAddress = startAddress; //are we supposed to load or store multiple registers? @@ -747,9 +762,22 @@ if (writeBack) { //write the last address we read from back to a register - //TODO: Check if we have to consider the different cases? - if (!incrementBase) - nextAddress = startAddress; + if (!incrementBase) { + //backward reading + if (postIndexing) { + //backward reading, post-indexing + nextAddress = startAddress; + } + else { + //backward reading, pre-indexing + nextAddress = startAddress + 4; + } + } + else { + //forward reading + if (postIndexing) + nextAddress += 4; + } regs.set(baseRegister, nextAddress); } @@ -954,32 +982,27 @@ //if we are not pre-indexing, then just use the base register for the memory access if (!preIndexing) return base; + + int addrOffset; switch (offset.getType()) { case Immediate: - if (positiveOffset) - return base + offset.getImmediate(); - else - return base - offset.getImmediate(); + addrOffset = offset.getImmediate(); + break; case Register: - int offsetRegister = regs.get(offset.getRegister()); + addrOffset = regs.get(offset.getRegister()); if (offset.getRegister() == ARM_Registers.PC) { - offsetRegister += 8; + addrOffset += 8; } + break; - if (positiveOffset) - return base + offsetRegister; - else - return base - offsetRegister; - case ImmediateShiftedRegister: + addrOffset = regs.get(offset.getRegister()); + if (offset.getRegister() == 15) - throw new RuntimeException( - "PC-relative memory accesses are not yet supported."); + addrOffset += 8; - int addrOffset = regs.get(offset.getRegister()); - switch (offset.getShiftType()) { case ASR: addrOffset = addrOffset >>> offset.getShiftAmount(); @@ -1008,6 +1031,7 @@ throw new RuntimeException("Unexpected shift type: " + offset.getShiftType()); } + break; case PcRelative: case RegisterShiftedRegister: @@ -1015,7 +1039,11 @@ throw new RuntimeException("Unexpected operand type: " + offset.getType()); } - + + if (positiveOffset) + return base + addrOffset; + else + return base - addrOffset; } public void execute() { 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:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-20 22:55:52 UTC (rev 78) @@ -9,6 +9,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; public class ARM_LinuxProcessSpace extends ARM_ProcessSpace implements @@ -51,13 +52,13 @@ 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, + 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, @@ -68,9 +69,10 @@ LinuxStackInitializer.AuxiliaryVectorType.AT_EGID, DBT_Options.GID, LinuxStackInitializer.AuxiliaryVectorType.AT_SECURE, 0, - LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0 }; + //LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, LinuxStackInitializer.AuxiliaryVectorType.STACK_TOP - getPlatformString().length, + LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0}; - LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector); + registers.set(ARM_Registers.SP, LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector)); } public int getBrk() { 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-20 18:51:50
|
Revision: 76 http://svn.sourceforge.net/pearcolator/?rev=76&view=rev Author: michael_baer Date: 2007-04-20 11:51:50 -0700 (Fri, 20 Apr 2007) Log Message: ----------- Reintroduced symbolic constants for OS ABIs. Modified Paths: -------------- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-20 18:42:26 UTC (rev 75) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-20 18:51:50 UTC (rev 76) @@ -262,11 +262,11 @@ /** * Class to read and hold ELF header indentity information */ - + @SuppressWarnings("unused") private static class ELF_Identity { /** Represents acceptable ELF address sizes. */ - enum AddressSize implements IdentifiedEnum { + private enum AddressSize implements IdentifiedEnum { Size32(1), Size64(2); @@ -282,7 +282,7 @@ } /** Represents accepted ELF byte orders. */ - enum ByteOrder implements IdentifiedEnum { + private enum ByteOrder implements IdentifiedEnum { LittleEndian(1), BigEndian(2); @@ -296,6 +296,22 @@ return identifier; } } + + /* Symbolic names for the most widely used ABIs. This is not an enum, because the list isn't complete. */ + private static final byte ELFOSABI_SYSTEMV = 0; + private static final byte ELFOSABI_HPUX = 1; + private static final byte ELFOSABI_NETBSD = 2; + private static final byte ELFOSABI_LINUX = 3; + private static final byte ELFOSABI_SOLARIS = 6; + private static final byte ELFOSABI_AIX = 7; + private static final byte ELFOSABI_IRIX = 8; + private static final byte ELFOSABI_FREEBSD = 9; + private static final byte ELFOSABI_TRU64 = 10; + private static final byte ELFOSABI_MODESTO = 11; + private static final byte ELFOSABI_OPENBSD = 12; + private static final byte ELFOSABI_OPENVMS = 13; + private static final byte ELFOSABI_NSK = 14; + private static final byte ELFOSABI_ARM = 97; /** * ELF magic values indicating an ELF file @@ -356,13 +372,13 @@ { //read the OS ABI switch (abi) { - case 0: + case ELFOSABI_SYSTEMV: return ABI.SystemV; - case 3: + case ELFOSABI_LINUX: return ABI.Linux; - case 97: + case ELFOSABI_ARM: return ABI.ARM; default: 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. |