From: <mic...@us...> - 2007-04-13 11:16:14
|
Revision: 37 http://svn.sourceforge.net/pearcolator/?rev=37&view=rev Author: michael_baer Date: 2007-04-13 04:16:14 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Refactored the program main loop into a seperate package (generic.execution) that shall contain all execution strategies. Removed run() method from ProcessSpace. Made GdbStub a seperate execution strategy. Modified Paths: -------------- src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/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/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/generic/execution/ src/org/binarytranslator/generic/execution/DynamicTranslationController.java src/org/binarytranslator/generic/execution/ExecutionController.java src/org/binarytranslator/generic/execution/GdbController.java Removed Paths: ------------- src/org/binarytranslator/generic/gdbstub/ Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/Main.java 2007-04-13 11:16:14 UTC (rev 37) @@ -8,6 +8,9 @@ */ package org.binarytranslator; +import org.binarytranslator.generic.execution.DynamicTranslationController; +import org.binarytranslator.generic.execution.ExecutionController; +import org.binarytranslator.generic.execution.GdbController; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -75,6 +78,21 @@ } report("Sucessfully created process."); - ps.run(); + + if (DBT_Options.debugPS) { + 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 == false) { + controller = new GdbController(DBT_Options.gdbStubPort, ps); + } + else + controller = new DynamicTranslationController(ps); + + controller.run(); } } Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -3,7 +3,7 @@ import org.binarytranslator.arch.arm.decoder.ARM2IR; 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.execution.GdbController.GdbTarget; import org.binarytranslator.generic.os.loader.Loader; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; @@ -23,7 +23,7 @@ } @Override - public GDBTarget getGDBTarget() { + 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-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -4,7 +4,7 @@ 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.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; @@ -100,8 +100,7 @@ } @Override - public GDBTarget getGDBTarget() { - // TODO Auto-generated method stub + public GdbTarget getGdbTarget() { return null; } Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -14,8 +14,8 @@ import org.binarytranslator.arch.ppc.decoder.PPC2IR; import org.binarytranslator.arch.ppc.decoder.PPC_InstructionDecoder; import org.binarytranslator.arch.ppc.os.process.linux.PPC_LinuxProcessSpace; +import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.generic.memory.ByteAddressedByteSwapMemory; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -28,7 +28,7 @@ * Capture the running of a PowerPC process */ public abstract class PPC_ProcessSpace extends ProcessSpace implements - GDBTarget { + 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 variables, not arrays 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-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -11,7 +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.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; @@ -192,7 +192,7 @@ brk = address; } - public GDBTarget getGDBTarget() { + public GdbTarget getGdbTarget() { return this; } Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -16,8 +16,8 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.memory.ByteAddressedMemory; +import org.binarytranslator.generic.execution.GdbController.GdbTarget; 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; @@ -26,7 +26,7 @@ /** * Encapsulate the parts of an X86 process that are common across operating systems */ -public abstract class X86_ProcessSpace extends ProcessSpace implements GDBTarget { +public abstract class X86_ProcessSpace extends ProcessSpace implements GdbTarget { /* * Process defaults @@ -107,7 +107,7 @@ return 8; } - public GDBTarget getGDBTarget() { + public GdbTarget getGdbTarget() { return this; } Added: src/org/binarytranslator/generic/execution/DynamicTranslationController.java =================================================================== --- src/org/binarytranslator/generic/execution/DynamicTranslationController.java (rev 0) +++ src/org/binarytranslator/generic/execution/DynamicTranslationController.java 2007-04-13 11:16:14 UTC (rev 37) @@ -0,0 +1,38 @@ +package org.binarytranslator.generic.execution; + +import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.vmInterface.DynamicCodeRunner; +import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; + +/** + * Runtime loop, goes through the binary and looks in a Hashtable + * to see if we have already translated/compiled this piece of code, if not it + * is compiled. The compiled code is then run. + */ +public class DynamicTranslationController extends ExecutionController { + + public DynamicTranslationController(ProcessSpace ps) { + super(ps); + } + + @Override + public void run() { + // The current block of compiled code. + VM_CodeArray code; + + + try { + // interpretFrom(); // Interpreter - experimental + while (ps.finished == false) { + // Get the compiled code + code = ps.getCodeForPC(ps.getCurrentInstructionAddress()); + // Run the compiled code. + ps.setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, ps)); + } + } catch (BadInstructionException e) { + System.out.println(e.toString()); + } + } + +} Added: src/org/binarytranslator/generic/execution/ExecutionController.java =================================================================== --- src/org/binarytranslator/generic/execution/ExecutionController.java (rev 0) +++ src/org/binarytranslator/generic/execution/ExecutionController.java 2007-04-13 11:16:14 UTC (rev 37) @@ -0,0 +1,14 @@ +package org.binarytranslator.generic.execution; + +import org.binarytranslator.generic.os.process.ProcessSpace; + +public abstract class ExecutionController { + + protected final ProcessSpace ps; + + public ExecutionController(ProcessSpace ps) { + this.ps = ps; + } + + public abstract void run(); +} Added: src/org/binarytranslator/generic/execution/GdbController.java =================================================================== --- src/org/binarytranslator/generic/execution/GdbController.java (rev 0) +++ src/org/binarytranslator/generic/execution/GdbController.java 2007-04-13 11:16:14 UTC (rev 37) @@ -0,0 +1,783 @@ +/* + * 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.execution; + +import java.io.*; +import java.net.*; + +import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.os.process.ProcessSpace; + +/** + * @author Ian Rogers + * @author Michael Baer + * + * Allows to control the execution of a ProcessSpace by using a remote GDB debugger. + */ +public class GdbController extends + ExecutionController { + + /** An interface that all ProcessSpaces have to implement (at the moment).*/ + 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(); + } + + + /** + * The socket that connections will arrive on + */ + private final Socket socket; + + /** + * The stream to read from the socket + */ + private final InputStream in; + + /** + * The stream to read from the socket + */ + private final OutputStream out; + + /** + * A buffer used in the reading/writing of data + */ + private final byte buffer[]; + + /** + * The process being debugged + */ + private final GdbTarget target; + + /** + * Thread to continue or step, a value of -1 means all threads, 0 means any + * thread. + */ + private int threadToStep; + + /** + * Thread to inspect, a value of -1 means all threads, 0 means any thread. + */ + private int threadToInspect; + + /** + * An array of breakpoints + */ + private int breakpoints[]; + + /* GDB Stub commands */ + /** ACK - Acknowledged */ + private final static int ACK = '+'; + + /** NAK - Not acknowledged, implies retransmit */ + private final static int NAK = '-'; + + /** Packet start */ + private final static int START = '$'; + + /** Sequence-ID separator - deprecated */ + private final static int SEQUENCE_ID_SEPERATOR = ':'; + + /** Checksum start */ + private final static int CHECKSUM_START = '#'; + + /** What signal halted the stub? Default is SIGTRAP */ + private final static int LAST_SIGNAL = '?'; + + /** Set thread */ + private final static int SET_THREAD = 'H'; + + /** Stop debugging */ + private final static int KILL_DEBUG = 'k'; + + /** Get memory values */ + private final static int GET_MEM_VALUE = 'm'; + + /** Set memory values */ + private final static int SET_MEM_VALUE = 'M'; + + /** Get a register value */ + private final static int GET_REG_VALUE = 'p'; + + /** Query */ + private final static int QUERY = 'q'; + + /** A verbose packet */ + private final static int VERBOSE_PACKET = 'v'; + + /** Set memory value to binary value */ + private final static int SET_MEM_VALUE_BIN = 'X'; + + /** Remove a breakpoint */ + private final static int REMOVE_BREAKPOINT = 'z'; + + /** Insert a breakpoint */ + private final static int INSERT_BREAKPOINT = 'Z'; + + /* Error codes */ + private final static int CANNOT_ACCESS_MEMORY = 1; + + /** + * Constructor + */ + public GdbController(int port, ProcessSpace ps) { + super(ps); + try { + ServerSocket connectionSocket = new ServerSocket(port); + socket = connectionSocket.accept(); + in = socket.getInputStream(); + out = socket.getOutputStream(); + buffer = new byte[256]; + getACK(); + } catch (IOException e) { + throw new Error("Error opening socket", e); + } + breakpoints = new int[0]; + this.target = ps.getGdbTarget(); + } + + /** + * Main run loop + */ + public void run() { + try { + while (socket.isConnected()) { + int dataEnd = readPacket(); + switch (buffer[1]) { + case GET_REG_VALUE: + handle_getRegValue(dataEnd); + break; + case GET_MEM_VALUE: + handle_getMemValue(dataEnd); + break; + case INSERT_BREAKPOINT: + handle_insertBreakPoint(dataEnd); + break; + case KILL_DEBUG: + System.exit(0); + case LAST_SIGNAL: + handle_lastSignal(dataEnd); + break; + case QUERY: + handle_query(dataEnd); + break; + case REMOVE_BREAKPOINT: + handle_removeBreakPoint(dataEnd); + break; + case SET_MEM_VALUE: + handle_setMemValue(dataEnd); + break; + case SET_MEM_VALUE_BIN: + handle_setMemValueBin(dataEnd); + break; + case SET_THREAD: + handle_setThread(dataEnd); + break; + case VERBOSE_PACKET: + handle_verbose(dataEnd); + break; + default: + throw new Error("Unknown GDB Stub command " + (char) buffer[1]); + } + } + } catch (IOException e) { + throw new Error("Error reading/writing to socket", e); + } + } + + /* Packet commands */ + /** + * Get an acknowledge + */ + private void getACK() throws IOException { + int command = in.read(); + if (command != ACK) { + throw new IOException("Acknowledge expected but got " + (char) command); + } + } + + /** + * Send an acknowledge + */ + private void sendACK() throws IOException { + out.write(ACK); + } + + /** + * Read a packet into the buffer and check the checksum + * + * @return the last byte in the buffer prior to the checksum + */ + 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]); + } + // Read the data + int csum = 0; + do { + index++; + buffer[index] = (byte) in.read(); + csum += (int) buffer[index]; + } while (buffer[index] != CHECKSUM_START); + csum -= CHECKSUM_START; + csum &= 0xFF; + // Abort if we got a sequence ID + if (buffer[3] == SEQUENCE_ID_SEPERATOR) { + throw new IOException("Found unsupported sequence ID in packet"); + } + // Read the checksum + index++; + buffer[index] = (byte) in.read(); + index++; + buffer[index] = (byte) in.read(); + int checkSum = (hexToInt(buffer[index - 1]) << 4) | hexToInt(buffer[index]); + if (checkSum == csum) { + report("Read: " + bufferToString(0, index)); + sendACK(); + return index - 3; + } else { + throw new IOException("Packet's checksum of " + checkSum + + " doesn't match computed checksum of " + csum); + } + } + + /** + * Send the command + */ + private void sendCommand(byte command[]) throws IOException { + buffer[0] = START; + int index = 1; + int csum = 0; + if (command != null) { + for (int i = 0; i < command.length; i++, index++) { + buffer[index] = command[i]; + csum += command[i]; + } + } + buffer[index] = CHECKSUM_START; + index++; + buffer[index] = intToHex(csum >> 4); + index++; + buffer[index] = intToHex(csum); + out.write(buffer, 0, index + 1); + report("Sent: " + bufferToString(0, index)); + getACK(); + } + + /** + * Send a reply of 'OK' + */ + private void replyOK() throws IOException { + byte command[] = { 'O', 'K' }; + sendCommand(command); + } + + /** + * Send a message saying that a sig trap stopped us + */ + private void sendStoppedByTrap() throws IOException { + // report that a SIGTRAP halted the debugger + // byte command[] = {'S','0','5'}; <- a command to just say stopped by + // SIGTRAP + byte command[]; + int index; + if (target.hasFrameBaseRegister()) { + // Add base pointer to packet + command = new byte[39]; + int bpReg = target.getGDBFrameBaseRegister(); + command[3] = intToHex(bpReg >> 4); + command[4] = intToHex(bpReg); + command[5] = ':'; + byte bpVal[] = target.readRegisterGDB(bpReg); + command[6] = intToHex(bpVal[0] >> 4); + command[7] = intToHex(bpVal[0]); + command[8] = intToHex(bpVal[1] >> 4); + command[9] = intToHex(bpVal[1]); + command[10] = intToHex(bpVal[2] >> 4); + command[11] = intToHex(bpVal[2]); + command[12] = intToHex(bpVal[3] >> 4); + command[13] = intToHex(bpVal[3]); + command[14] = ';'; + index = 15; + } else { + command = new byte[27]; + index = 3; + } + command[0] = 'T'; + command[1] = '0'; + command[2] = '5'; // stopped by trap + { // Add stack pointer to packet + int spReg = target.getGDBStackPointerRegister(); + command[index] = intToHex(spReg >> 4); + index++; + command[index] = intToHex(spReg); + index++; + command[index] = ':'; + index++; + 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++; + command[index] = intToHex(spVal[1]); + index++; + command[index] = intToHex(spVal[2] >> 4); + index++; + command[index] = intToHex(spVal[2]); + index++; + command[index] = intToHex(spVal[3] >> 4); + index++; + command[index] = intToHex(spVal[3]); + index++; + command[index] = ';'; + index++; + } + { // Add program counter to packet + int pcReg = target.getGDBProgramCountRegister(); + command[index] = intToHex(pcReg >> 4); + index++; + command[index] = intToHex(pcReg); + index++; + command[index] = ':'; + index++; + 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++; + command[index] = intToHex(pcVal[1]); + index++; + command[index] = intToHex(pcVal[2] >> 4); + index++; + command[index] = intToHex(pcVal[2]); + index++; + command[index] = intToHex(pcVal[3] >> 4); + index++; + command[index] = intToHex(pcVal[3]); + index++; + command[index] = ';'; + index++; + } + sendCommand(command); + } + + /** + * Send a reply of 'ENN' indicating an error with error code NN + */ + private void replyError(int nn) throws IOException { + byte command[] = { 'E', intToHex(nn >> 4), intToHex(nn) }; + sendCommand(command); + } + + /** + * A command arrived to set the thread for subsequent operations + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_setThread(int dataEnd) throws IOException { + if (buffer[2] == 'c') { + threadToStep = Integer.parseInt(bufferToString(3, dataEnd)); + replyOK(); + } else if (buffer[2] == 'g') { + threadToInspect = Integer.parseInt(bufferToString(3, dataEnd)); + replyOK(); + } else { + replyError(0); + } + } + + /** + * A query packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_query(int dataEnd) throws IOException { + if (buffer[2] == 'C') { // query current thread + // send reply that current thread is 1 + byte command[] = { 'Q', 'C', '0', '1' }; + sendCommand(command); + } else if (doesBufferMatch(2, new byte[] { 'O', 'f', 'f', 's', 'e', 't', + 's' })) { + // query relocation offsets. As the binary is loaded where it + // hoped then we don't specify any relocation offsets. + byte command[] = { 'T', 'e', 'x', 't', '=', '0', ';', 'D', 'a', 't', 'a', + '=', '0', ';', 'B', 's', 's', '=', '0' }; + sendCommand(command); + } else if (doesBufferMatch(2, new byte[] { 'S', 'y', 'm', 'b', 'o', 'l', + ':', ':' })) { + // GDB is telling us it will handle symbol queries for us - nice :-) + replyOK(); + } else { + // unrecognized query + sendCommand(null); + } + } + + /** + * A last signal packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_lastSignal(int dataEnd) throws IOException { + sendStoppedByTrap(); + } + + /** + * A get register value packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_getRegValue(int dataEnd) throws IOException { + int regNum; + if (buffer[3] != CHECKSUM_START) { + regNum = (hexToInt(buffer[2]) << 4) | hexToInt(buffer[3]); + } else { + regNum = hexToInt(buffer[2]); + } + 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); + hexValue[(i * 2) + 1] = intToHex(value[i]); + } + sendCommand(hexValue); + } + + /** + * A get memory value packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_getMemValue(int dataEnd) throws IOException { + String data = bufferToString(2, dataEnd); + int address = Integer.parseInt(data.substring(0, data.indexOf(',')), 16); + int count = Integer.parseInt(data.substring(data.indexOf(',') + 1), 16); + try { + byte value[] = new byte[count * 2]; + for (int i = 0; i < count; i++) { + byte byteVal = (byte) ps.memory.loadUnsigned8(address + i); + value[i * 2] = intToHex(byteVal >> 4); + value[(i * 2) + 1] = intToHex(byteVal); + } + sendCommand(value); + } catch (NullPointerException e) { + replyError(CANNOT_ACCESS_MEMORY); + } + } + + /** + * A set memory value packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_setMemValue(int dataEnd) throws IOException { + int address = readHexValFromBuffer(2); + int count = readHexValFromBuffer(indexOf(2, ',') + 1); + int start = indexOf(2, ':') + 1; + try { + 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.memory.store8(address + i, byteVal); + } + replyOK(); + } catch (NullPointerException e) { + replyError(CANNOT_ACCESS_MEMORY); + } + } + + /** + * A set memory value packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_setMemValueBin(int dataEnd) throws IOException { + // Report not supported + sendCommand(null); + } + + /** + * A verbose packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_verbose(int dataEnd) throws IOException { + if (doesBufferMatch(2, new byte[] { 'C', 'o', 'n', 't' })) { + if (buffer[6] == '?') { // query what verbose resume commands are + // supported + byte command[] = { 'v', 'C', 'o', 'n', 't', ';', 's', ';', 'S', ';', + 'c', ';', 'C' }; + sendCommand(command); + } else { // a verbose resume packet + int index = 6; + while (index < dataEnd) { + if (buffer[index] != ';') { + // values for each thread should be ';' separated + replyError(0); + break; + } else { + switch (buffer[index + 1]) { + case 's': + // the next two optional characters specify the thread + // to step, we have one thread so we ignore them + try { + target.runOneInstruction(); + index = dataEnd; + // report that a SIGTRAP halted the debugger + sendStoppedByTrap(); + } catch (BadInstructionException e) { + // report that a SIGILL halted the debugger + byte command[] = { 'S', '0', '4' }; + sendCommand(command); + } + break; + case 'c': + // the next two optional characters specify the thread + // to step, we have one thread so we ignore them + try { + boolean hitBreakpoint; + do { + target.runOneInstruction(); + hitBreakpoint = false; + int pc = target.getCurrentInstructionAddress(); + for (int i = 0; i < breakpoints.length; i++) { + if (pc == breakpoints[i]) { + hitBreakpoint = true; + break; + } + } + } while (!hitBreakpoint); + index = dataEnd; + // report that a SIGTRAP halted the debugger + sendStoppedByTrap(); + } catch (BadInstructionException e) { + // report that a SIGILL halted the debugger + byte command[] = { 'S', '0', '4' }; + sendCommand(command); + } + break; + case 'S': + case 'C': + default: + replyError(0); + break; + } + } + } + } + } else { // unknown verbose packet + replyError(0); + } + } + + /** + * Insert a break point + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_insertBreakPoint(int dataEnd) throws IOException { + String data = bufferToString(4, dataEnd); + int address = Integer.parseInt(data.substring(0, data.indexOf(',')), 16); + int length = Integer.parseInt(data.substring(data.indexOf(',') + 1), 16); + switch (buffer[2]) { // determine the breakpoint type + case '0': // memory break point + int newbp[] = new int[breakpoints.length + 1]; + System.arraycopy(breakpoints, 0, newbp, 0, breakpoints.length); + newbp[breakpoints.length] = address; + breakpoints = newbp; + replyOK(); + break; + default: // unrecognized breakpoint type + sendCommand(null); + } + } + + /** + * Remove a break point + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_removeBreakPoint(int dataEnd) throws IOException { + String data = bufferToString(4, dataEnd); + int address = Integer.parseInt(data.substring(0, data.indexOf(',')), 16); + int length = Integer.parseInt(data.substring(data.indexOf(',') + 1), 16); + switch (buffer[2]) { // determine the breakpoint type + case '0': // memory break point + int breakpointToRemove = -1; + for (int i = 0; i < breakpoints.length; i++) { + if (breakpoints[i] == address) { + breakpointToRemove = i; + break; + } + } + if (breakpointToRemove >= 0) { + int newbp[] = new int[breakpoints.length - 1]; + for (int fromIndex = 0, toIndex = 0; fromIndex < breakpoints.length; fromIndex++) { + if (fromIndex != breakpointToRemove) { + newbp[toIndex] = breakpoints[fromIndex]; + toIndex++; + } + } + breakpoints = newbp; + replyOK(); + } else { // breakpoint wasn't found + sendCommand(null); + } + break; + default: // unrecognized breakpoint type + sendCommand(null); + } + } + + /* Utilities */ + /** + * Convert the ASCII character in the byte, convert it to its integer value + */ + private static int hexToInt(byte val) { + if ((val >= 'a') && (val <= 'f')) { + return val - 'a' + 10; + } else if ((val >= 'A') && (val <= 'F')) { + return val - 'A' + 10; + } else if ((val >= '0') && (val <= '9')) { + return val - '0'; + } else { // found none hex value + return -1; + } + } + + /** + * Convert the nibble integer into the ASCII character + */ + private static byte intToHex(int val) { + val &= 0xF; + if ((val >= 0) && (val <= 9)) { + return (byte) (val + '0'); + } else { // ((val >= 10) && (val <= 15)) + return (byte) (val + 'a' - 10); + } + } + + /** + * Convert a range in the buffer into a String + */ + private String bufferToString(int start, int end) { + StringBuffer sb = new StringBuffer(end - start + 1); + for (; start <= end; start++) { + sb.append((char) buffer[start]); + } + return sb.toString(); + } + + /** + * Read a hexadecimal value from the buffer + */ + private int readHexValFromBuffer(int start) throws IOException { + int result = 0; + for (int i = 0; i < 8; i++) { + int hexVal = hexToInt(buffer[start + i]); + if (hexVal == -1) + break; + result <<= 4; + result |= hexVal; + } + return result; + } + + /** + * Does the buffer starting at start match the byte array match + */ + private boolean doesBufferMatch(int start, byte match[]) { + for (int i = 0; i < match.length; i++) { + if (buffer[start + i] != match[i]) { + return false; + } + } + return true; + } + + /** + * Return the first index of the specified character + */ + private int indexOf(int start, char toFind) { + for (int i = start; i < buffer.length; i++) { + if (buffer[i] == (byte) toFind) { + return i; + } + } + return -1; + } + + /** + * Debug information + * + * @param s + * string of debug information + */ + private static void report(String s) { + if (true) { + System.out.print("GDBStub:"); + System.out.println(s); + } + } +} Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -8,27 +8,24 @@ */ package org.binarytranslator.generic.os.process; +import java.io.IOException; +import java.io.RandomAccessFile; import java.util.Hashtable; -import java.io.*; -import org.jikesrvm.compilers.common.VM_CompiledMethod; -import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; -import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; - -import org.binarytranslator.vmInterface.DBT_Trace; -import org.binarytranslator.vmInterface.DynamicCodeRunner; import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; +import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.generic.branch.BranchLogic; +import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.memory.Memory; 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; -import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; +import org.binarytranslator.vmInterface.DBT_Trace; +import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; +import org.jikesrvm.compilers.common.VM_CompiledMethod; +import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; +import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.vmmagic.pragma.Uninterruptible; @@ -289,43 +286,6 @@ } /** - * Runtime loop, goes through the binary and looks in the Hashtable codeHash - * to see if we have already translated/compiled this piece of code, if not it - * is compiled. The compiled code is then run. - */ - public void run() { - if (DBT_Options.debugRuntime) { - System.out.println("Main: run"); - } - - // The current block of compiled code. - VM_CodeArray code; - - if (DBT_Options.debugPS) { - System.out.println("***** INITIAL PROCESS SPACE *****\n" + this); - System.out.println(this); - // dumpStack(20); - } - - if (DBT_Options.gdbStub == false) { - try { - // interpretFrom(); // Interpreter - experimental - while (finished == false) { - // Get the compiled code - code = getCodeForPC(getCurrentInstructionAddress()); - // Run the compiled code. - setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, this)); - } - } catch (BadInstructionException e) { - System.out.println(e.toString()); - } - } else { - GDBStub gdbStub = new GDBStub(DBT_Options.gdbStubPort, this); - gdbStub.run(); - } - } - - /** * Entry point for system calls */ public abstract void doSysCall(); @@ -383,5 +343,5 @@ /** * Return an interface that allows GDB to read from this process */ - public abstract GDBTarget getGDBTarget(); + public abstract GdbTarget getGdbTarget(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |