From: <mic...@us...> - 2007-03-30 15:38:56
|
Revision: 15 http://svn.sourceforge.net/pearcolator/?rev=15&view=rev Author: michael_baer Date: 2007-03-30 08:38:52 -0700 (Fri, 30 Mar 2007) Log Message: ----------- Introduced various refactorings Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/gdbstub/GDBStub.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/loader/Loader.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java src/org/binarytranslator/generic/gdbstub/GDBTarget.java src/org/binarytranslator/generic/os/loader/image/ src/org/binarytranslator/generic/os/loader/image/ImageLoader.java Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -4,6 +4,7 @@ import org.jikesrvm.opt.ir.OPT_HIRGenerator; import org.jikesrvm.opt.ir.OPT_GenerationContext; import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.os.process.image.ARM_SimpleProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; import org.binarytranslator.arch.x86.os.process.X86_Registers; @@ -24,43 +25,6 @@ */ public ARM_Registers registers; - /* GDB Interface */ - /** - * Read a register and turn into a byte array conforming to the endianness of - * the architecture - */ - public byte[] readRegisterGDB(int regNum) { - throw new RuntimeException("Not yet implemented"); - } - - /** - * Has frame base register? - */ - public boolean hasFrameBaseRegister() { - throw new RuntimeException("Not yet implemented"); - } - - /** - * Get the value of the frame base register - */ - public int getGDBFrameBaseRegister() { - throw new RuntimeException("Not yet implemented"); - } - - /** - * Get the value of the frame base register - */ - public int getGDBStackPointerRegister() { - throw new RuntimeException("Not yet implemented"); - } - - /** - * Get the value of the frame base register - */ - public int getGDBProgramCountRegister() { - throw new RuntimeException("Not yet implemented"); - } - /* * Utility functions */ @@ -99,6 +63,7 @@ * @return a HIR generator */ public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { + System.out.println("Executing instr: " + memory.load32(0)); throw new RuntimeException("Not yet implemented"); } @@ -111,12 +76,12 @@ */ public static ProcessSpace createProcessSpaceFromBinary(Loader loader) throws IOException { - if (loader.isARM_ABI()) { + if (loader.isARM_ABI() || loader.isSysV_ABI()) { report("ARM ABI"); return new ARM_LinuxProcessSpace(); } else { - throw new UnsupportedOperationException("Binary of " + loader.getABIString() - + " ABI is unsupported for the ARM architecture"); + report("Creating simple ARM process space."); + return new ARM_SimpleProcessSpace(); } } @@ -132,21 +97,21 @@ * Return as an integer the current instruction's address */ public int getCurrentInstructionAddress() { - return registers.getPC(); + return registers.read(ARM_Registers.PC); } /** * Sets the current instruction's address */ public void setCurrentInstructionAddress(int pc) { - registers.setPC(pc); + registers.write(ARM_Registers.PC, pc); } /** * Return as an integer the current instruction's address */ public int getCurrentStackAddress() { - throw new RuntimeException("Not yet implemented"); + return registers.read(14); } /** Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-03-30 15:38:52 UTC (rev 15) @@ -1,7 +1,12 @@ package org.binarytranslator.arch.arm.os.process; +import org.jikesrvm.VM; + public final class ARM_Registers { + public final static int SP = 14; + public final static int PC = 15; + /** * The currently visible ARM general purpose registers. Register 15 also serves as the PC. */ @@ -58,7 +63,7 @@ /** * Definition of symbolic constants for all valid operating modes */ - public final static byte OPERATING_MODE_USER = 0x10; + public final static byte OPERATING_MODE_USR = 0x10; public final static byte OPERATING_MODE_FIQ = 0x11; public final static byte OPERATING_MODE_IRQ = 0x12; public final static byte OPERATING_MODE_SVC = 0x13; @@ -68,18 +73,16 @@ public ARM_Registers() { } - /** - * Sets the pc to a new value - */ - public void setPC(int pc) { - regs[15] = pc; + public int read(int reg) { + if (VM.VerifyAssertions) VM._assert(reg < 16); + + return regs[reg]; } - /** - * Sets the pc to a new value - */ - public int getPC() { - return regs[15]; + public void write(int reg, int value) { + if (VM.VerifyAssertions) VM._assert(reg < 16); + + regs[reg] = value; } /** Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -3,6 +3,8 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.os.abi.linux.ARM_LinuxSystemCalls; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.generic.os.abi.linux.LinuxStackInitializer; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; @@ -16,6 +18,11 @@ private final LinuxSystemCalls sysCalls; /** + * A re-used iterator that allows enumerating the argument of the current system call + */ + private final ARM_SyscallArgumentIterator syscallArgs; + + /** * The top of the stack */ private static final int STACK_TOP = 0xC0000000; @@ -27,6 +34,7 @@ public ARM_LinuxProcessSpace() { sysCalls = new ARM_LinuxSystemCalls(this); + syscallArgs = new ARM_SyscallArgumentIterator(this); } @Override @@ -36,7 +44,7 @@ @Override public void initialise(Loader loader, int pc, int brk, String[] args) { - registers.setPC(pc); + registers.write(ARM_Registers.PC, pc); this.brk = brk; //initialize the stack @@ -66,15 +74,15 @@ return brk; } - public int[] getSysCallArguments(int n) { - // TODO Auto-generated method stub - return null; - } - public int getSysCallNumber() { // TODO Auto-generated method stub return 0; } + + public CallArgumentIterator getSysCallArguments() { + syscallArgs.reset(); + return syscallArgs; + } public void setBrk(int address) { brk = address; @@ -88,4 +96,10 @@ // TODO Auto-generated method stub } + @Override + public GDBTarget getGDBTarget() { + // TODO Auto-generated method stub + return null; + } + } Added: src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java 2007-03-30 15:38:52 UTC (rev 15) @@ -0,0 +1,35 @@ +package org.binarytranslator.arch.arm.os.process.linux; + +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; + +public class ARM_SyscallArgumentIterator implements LinuxSystemCallGenerator.CallArgumentIterator { + + private final ARM_LinuxProcessSpace ps; + private int currentArgument; + + public ARM_SyscallArgumentIterator(ARM_LinuxProcessSpace ps) { + this.ps = ps; + this.currentArgument = 0; + } + + public int nextInt() { + return ps.registers.read(currentArgument++); + } + + public long nextLong() { + // only start reading longs from even registers + if ((currentArgument & 1) == 1) + currentArgument++; + + //TODO: This code is actually assuming that we're on little endian + long lowWord = nextInt(); + long highWord = nextInt(); + + return highWord << 32 | lowWord; + } + + public void reset() { + currentArgument = 0; + } + +} Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -19,6 +19,7 @@ import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.vmInterface.*; import java.util.*; import java.io.*; @@ -26,7 +27,7 @@ /** * Capture the running of a PowerPC process */ -public abstract class PPC_ProcessSpace extends ProcessSpace +public abstract class PPC_ProcessSpace extends ProcessSpace implements GDBTarget { /* Here's what would be in the PowerPC's registers if the binary were running on a real PowerPC. For speed I am using individual Modified: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -11,6 +11,7 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; import org.binarytranslator.arch.ppc.os.abi.linux.PPC_LinuxSystemCalls; +import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.generic.os.abi.linux.LinuxStackInitializer; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; @@ -29,6 +30,11 @@ * System calls object for handling system calls generated by this process */ final LinuxSystemCalls syscalls; + + /** + * Provides access to the single arguments of a system call. + */ + final PPC_LinuxSyscallArgumentIterator syscallArgs; /** * The top of the bss segment @@ -45,6 +51,7 @@ */ public PPC_LinuxProcessSpace(Loader loader) { syscalls = new PPC_LinuxSystemCalls(this); + syscallArgs = new PPC_LinuxSyscallArgumentIterator(this); } /** @@ -114,15 +121,12 @@ } /** * Create an array of arguments for the system call - * @param n number of system call arguments to read * @return array of system call argument values */ - public int[] getSysCallArguments(int n) { - int args[] = new int[n]; - for (int i=0; i < n; i++) { - args[i] = getRegister(3+i); - } - return args; + public CallArgumentIterator getSysCallArguments() { + + syscallArgs.reset(); + return syscallArgs; } /** @@ -158,4 +162,16 @@ brk = address; } + public GDBTarget getGDBTarget() { + return this; + } + + public int getGDBFrameBaseRegister() { + return -1; + } + + public boolean hasFrameBaseRegister() { + return false; + } + } Added: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java (rev 0) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxSyscallArgumentIterator.java 2007-03-30 15:38:52 UTC (rev 15) @@ -0,0 +1,54 @@ +package org.binarytranslator.arch.ppc.os.process.linux; + +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; + +final class PPC_LinuxSyscallArgumentIterator implements LinuxSystemCallGenerator.CallArgumentIterator { + + /** + * That process space that this class is enumerating the arguments from. + */ + private final PPC_LinuxProcessSpace ps; + + /** + * The index of the argument that is fetched by the next call to next<datatype>() + */ + private int nextArgument; + + public PPC_LinuxSyscallArgumentIterator(PPC_LinuxProcessSpace ps) { + this.ps = ps; + this.nextArgument = 0; + } + + /** + * Return the next integer argument by reading it from a register, starting with GPR3. + */ + public int nextInt() { + return ps.getRegister(3 + nextArgument++); + } + + /** + * Returns the next long argument. + * This implementation follows the information on p. 3-19f of http://refspecs.freestandards.org/elf/elfspec_ppc.pdf + */ + public long nextLong() { + + //Start reading long arguments only from uneven registers + if ((nextArgument & 1) == 0) { + nextArgument++; + } + + long lowWord = nextInt(); + long highWord = nextInt(); + + return highWord << 32 | lowWord; + } + + /** + * We're actually reusing that class instead of initializing a new one each time syscall arguments are inspected. + * Therefore, this function starts iterating over all arguments anew. + */ + public void reset() { + nextArgument = 0; + } + +} Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -17,6 +17,7 @@ import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.memory.ByteAddressedMemory; import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; import org.binarytranslator.generic.os.loader.Loader; @@ -24,7 +25,7 @@ /** * Encapsulate the parts of an X86 process that are common across operating systems */ -public abstract class X86_ProcessSpace extends ProcessSpace { +public abstract class X86_ProcessSpace extends ProcessSpace implements GDBTarget { /* * Process defaults @@ -104,6 +105,10 @@ public int getGDBProgramCountRegister() { return 8; } + + public GDBTarget getGDBTarget() { + return this; + } /* * Utility functions @@ -161,7 +166,7 @@ * Run a single instruction */ public void runOneInstruction() throws BadInstructionException { - // TODO + throw new UnsupportedOperationException("To be implemented"); } /** Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -12,6 +12,7 @@ import org.binarytranslator.generic.os.abi.linux.LinuxStackInitializer; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator.CallArgumentIterator; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; import org.binarytranslator.arch.x86.os.abi.linux.X86_LinuxSystemCalls; @@ -25,6 +26,11 @@ * System calls object for handling system calls generated by this process */ LinuxSystemCalls syscalls; + + /** + * Allows uniform access to the arguments of a system call. We cache this object for reuse. + */ + private final X86_LinuxSyscallArgumentIterator syscallArgs; /** * The top of the bss segment @@ -41,6 +47,7 @@ */ public X86_LinuxProcessSpace(Loader loader) { syscalls = new X86_LinuxSystemCalls(this); + syscallArgs = new X86_LinuxSyscallArgumentIterator(this); } /** @@ -97,22 +104,12 @@ return registers.readGP32(X86_Registers.EAX); } - public int[] getSysCallArguments(int n) { - int[] args = new int[n]; - if (n <= 6) { - int[] order = {X86_Registers.EBX, X86_Registers.ECX, X86_Registers.EDX, X86_Registers.ESI, X86_Registers.EDI, X86_Registers.EBP}; - - for (int i = 0; i < n; i++) { - args[i] = registers.readGP32(order[i]); - } - } else { - throw new Error("We should check this"); -// for (int i = 0; i < n; i++) { -// args[i] = memory.load32(registers.readGP32(X86_Registers.EBX) + (i * 4)); -// } - } - - return args; + /** + * Returns an interface to read the arguments of a system call. + */ + public CallArgumentIterator getSysCallArguments() { + syscallArgs.reset(); + return syscallArgs; } public void setSysCallReturn(int r) { Added: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java (rev 0) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxSyscallArgumentIterator.java 2007-03-30 15:38:52 UTC (rev 15) @@ -0,0 +1,37 @@ +package org.binarytranslator.arch.x86.os.process.linux; + +import org.binarytranslator.arch.x86.os.process.X86_Registers; +import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; +import org.jikesrvm.VM; + +public class X86_LinuxSyscallArgumentIterator implements LinuxSystemCallGenerator.CallArgumentIterator { + + private final static int[] order = {X86_Registers.EBX, X86_Registers.ECX, X86_Registers.EDX, X86_Registers.ESI, X86_Registers.EDI, X86_Registers.EBP}; + + private final X86_LinuxProcessSpace ps; + private int nextParameter; + + public X86_LinuxSyscallArgumentIterator(X86_LinuxProcessSpace ps) { + this.ps = ps; + this.nextParameter = 0; + } + + public int nextInt() { + if (VM.VerifyAssertions) VM._assert(nextParameter <= 6); + + return ps.registers.readGP32(order[nextParameter++]); + } + + public long nextLong() { + throw new UnsupportedOperationException("X86 System Calls do not support long arguments, yet."); + } + + /** + * We're actually reusing that class instead of initializing a new one each time syscall arguments are inspected. + * Therefore, this function starts iterating over all arguments anew. + */ + public void reset() { + nextParameter = 0; + } + +} Modified: src/org/binarytranslator/generic/gdbstub/GDBStub.java =================================================================== --- src/org/binarytranslator/generic/gdbstub/GDBStub.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/gdbstub/GDBStub.java 2007-03-30 15:38:52 UTC (rev 15) @@ -40,7 +40,7 @@ /** * The process being debugged */ - private final ProcessSpace ps; + private final GDBTarget target; /** * Thread to continue or step, a value of -1 means all threads, 0 * means any thread. @@ -93,7 +93,7 @@ /** * Constructor */ - public GDBStub(int port, ProcessSpace ps) { + public GDBStub(int port, GDBTarget target) { try { ServerSocket connectionSocket = new ServerSocket(port); socket = connectionSocket.accept(); @@ -105,7 +105,7 @@ throw new Error("Error opening socket", e); } breakpoints = new int[0]; - this.ps = ps; + this.target = target; } /** @@ -228,14 +228,14 @@ // byte command[] = {'S','0','5'}; <- a command to just say stopped by SIGTRAP byte command[]; int index; - if (ps.hasFrameBaseRegister()) { + if (target.hasFrameBaseRegister()) { // Add base pointer to packet command = new byte[39]; - int bpReg = ps.getGDBFrameBaseRegister(); + int bpReg = target.getGDBFrameBaseRegister(); command[3] = intToHex(bpReg >> 4); command[4] = intToHex(bpReg); command[5] = ':'; - byte bpVal[] = ps.readRegisterGDB(bpReg); + byte bpVal[] = target.readRegisterGDB(bpReg); command[6] = intToHex(bpVal[0] >> 4); command[7] = intToHex(bpVal[0]); command[8] = intToHex(bpVal[1] >> 4); @@ -254,11 +254,11 @@ command[1] = '0'; command[2] = '5'; // stopped by trap { // Add stack pointer to packet - int spReg = ps.getGDBStackPointerRegister(); + int spReg = target.getGDBStackPointerRegister(); command[index] = intToHex(spReg >> 4); index++; command[index] = intToHex(spReg); index++; command[index] = ':'; index++; - byte spVal[] = ps.readRegisterGDB(spReg); + byte spVal[] = target.readRegisterGDB(spReg); command[index] = intToHex(spVal[0] >> 4); index++; command[index] = intToHex(spVal[0]); index++; command[index] = intToHex(spVal[1] >> 4); index++; @@ -270,11 +270,11 @@ command[index] = ';'; index++; } { // Add program counter to packet - int pcReg = ps.getGDBProgramCountRegister(); + int pcReg = target.getGDBProgramCountRegister(); command[index] = intToHex(pcReg >> 4); index++; command[index] = intToHex(pcReg); index++; command[index] = ':'; index++; - byte pcVal[] = ps.readRegisterGDB(pcReg); + byte pcVal[] = target.readRegisterGDB(pcReg); command[index] = intToHex(pcVal[0] >> 4); index++; command[index] = intToHex(pcVal[0]); index++; command[index] = intToHex(pcVal[1] >> 4); index++; @@ -357,7 +357,7 @@ } else { regNum = hexToInt(buffer[2]); } - byte value[] = ps.readRegisterGDB(regNum); + byte value[] = target.readRegisterGDB(regNum); byte hexValue[] = new byte[value.length * 2]; for(int i=0; i < value.length; i++) { hexValue[i*2] = intToHex(value[i] >> 4); @@ -378,7 +378,7 @@ try { byte value[] = new byte[count*2]; for(int i=0; i < count; i++) { - byte byteVal = ps.memoryLoad8(address+i); + byte byteVal = target.memoryLoad8(address+i); value[i*2] = intToHex(byteVal >> 4); value[(i*2)+1] = intToHex(byteVal); } @@ -401,7 +401,7 @@ byte value[] = new byte[2]; for(int i=0; i < count; i++) { byte byteVal = (byte)((hexToInt(buffer[start+(i*2)]) << 4) | (hexToInt(buffer[start+(i*2)+1]))); - ps.memoryStore8(address+i, byteVal); + target.memoryStore8(address+i, byteVal); } replyOK(); } catch (NullPointerException e) { @@ -444,7 +444,7 @@ // the next two optional characters specify the thread // to step, we have one thread so we ignore them try { - ps.runOneInstruction(); + target.runOneInstruction(); index = dataEnd; // report that a SIGTRAP halted the debugger sendStoppedByTrap(); @@ -461,9 +461,9 @@ try { boolean hitBreakpoint; do { - ps.runOneInstruction(); + target.runOneInstruction(); hitBreakpoint = false; - int pc = ps.getCurrentInstructionAddress(); + int pc = target.getCurrentInstructionAddress(); for(int i=0; i < breakpoints.length; i++) { if(pc == breakpoints[i]) { hitBreakpoint = true; Added: src/org/binarytranslator/generic/gdbstub/GDBTarget.java =================================================================== --- src/org/binarytranslator/generic/gdbstub/GDBTarget.java (rev 0) +++ src/org/binarytranslator/generic/gdbstub/GDBTarget.java 2007-03-30 15:38:52 UTC (rev 15) @@ -0,0 +1,53 @@ +package org.binarytranslator.generic.gdbstub; + +import org.binarytranslator.generic.fault.BadInstructionException; + +public interface GDBTarget { + /** + * Read a register from the target machine. + * + * @param regNum + * A register number, starting from 0. + */ + byte[] readRegisterGDB(int regNum); + + /** + * Run a single instruction + */ + void runOneInstruction() throws BadInstructionException; + + /** + * Has frame base register? + */ + boolean hasFrameBaseRegister(); + + /** + * Get the value of the frame base register + */ + int getGDBFrameBaseRegister(); + + /** + * Get the value of the frame base register + */ + int getGDBStackPointerRegister(); + + /** + * Get the value of the frame base register + */ + int getGDBProgramCountRegister(); + + /** + * Return the address of the current instruction. + */ + int getCurrentInstructionAddress(); + + /** + * Store the given bye of data at the given address within the process. + */ + void memoryStore8(int address, byte data); + + /** + * Load a byte from the given address within the process. + */ + byte memoryLoad8(int address); +} Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-03-30 15:38:52 UTC (rev 15) @@ -15,7 +15,23 @@ * the memory and registers of various architectures. */ public interface LinuxSystemCallGenerator { + /** + * This interface allows you to iteratively grab all arguments to a system call. + */ + public interface CallArgumentIterator { + /** + * Interpret the next system call argument as an integer and return it. + */ + int nextInt(); + + /** + * Interpret the next system call argument as a long and return it. + */ + long nextLong(); + } + + /** * Return the system call number from the generator */ public int getSysCallNumber(); @@ -24,7 +40,7 @@ * @param n number of system call arguments to read * @return array of system call argument values */ - public int[] getSysCallArguments(int n); + public CallArgumentIterator getSysCallArguments(); /** * Set the return value for a system call * @param r the return value Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-03-30 15:38:52 UTC (rev 15) @@ -445,6 +445,14 @@ */ public abstract void doSysCall(); } + + abstract class ParameterizedSystemCall extends SystemCall { + protected LinuxSystemCallGenerator.CallArgumentIterator arguments; + + public ParameterizedSystemCall() { + arguments = src.getSysCallArguments(); + } + } /** * Unknown System Call @@ -466,11 +474,9 @@ /** * Exit system call */ - public class SysExit extends SystemCall { + public class SysExit extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(1); - int status = args[0]; - + int status = arguments.nextInt(); System.exit(status); } } @@ -478,12 +484,11 @@ /** * Read from a file */ - public class SysRead extends SystemCall { + public class SysRead extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(3); - int fd = args[0]; - int buf = args[1]; - int count = args[2]; + int fd = arguments.nextInt(); + int buf = arguments.nextInt(); + int count = arguments.nextInt(); if(fd == 0) { // read from stdin byte[] b = new byte[256]; @@ -528,12 +533,11 @@ /** * Write to a file */ - public class SysWrite extends SystemCall { + public class SysWrite extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(3); - int fd = args[0]; - int buf = args[1]; - int count = args[2]; + int fd = arguments.nextInt(); + int buf = arguments.nextInt(); + int count = arguments.nextInt(); if(fd == 1) { // stdout for(int c = 0 ; c < count; c++) { @@ -579,12 +583,11 @@ /** * Write data into multiple buffers */ - public class SysWriteV extends SystemCall { - public void doSysCall() { - int[] args = src.getSysCallArguments(3); - int fd = args[0]; - int vector = args[1]; - int count = args[2]; + public class SysWriteV extends ParameterizedSystemCall { + public void doSysCall() { + int fd = arguments.nextInt(); + int vector = arguments.nextInt(); + int count = arguments.nextInt(); if((fd == 1)||(fd == 2)) { // stdout || stderr PrintStream out = (fd == 1) ? System.out : System.err; @@ -609,11 +612,10 @@ } } - public class SysOpen extends SystemCall { + public class SysOpen extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(2); - int pathname = args[0]; - int flags = args[1]; + int pathname = arguments.nextInt(); + int flags = arguments.nextInt(); // Examine the flags argument and open read or read-write // accordingly. args[0] points to the file name. @@ -660,10 +662,9 @@ } } - public class SysClose extends SystemCall { + public class SysClose extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(1); - int fd = args[0]; + int fd = arguments.nextInt(); RandomAccessFile raFile = getRAFile(fd); // Check that fd is a valid file descriptor if(raFile == null) { @@ -705,16 +706,17 @@ } } - public class SysBrk extends SystemCall { + public class SysBrk extends ParameterizedSystemCall { public void doSysCall() { - int args[] = src.getSysCallArguments(1); - if(args[0] == 0) { + int brk = arguments.nextInt(); + + if(brk == 0) { // Request for the current top of bss. src.setSysCallReturn(src.getBrk()); } else { // Changing the value. - src.setBrk(args[0]); + src.setBrk(brk); } } } @@ -724,13 +726,11 @@ } } - public class SysFcntl64 extends SystemCall { + public class SysFcntl64 extends ParameterizedSystemCall { public void doSysCall() { // This is complicated so fudge it for now. - int[] args = src.getSysCallArguments(2); - - int fd = args[0]; - int cmd = args[1]; + int fd = arguments.nextInt(); + int cmd = arguments.nextInt(); if( ((fd == 0) | (fd == 1) | (fd == 2)) & (cmd == 1) ) src.setSysCallReturn(0); @@ -739,11 +739,12 @@ } } - public class SysUname extends SystemCall { + public class SysUname extends ParameterizedSystemCall { public void doSysCall() { // Simple uname support - int[] args = src.getSysCallArguments(1); - if (args[0] != 0) { + int addr = arguments.nextInt(); + + if (addr != 0) { String localhostString, domainName, hostName; try { InetAddress localhost = InetAddress.getLocalHost(); @@ -762,12 +763,12 @@ hostName = localhostString.substring(0,index); } // Fill in utsname struct - see /usr/include/sys/utsname.h - src.memoryWriteString (args[0], getSysName()); // sysname - src.memoryWriteString (args[0]+65, hostName); // nodename - src.memoryWriteString (args[0]+130, getRelease()); // release - src.memoryWriteString (args[0]+195, getVersion()); // version - src.memoryWriteString (args[0]+260, getMachine()); // machine - src.memoryWriteString (args[0]+325, domainName); // __domainname + src.memoryWriteString (addr, getSysName()); // sysname + src.memoryWriteString (addr+65, hostName); // nodename + src.memoryWriteString (addr+130, getRelease()); // release + src.memoryWriteString (addr+195, getVersion()); // version + src.memoryWriteString (addr+260, getMachine()); // machine + src.memoryWriteString (addr+325, domainName); // __domainname src.setSysCallReturn(0); } else { @@ -777,15 +778,15 @@ } } - public class SysMmap extends SystemCall { + public class SysMmap extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(6); - int start = args[0]; - int length = args[1]; - int prot = args[2]; - int flags = args[3]; - int fd = args[4]; - int offset = args[5]; + + int start = arguments.nextInt(); + int length = arguments.nextInt(); + int prot = arguments.nextInt(); + int flags = arguments.nextInt(); + int fd = arguments.nextInt(); + int offset = arguments.nextInt(); if((flags & mman.MAP_ANONYMOUS) != 0 ) { try { src.setSysCallReturn(src.memoryMap(start, length, @@ -802,20 +803,20 @@ } } - public class SysMunmap extends SystemCall { + public class SysMunmap extends ParameterizedSystemCall { public void doSysCall() { - int[] args = src.getSysCallArguments(2); - int start = args[0]; - int length = args[1]; + + int start = arguments.nextInt(); + int length = arguments.nextInt(); throw new Error("TODO!"); //src.setSysCallReturn(src.munmap(start, length)); } } - public class SysExitGroup extends SystemCall { + public class SysExitGroup extends ParameterizedSystemCall { public void doSysCall() { // For now, equivalent to SysExit - System.exit(src.getSysCallArguments(1)[0]); + System.exit(arguments.nextInt()); } } } Modified: src/org/binarytranslator/generic/os/loader/Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/Loader.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/os/loader/Loader.java 2007-03-30 15:38:52 UTC (rev 15) @@ -10,6 +10,7 @@ import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.os.loader.elf.ELF_Loader; +import org.binarytranslator.generic.os.loader.image.ImageLoader; import org.binarytranslator.DBT_Options; import java.io.*; @@ -97,30 +98,19 @@ * @return a binaryloader to create a process */ public static Loader getLoader(String filename) throws IOException - { - File file = new File(filename); - RandomAccessFile rFile = new RandomAccessFile(file, "r"); - report("Opened file: " + filename); - - byte[] id = new byte[4]; - rFile.read(id); - report("Read ID"); - - if (isELF_Binary(id)) { + { + if (ELF_Loader.conforms(filename)) { report("ELF object file found"); return new ELF_Loader(); - } else { + } + else if (ImageLoader.conforms(filename)) { + report("Image Loader file found."); + return new ImageLoader(); + } + else { throw new Error("File " + filename + " has an unrecognized binary format"); } } - /** - * Determine if the id array corresponds with the initial part of an - * ELF binary - * @param id start of binary - * @return whether this is an ELF binary - */ - private static boolean isELF_Binary(byte[] id) { - return (id[0] == 0x7f) && (id[1] == 'E') && (id[2] == 'L') && (id[3] == 'F'); - } + } Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-03-30 15:38:52 UTC (rev 15) @@ -121,9 +121,8 @@ */ public ProcessSpace readBinary(String[] args) throws IOException { - File elfFile = new File(args[0]); - RandomAccessFile rFile = new RandomAccessFile(elfFile, "r"); - report("Opened File: " + elfFile); + report("Opening File: " + args[0]); + RandomAccessFile rFile = new RandomAccessFile(args[0], "r"); elfHeader = new ELF_Header(rFile); //NB also sets up reader report("ELF header read successfully"); @@ -154,6 +153,35 @@ return ps; } + + /** + * Determine if the id array corresponds with the initial part of an + * ELF binary + * @param filename Name of the file to check + * @return whether this is an ELF binary + */ + public static boolean conforms(String filename) { + + RandomAccessFile rFile = null; + report("Testing is file is ELF: " + filename); + + try { + rFile = new RandomAccessFile(filename, "r"); + byte[] id = new byte[4]; + rFile.read(id); + + return (id[0] == 0x7f) && (id[1] == 'E') && (id[2] == 'L') && (id[3] == 'F'); + } + catch (Exception e) { + return false; + } + finally { + try { + rFile.close(); + } + catch(Exception e) {} + } + } /** * Read and construct the program segment headers Added: src/org/binarytranslator/generic/os/loader/image/ImageLoader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/image/ImageLoader.java (rev 0) +++ src/org/binarytranslator/generic/os/loader/image/ImageLoader.java 2007-03-30 15:38:52 UTC (rev 15) @@ -0,0 +1,156 @@ +package org.binarytranslator.generic.os.loader.image; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.io.UnsupportedEncodingException; + +import org.binarytranslator.DBT_Options; +import org.binarytranslator.generic.memory.MemoryMapException; +import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.process.ProcessSpace; + +/** + * A very simple loader, that will load binary directly into memory and then start executing it from address 0. + * Actually, this is just a hack to the .bin file format to include some header information that tells us the + * architecture for this image. + * The file format is: + * [Identifier] <8 ASCII-CHARS> EXT_IMG\0 + * [File Version] <1 BYTE> 0x0 + * [Architecture ID] <4 ASCII-CHARS> <ARM|PPC|X86> \0 + * [Padding] <3 BYTE> + * [Image data] <BINARY-Data> <Assembly Code, to be loaded at addr #0> + * @author baerm + * + */ +public class ImageLoader extends Loader { + + private String architecture; + + @Override + public String getABIString() { + return null; + } + + @Override + public String getArchitectureString() { + return architecture; + } + + @Override + public boolean isARM_ABI() { + return false; + } + + @Override + public boolean isARM_ISA() { + return architecture.equals("ARM"); + } + + @Override + public boolean isLinuxABI() { + return false; + } + + @Override + public boolean isPPC_ISA() { + return architecture.equals("ISA"); + } + + @Override + public boolean isSysV_ABI() { + return false; + } + + @Override + public boolean isX86_ISA() { + return architecture.equals("X86"); + } + + /** + * Read from the given file and determine whether it contains the correct ID string for an + * ASM Loader file. + */ + private static boolean readAndCheckID(RandomAccessFile file) { + try { + byte[] ID = new byte[8]; + if (file.read(ID) != ID.length) + return false; + + return ID[0] == 'E' && ID[1] == 'X' && ID[2] == 'T' && ID[3] == '_' + && ID[4] == 'I' && ID[5] == 'M' && ID[6] == 'G' && ID[7] == 0; + } + catch (Exception e) { + return false; + } + } + + public ProcessSpace readBinary(String[] args) throws IOException { + + report("Reading: " + args[0]); + RandomAccessFile file = new RandomAccessFile(args[0], "r"); + + if (!readAndCheckID(file)) + throw new IOException("File does not contain the expected EXT_IMG ID string."); + + //check the file version. Currently, we only support one version anyway. + byte version = file.readByte(); + + if (version != 0) { + throw new IOException("Unsupported image file version."); + } + + byte[] architecture = new byte[3]; + if (file.read(architecture) != architecture.length) + throw new IOException("Unable to read architecture string."); + + //read the architecture string + this.architecture = new String(architecture, "ASCII"); + + //skip the double-word padding and the delimiter of the architecture string + //file.skipBytes(4); + + ProcessSpace ps = ProcessSpace.createProcessSpaceFromBinary(this); + + int fileAndMemSize = (int)file.length() - 16; + try { + ps.createSegment(file, 16, 0, fileAndMemSize, fileAndMemSize, true, true, true); + } + catch (MemoryMapException e) { + e.printStackTrace(); + return null; + } + + ps.initialise(this, 0, -1, args); + return ps; + } + + /** + * Checks if the given file is an ASM Loader file. + */ + public static boolean conforms(String filename) { + + report("Testing if file conforms: " + filename); + RandomAccessFile file = null; + + try { + //if the file contains the correct ID string, then we assume it to be an ASM loader file + file = new RandomAccessFile(filename, "r"); + return readAndCheckID(file); + } + catch (Exception e) { + return false; + } + finally { + try { + file.close(); + } + catch (Exception e) {} + } + } + + private static void report(String s){ + if (DBT_Options.debugLoader) { + System.out.print("Image Loader:"); + System.out.println(s); + } + } +} Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-29 13:53:07 UTC (rev 14) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-30 15:38:52 UTC (rev 15) @@ -24,6 +24,7 @@ import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.gdbstub.GDBStub; +import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; @@ -191,8 +192,10 @@ * the generation context for the HIR generation * @return a HIR generator */ + public abstract OPT_HIRGenerator createHIRGenerator( - OPT_GenerationContext context); + OPT_GenerationContext context); + /** * Given an ELF binary loader, create the appropriate process space @@ -316,7 +319,7 @@ VM_CodeArray code = cm.getEntryCodeArray(); codeHash.put(trace.pc, code); } - + public synchronized VM_CodeArray getCodeForPC(int pc) { VM_CodeArray code = (VM_CodeArray) codeHash.get(pc); if (code == null) { @@ -324,7 +327,7 @@ } return code; } - + private VM_CodeArray translateCode(DBT_Trace trace) { if (DBT_Options.debugRuntime) { report("Translating code for 0x" + Integer.toHexString(trace.pc)); @@ -334,6 +337,8 @@ replaceCompiledTrace(cm, trace); return cm.getEntryCodeArray(); } + + /* /** * Record a branch instruction @@ -415,7 +420,7 @@ System.out.println(e.toString()); } } else { - GDBStub gdbStub = new GDBStub(DBT_Options.gdbStubPort, this); + GDBStub gdbStub = new GDBStub(DBT_Options.gdbStubPort, getGDBTarget()); gdbStub.run(); } } @@ -474,40 +479,9 @@ * DataInputStream(printenv.getInputStream()); variables.readUTF(); } */ } - - /* GDB stub interface */ + /** - * Read a register and turn into a byte array conforming to the endianness of - * the architecture + * Return an interface that allows GDB to read from this process */ - public abstract byte[] readRegisterGDB(int regNum); - - /** - * Run a single instruction - */ - public abstract void runOneInstruction() throws BadInstructionException; - - /** - * Has frame base register? - */ - public boolean hasFrameBaseRegister() { - return false; - } - - /** - * Get the value of the frame base register - */ - public int getGDBFrameBaseRegister() { - return -1; - } - - /** - * Get the value of the frame base register - */ - public abstract int getGDBStackPointerRegister(); - - /** - * Get the value of the frame base register - */ - public abstract int getGDBProgramCountRegister(); + public abstract GDBTarget getGDBTarget(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |