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-14 09:35:22
|
Revision: 49 http://svn.sourceforge.net/pearcolator/?rev=49&view=rev Author: michael_baer Date: 2007-04-14 02:35:23 -0700 (Sat, 14 Apr 2007) Log Message: ----------- Moved createSegment() from ProcessSpace to ELF_Loader. Modified Paths: -------------- 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/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-13 18:40:22 UTC (rev 48) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-14 09:35:23 UTC (rev 49) @@ -10,6 +10,7 @@ import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.DBT_Options; @@ -935,11 +936,11 @@ break; case PT_LOAD: // A loadable segment try { - ps.createSegment(reader.rFile, - p_offset, p_vaddr, - p_filesz, p_memsz, - (p_flags & PF_R) != 0, (p_flags & PF_W) != 0, (p_flags & PF_X) != 0 - ); + createSegment(ps.memory, + reader.rFile, + p_offset, p_vaddr, + p_filesz, p_memsz, + (p_flags & PF_R) != 0, (p_flags & PF_W) != 0, (p_flags & PF_X) != 0); } catch(MemoryMapException e) { throw new Error("Error in creating: " + this, e); @@ -959,6 +960,68 @@ throw new Error("Segment type " + toString() + " not yet supported"); } } + + /** + * Create a segment + * + * @param memory + * The memory into which the segment is to be mapped. + * @param file + * file to read segment data from if file size != 0 + * @param offset + * file offset + * @param address + * location of segment + * @param filesize + * size of segment in file + * @param memsize + * size of segment in memory + * @param read + * is segment readable + * @param write + * is segment writable + * @param exec + * is segment executable + */ + public void createSegment(Memory memory, RandomAccessFile file, long offset, int address, + int filesize, int memsize, boolean read, boolean write, boolean exec) + throws MemoryMapException { + // Sanity check + if (memsize < filesize) { + throw new Error("Segment memory size (" + memsize + + ")less than file size (" + filesize + ")"); + } + // Are we mapping anything from a file? + if (filesize == 0) { + // No: map anonymously + memory.map(address, memsize, read, write, exec); + } else { + // align offset and address + int alignedAddress; + long alignedOffset; + int alignedFilesize; + if (memory.isPageAligned(address)) { + // memory and therefore offset should be aligned + alignedAddress = address; + alignedOffset = offset; + alignedFilesize = filesize; + } else { + // Address not aligned + alignedAddress = memory.truncateToPage(address); + int delta = address - alignedAddress; + // adjust offset and length too + alignedOffset = offset - delta; + alignedFilesize = filesize + delta; + } + memory.map(file, alignedOffset, alignedAddress, alignedFilesize, read, + write, exec); + // Do we need to map in some blank pages at the end of the segment? + if (filesize < memsize) { + alignedAddress = memory.truncateToNextPage(address + filesize); + memory.map(alignedAddress, memsize - filesize, read, write, exec); + } + } + } /** * Round the give value up so that it is at the beginning of the Modified: src/org/binarytranslator/generic/os/loader/image/ImageLoader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/image/ImageLoader.java 2007-04-13 18:40:22 UTC (rev 48) +++ src/org/binarytranslator/generic/os/loader/image/ImageLoader.java 2007-04-14 09:35:23 UTC (rev 49) @@ -113,7 +113,7 @@ int fileAndMemSize = (int)file.length() - 16; try { - ps.createSegment(file, 16, 0, fileAndMemSize, fileAndMemSize, true, true, true); + ps.memory.map(file, 16, 0, fileAndMemSize, true, true, true); } catch (MemoryMapException e) { e.printStackTrace(); Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-13 18:40:22 UTC (rev 48) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-14 09:35:23 UTC (rev 49) @@ -9,7 +9,6 @@ package org.binarytranslator.generic.os.process; import java.io.IOException; -import java.io.RandomAccessFile; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; @@ -18,7 +17,6 @@ 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.os.loader.Loader; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; @@ -98,66 +96,6 @@ } /** - * Create a segment - * - * @param RandomAccessFile - * file to read segment data from if file size != 0 - * @param offset - * file offset - * @param address - * location of segment - * @param filesize - * size of segment in file - * @param memsize - * size of segment in memory - * @param read - * is segment readable - * @param write - * is segment writable - * @param exec - * is segment executable - */ - public void createSegment(RandomAccessFile file, long offset, int address, - int filesize, int memsize, boolean read, boolean write, boolean exec) - throws MemoryMapException { - // Sanity check - if (memsize < filesize) { - throw new Error("Segment memory size (" + memsize - + ")less than file size (" + filesize + ")"); - } - // Are we mapping anything from a file? - if (filesize == 0) { - // No: map anonymously - memory.map(address, memsize, read, write, exec); - } else { - // align offset and address - int alignedAddress; - long alignedOffset; - int alignedFilesize; - if (memory.isPageAligned(address)) { - // memory and therefore offset should be aligned - alignedAddress = address; - alignedOffset = offset; - alignedFilesize = filesize; - } else { - // Address not aligned - alignedAddress = memory.truncateToPage(address); - int delta = address - alignedAddress; - // adjust offset and length too - alignedOffset = offset - delta; - alignedFilesize = filesize + delta; - } - memory.map(file, alignedOffset, alignedAddress, alignedFilesize, read, - write, exec); - // Do we need to map in some blank pages at the end of the segment? - if (filesize < memsize) { - alignedAddress = memory.truncateToNextPage(address + filesize); - memory.map(alignedAddress, memsize - filesize, read, write, exec); - } - } - } - - /** * Initialise the process space * * @param loader This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-13 18:40:21
|
Revision: 48 http://svn.sourceforge.net/pearcolator/?rev=48&view=rev Author: captain5050 Date: 2007-04-13 11:40:22 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Bad instruction tests Added Paths: ----------- tests/simple/ppc/bad_instruction tests/simple/ppc/bad_instruction.s tests/simple/x86/bad_instruction tests/simple/x86/bad_instruction.s Added: tests/simple/ppc/bad_instruction =================================================================== (Binary files differ) Property changes on: tests/simple/ppc/bad_instruction ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: tests/simple/ppc/bad_instruction.s =================================================================== --- tests/simple/ppc/bad_instruction.s (rev 0) +++ tests/simple/ppc/bad_instruction.s 2007-04-13 18:40:22 UTC (rev 48) @@ -0,0 +1,4 @@ +.text +.global _start +_start: + .word 0 Added: tests/simple/x86/bad_instruction =================================================================== (Binary files differ) Property changes on: tests/simple/x86/bad_instruction ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: tests/simple/x86/bad_instruction.s =================================================================== --- tests/simple/x86/bad_instruction.s (rev 0) +++ tests/simple/x86/bad_instruction.s 2007-04-13 18:40:22 UTC (rev 48) @@ -0,0 +1,4 @@ +.text +.global _start +_start: +.byte 0x0f, 0x0b This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-13 18:27:36
|
Revision: 47 http://svn.sourceforge.net/pearcolator/?rev=47&view=rev Author: michael_baer Date: 2007-04-13 11:27:36 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Moved management of translated caches from the process space to the DynamicTranslationController. Modified Paths: -------------- src/org/binarytranslator/generic/execution/DynamicTranslationController.java src/org/binarytranslator/generic/execution/GdbController.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_Trace.java Modified: src/org/binarytranslator/generic/execution/DynamicTranslationController.java =================================================================== --- src/org/binarytranslator/generic/execution/DynamicTranslationController.java 2007-04-13 17:54:29 UTC (rev 46) +++ src/org/binarytranslator/generic/execution/DynamicTranslationController.java 2007-04-13 18:27:36 UTC (rev 47) @@ -1,7 +1,11 @@ package org.binarytranslator.generic.execution; +import java.util.Hashtable; + +import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.vmInterface.DBT_Trace; import org.binarytranslator.vmInterface.DynamicCodeRunner; import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; @@ -12,8 +16,13 @@ */ public class DynamicTranslationController extends ExecutionController { + /** Caches pre-translated code and uses the starting address of the code on the subject machine as a key*/ + private final Hashtable<Integer, DBT_Trace> codeHash; + public DynamicTranslationController(ProcessSpace ps) { super(ps); + + codeHash = new Hashtable<Integer, DBT_Trace>(); } @Override @@ -21,18 +30,66 @@ // The current block of compiled code. VM_CodeArray code; - try { - // interpretFrom(); // Interpreter - experimental while (ps.finished == false) { // Get the compiled code - code = ps.getCodeForPC(ps.getCurrentInstructionAddress()); + code = getCodeForPC(ps.getCurrentInstructionAddress()); + // Run the compiled code. ps.setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, ps)); } } catch (BadInstructionException e) { System.out.println(e.toString()); } + } + + /** + * Returns an array of code starting at the given program counter. + * @param pc + * The program counter at which the code is supposed to start. + * @return + * An executable VM_CodeArray, which contains a trace starting at the given address. + */ + private VM_CodeArray getCodeForPC(int pc) { + DBT_Trace trace = codeHash.get(pc); + + if (trace == null) { + trace = translateCode(pc); + } + + return trace.getCurrentCompiledMethod().getEntryCodeArray(); } + /** + * Translates a piece of code starting at the given program counter value. + * + * @param pc + * The memory address of the first instruction that is translated + * into the code array. + * @return An code array containing target system assembly language, which has + * been translated from the subject executable. + */ + private DBT_Trace translateCode(int pc) { + + synchronized (ps) { + DBT_Trace trace = new DBT_Trace(ps, pc); + + if (DBT_Options.debugRuntime) { + report("Translating code for 0x" + Integer.toHexString(trace.pc)); + } + + // compile the given trace + trace.compile(); + + // store the compiled code in code hash + codeHash.put(trace.pc, trace); + + return trace; + } + } + + /** Outputs a debug message */ + private void report(String msg) { + System.out.println("Dynamic Translation Controller: " + msg); + } } Modified: src/org/binarytranslator/generic/execution/GdbController.java =================================================================== --- src/org/binarytranslator/generic/execution/GdbController.java 2007-04-13 17:54:29 UTC (rev 46) +++ src/org/binarytranslator/generic/execution/GdbController.java 2007-04-13 18:27:36 UTC (rev 47) @@ -181,6 +181,7 @@ /** * Main run loop */ + @Override public void run() { try { while (socket.isConnected()) { Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-13 17:54:29 UTC (rev 46) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-13 18:27:36 UTC (rev 47) @@ -10,7 +10,6 @@ import java.io.IOException; import java.io.RandomAccessFile; -import java.util.Hashtable; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; @@ -21,22 +20,15 @@ import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.os.loader.Loader; -import org.binarytranslator.vmInterface.DBT_Trace; -import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; -import org.jikesrvm.compilers.common.VM_CompiledMethod; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.vmmagic.pragma.Uninterruptible; - /** * A process space encapsulates a running process. This superclass contains non * operating and architecture specific details of the process. */ public abstract class ProcessSpace { - /* - * Runtime information - */ /** * A record of branches to guide translation @@ -44,29 +36,16 @@ public final BranchLogic branchInfo; /** - * A hashtable containing translated traces of code - */ - protected final Hashtable<Integer, VM_CodeArray> codeHash = new Hashtable<Integer, VM_CodeArray>(); - - /** * Has a system call been called to terminate the process */ public boolean finished = false; - /* - * Interface to memory - */ - /** * The memory for the process. As this is user mode code, it is a virtual * address space */ public Memory memory; - /* - * Utility functions - */ - /** * Debug information * @@ -80,10 +59,6 @@ } } - /* - * Methods - */ - /** * Create an optimizing compiler HIR code generator suitable for a particular * architecture @@ -121,7 +96,7 @@ } return result; } - + /** * Create a segment * @@ -202,43 +177,8 @@ } /** - * Constructor + * Record a branch instruction */ - public ProcessSpace(String[] args) throws IOException { - branchInfo = new BranchLogic(); - } - - /** - * Replace the compiled code for a trace (called by the adaptive system) - */ - public synchronized void replaceCompiledTrace(VM_CompiledMethod cm, - DBT_Trace trace) { - VM_CodeArray code = cm.getEntryCodeArray(); - codeHash.put(trace.pc, code); - } - - public synchronized VM_CodeArray getCodeForPC(int pc) { - VM_CodeArray code = (VM_CodeArray) codeHash.get(pc); - if (code == null) { - code = translateCode(new DBT_Trace(this, pc)); - } - return code; - } - - private VM_CodeArray translateCode(DBT_Trace trace) { - if (DBT_Options.debugRuntime) { - report("Translating code for 0x" + Integer.toHexString(trace.pc)); - } - trace.compile(); - VM_CompiledMethod cm = trace.getCurrentCompiledMethod(); - replaceCompiledTrace(cm, trace); - return cm.getEntryCodeArray(); - } - - /* - * - * /** Record a branch instruction - */ public void recordUncaughtBranch(int location, int destination, int code) { branchInfo.registerBranch(location, destination, code); } Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-13 17:54:29 UTC (rev 46) +++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-13 18:27:36 UTC (rev 47) @@ -18,6 +18,7 @@ import org.jikesrvm.classloader.VM_MemberReference; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_BytecodeStream; +import org.jikesrvm.runtime.VM_Magic; import org.jikesrvm.runtime.VM_Statics; import org.jikesrvm.runtime.VM_DynamicLink; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; @@ -190,7 +191,6 @@ */ public final synchronized void replaceCompiledMethod( VM_CompiledMethod compiledMethod) { - ps.replaceCompiledTrace(compiledMethod, this); // Grab version that is being replaced VM_CompiledMethod oldCompiledMethod = currentCompiledMethod; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-13 17:54:28
|
Revision: 46 http://svn.sourceforge.net/pearcolator/?rev=46&view=rev Author: captain5050 Date: 2007-04-13 10:54:29 -0700 (Fri, 13 Apr 2007) Log Message: ----------- X86 simple helloworld test Added Paths: ----------- tests/simple/x86/helloworld tests/simple/x86/helloworld.s Added: tests/simple/x86/helloworld =================================================================== (Binary files differ) Property changes on: tests/simple/x86/helloworld ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: tests/simple/x86/helloworld.s =================================================================== --- tests/simple/x86/helloworld.s (rev 0) +++ tests/simple/x86/helloworld.s 2007-04-13 17:54:29 UTC (rev 46) @@ -0,0 +1,27 @@ +.data # section declaration + +msg: + .string "Hello, world!\n" + len = . - msg # length of our dear string + +.text # section declaration + + # we must export the entry point to the ELF linker or + .global _start # loader. They conventionally recognize _start as their + # entry point. Use ld -e foo to override the default. + +_start: + +# write our string to stdout + + movl $len,%edx # third argument: message length + movl $msg,%ecx # second argument: pointer to message to write + movl $1,%ebx # first argument: file handle (stdout) + movl $4,%eax # system call number (sys_write) + int $0x80 # call kernel + +# and exit + + movl $0,%ebx # first argument: exit code + movl $1,%eax # system call number (sys_exit) + int $0x80 # call kernel This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-13 17:53:25
|
Revision: 45 http://svn.sourceforge.net/pearcolator/?rev=45&view=rev Author: captain5050 Date: 2007-04-13 10:53:27 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Organize naming a little better Added Paths: ----------- tests/simple/ppc/syscall_exit tests/simple/ppc/syscall_exit.s tests/simple/x86/syscall_exit tests/simple/x86/syscall_exit.s Removed Paths: ------------- tests/simple/ppc/ppc_exit tests/simple/ppc/ppc_exit.s tests/simple/x86/x86_exit tests/simple/x86/x86_exit.s Deleted: tests/simple/ppc/ppc_exit =================================================================== (Binary files differ) Deleted: tests/simple/ppc/ppc_exit.s =================================================================== --- tests/simple/ppc/ppc_exit.s 2007-04-13 17:50:21 UTC (rev 44) +++ tests/simple/ppc/ppc_exit.s 2007-04-13 17:53:27 UTC (rev 45) @@ -1,5 +0,0 @@ -.text -.global _start -_start: - li 0,1 - sc Copied: tests/simple/ppc/syscall_exit (from rev 42, tests/simple/ppc/ppc_exit) =================================================================== (Binary files differ) Copied: tests/simple/ppc/syscall_exit.s (from rev 42, tests/simple/ppc/ppc_exit.s) =================================================================== --- tests/simple/ppc/syscall_exit.s (rev 0) +++ tests/simple/ppc/syscall_exit.s 2007-04-13 17:53:27 UTC (rev 45) @@ -0,0 +1,5 @@ +.text +.global _start +_start: + li 0,1 + sc Copied: tests/simple/x86/syscall_exit (from rev 41, tests/simple/x86/x86_exit) =================================================================== (Binary files differ) Copied: tests/simple/x86/syscall_exit.s (from rev 41, tests/simple/x86/x86_exit.s) =================================================================== --- tests/simple/x86/syscall_exit.s (rev 0) +++ tests/simple/x86/syscall_exit.s 2007-04-13 17:53:27 UTC (rev 45) @@ -0,0 +1,5 @@ +.text +.global _start +_start: + mov $1, %eax + int $0x80 Deleted: tests/simple/x86/x86_exit =================================================================== (Binary files differ) Deleted: tests/simple/x86/x86_exit.s =================================================================== --- tests/simple/x86/x86_exit.s 2007-04-13 17:50:21 UTC (rev 44) +++ tests/simple/x86/x86_exit.s 2007-04-13 17:53:27 UTC (rev 45) @@ -1,5 +0,0 @@ -.text -.global _start -_start: - mov $1, %eax - int $0x80 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-13 17:50:20
|
Revision: 44 http://svn.sourceforge.net/pearcolator/?rev=44&view=rev Author: captain5050 Date: 2007-04-13 10:50:21 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Simple helloworld test Added Paths: ----------- tests/simple/ppc/helloworld tests/simple/ppc/helloworld.s Added: tests/simple/ppc/helloworld =================================================================== (Binary files differ) Property changes on: tests/simple/ppc/helloworld ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: tests/simple/ppc/helloworld.s =================================================================== --- tests/simple/ppc/helloworld.s (rev 0) +++ tests/simple/ppc/helloworld.s 2007-04-13 17:50:21 UTC (rev 44) @@ -0,0 +1,26 @@ +.data # section declaration - variables only + +msg: + .string "Hello, world!\n" + len = . - msg # length of our dear string + +.text # section declaration - begin code + + .global _start +_start: + +# write our string to stdout + + li 0,4 # syscall number (sys_write) + li 3,1 # first argument: file descriptor (stdout) + # second argument: pointer to message to write + lis 4,msg@ha # load top 16 bits of &msg + addi 4,4,msg@l # load bottom 16 bits + li 5,len # third argument: message length + sc # call kernel + +# and exit + + li 0,1 # syscall number (sys_exit) + li 3,1 # first argument: exit code + sc # call kernel This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-13 17:18:18
|
Revision: 43 http://svn.sourceforge.net/pearcolator/?rev=43&view=rev Author: captain5050 Date: 2007-04-13 10:18:18 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Fix to constructor enabling simple tests to run Modified Paths: -------------- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 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 17:04:24 UTC (rev 42) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-13 17:18:18 UTC (rev 43) @@ -52,8 +52,8 @@ * Constructor */ public PPC_LinuxProcessSpace(Loader loader) { + syscallArgs = new PPC_LinuxSyscallArgumentIterator(this); syscalls = new PPC_LinuxSystemCalls(this); - syscallArgs = new PPC_LinuxSyscallArgumentIterator(this); } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-13 17:04:28
|
Revision: 42 http://svn.sourceforge.net/pearcolator/?rev=42&view=rev Author: captain5050 Date: 2007-04-13 10:04:24 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Simple ppc exit test Added Paths: ----------- tests/simple/ppc/ tests/simple/ppc/ppc_exit tests/simple/ppc/ppc_exit.s Added: tests/simple/ppc/ppc_exit =================================================================== (Binary files differ) Property changes on: tests/simple/ppc/ppc_exit ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: tests/simple/ppc/ppc_exit.s =================================================================== --- tests/simple/ppc/ppc_exit.s (rev 0) +++ tests/simple/ppc/ppc_exit.s 2007-04-13 17:04:24 UTC (rev 42) @@ -0,0 +1,5 @@ +.text +.global _start +_start: + li 0,1 + sc This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-13 16:55:17
|
Revision: 41 http://svn.sourceforge.net/pearcolator/?rev=41&view=rev Author: captain5050 Date: 2007-04-13 09:55:18 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Simple x86 test Added Paths: ----------- tests/ tests/simple/ tests/simple/x86/ tests/simple/x86/x86_exit tests/simple/x86/x86_exit.s Added: tests/simple/x86/x86_exit =================================================================== (Binary files differ) Property changes on: tests/simple/x86/x86_exit ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: tests/simple/x86/x86_exit.s =================================================================== --- tests/simple/x86/x86_exit.s (rev 0) +++ tests/simple/x86/x86_exit.s 2007-04-13 16:55:18 UTC (rev 41) @@ -0,0 +1,5 @@ +.text +.global _start +_start: + mov $1, %eax + int $0x80 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-13 16:51:40
|
Revision: 40 http://svn.sourceforge.net/pearcolator/?rev=40&view=rev Author: captain5050 Date: 2007-04-13 09:51:40 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Reverse logic for GDB stub Modified Paths: -------------- src/org/binarytranslator/Main.java Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-04-13 16:23:27 UTC (rev 39) +++ src/org/binarytranslator/Main.java 2007-04-13 16:51:40 UTC (rev 40) @@ -87,11 +87,12 @@ //Create an execution controller and pass execution on to it ExecutionController controller; - if (DBT_Options.gdbStub == false) { + if (DBT_Options.gdbStub) { controller = new GdbController(DBT_Options.gdbStubPort, ps); } - else + else { controller = new DynamicTranslationController(ps); + } controller.run(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-13 16:23:25
|
Revision: 39 http://svn.sourceforge.net/pearcolator/?rev=39&view=rev Author: michael_baer Date: 2007-04-13 09:23:27 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Switched from vectors to ArrayLists. Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-04-13 15:01:40 UTC (rev 38) +++ src/org/binarytranslator/DBT_Options.java 2007-04-13 16:23:27 UTC (rev 39) @@ -8,9 +8,9 @@ */ package org.binarytranslator; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; -import java.util.Vector; import java.util.Map.Entry; /** @@ -175,7 +175,7 @@ public static void parseArguments(String[] args) { try { - Vector<String> remainingArguments = new Vector<String>(); + ArrayList<String> remainingArguments = new ArrayList<String>(); ArgumentParser.parse(args, dbtArguments, remainingArguments); //did the user give an executable to execute? @@ -260,7 +260,7 @@ /** A list of remaining arguments. See the class documentation to learn about the difference * between Key-Value and remaining arguments. */ - protected final Vector<String> remainingArguments; + protected final ArrayList<String> remainingArguments; /** * Parses command line arguments. @@ -269,11 +269,11 @@ * @param keyValueArguments * Parsed Key-Value argument pairs are stored within this map. * @param remainingArguments - * Remaining arguments are being stored into this vector. + * Remaining arguments are being stored into this array list. * @throws ParseException * A ArgumentParser.ParseException is thrown in case arguments are not properly formatted and could not be parsed. */ - public static void parse(String[] args, Map<String, String> keyValueArguments, Vector<String> remainingArguments) + public static void parse(String[] args, Map<String, String> keyValueArguments, ArrayList<String> remainingArguments) throws ParseException { ArgumentParser parser = new ArgumentParser(keyValueArguments, remainingArguments); @@ -285,9 +285,9 @@ * @param arguments * Parsed Key-Value argument pairs are stored within this map. * @param remainingArguments - * Remaining arguments are being stored into this vector. + * Remaining arguments are being stored into this array list. */ - private ArgumentParser(Map<String, String> arguments, Vector<String> remainingArguments) { + private ArgumentParser(Map<String, String> arguments, ArrayList<String> remainingArguments) { this.arguments = arguments; this.remainingArguments = remainingArguments; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-13 15:01:40
|
Revision: 38 http://svn.sourceforge.net/pearcolator/?rev=38&view=rev Author: michael_baer Date: 2007-04-13 08:01:40 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Added Support for half-word and signed data transfers. Added initial version of an ARM instruction decoder. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java Added: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-13 15:01:40 UTC (rev 38) @@ -0,0 +1,211 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.DBT; + +/** + * This class decodes an ARM instruction and uses a user-supplied ARM_InstructionFactory to create a class + * that represents the given instruction. + * + * I'm not happy with the structure of this module, but looking at the opcode map of the ARM, it's hard to + * provide a structured way of decoding primary and secondary opcodes efficiently. This class first looks at + * bits 25-27 and tries to decode as much from these as possible, using the decode_xxx functions. However, + * sometimes bits have to be checked in quite a non-systematic fashion to really catch all the cases that + * have been squeezed into newer ARM architectures. + * + * @author Michael Baer + * + */ +public class ARM_InstructionDecoder { + + /** + * Checks if a bit is set within a word. + * @param word + * The word that is being examined. + * @param bit + * The number of the bit that is to be checked, starting from zero. + * @return + * True, if the given bit is set within the word, false otherwise. + */ + private static final boolean getBit(int word, int bit) { + if (DBT.VerifyAssertions) + DBT._assert(bit >= 0 && bit <= 31); + return (word & (1 << bit)) != 0; + } + + public static <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + if (getBit(instr, 27)) { + return decode_1xx(instr, factory); + } + else { + return decode_0xx(instr, factory); + } + } + + private static <T> T decode_0xx(int instr, ARM_InstructionFactory<T> factory) { + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } + + if (getBit(instr, 26)) { + //opcode: 01 + if (getBit(instr, 25) && getBit(instr, 4)) + return factory.createUndefinedInstruction(instr); + else + return factory.createSingleDataTransfer(instr); + } + else { + //opcode: 00 + return decode_00x(instr, factory); + } + } + + private static <T> T decode_1xx(int instr, ARM_InstructionFactory<T> factory) { + if (getBit(instr, 26)) { + //opcode: 11 + return decode_11x( instr, factory); + } + else { + //opcode: 10 + return decode_10x(instr, factory); + } + } + + private static <T> T decode_00x(int instr, ARM_InstructionFactory<T> factory) { + if (getBit(instr, 25)) + return decode_001(instr, factory); + else + return decode_000(instr, factory); + } + + private static <T> T decode_10x(int instr, ARM_InstructionFactory<T> factory) { + if (getBit(instr, 25)) { + //opcode: 101 + if ((instr & 0xF0000000) == 0xF0000000) + return factory.createBranchExchange(instr); + else + return factory.createBranch(instr); + } + else { + //opcode: 100 + if ((instr & 0xF0000000) == 0xF0000000) + return factory.createUndefinedInstruction(instr); + else + return factory.createBlockDataTransfer(instr); + } + } + + private static <T> T decode_000(int instr, ARM_InstructionFactory<T> factory) { + //opcode: 000 + if (getBit(instr, 24) && !getBit(instr, 23) && !getBit(instr, 20)) { + //opcode: 00010xx0 - those are the new instructions, which the ARM ref. manual calls "misc. instructions" + return decode_00010xx0(instr, factory); + } + else { + if (getBit(instr, 4) == false || getBit(instr, 7) == false) + return factory.createDataProcessing(instr); + + return decode_multiplies_extra_load_stores(instr, factory); + } + } + + private static <T> T decode_001(int instr, ARM_InstructionFactory<T> factory) { + //opcode: 001 + if (!getBit(instr, 24) || getBit(instr, 23) || getBit(instr, 20)) { + return factory.createDataProcessing(instr); + } + + if (getBit(instr, 21)) + return factory.createMoveToStatusRegister(instr); + else + return factory.createUndefinedInstruction(instr); + } + + private static <T> T decode_11x(int instr, ARM_InstructionFactory<T> factory) { + + if (getBit(instr, 25) == false) { + //opcode: 110 + return factory.createCoprocessorDataTransfer(instr); + } + + //opcode: 111 + if (getBit(instr, 24)) { + //opcode: 1111 + if ((instr & 0xF0000000) == 0xF0000000) + return factory.createUndefinedInstruction(instr); + else + return factory.createSoftwareInterrupt(instr); + } + else { + //opcode: 1110 + if (getBit(instr, 4)) { + return factory.createCoprocessorDataTransfer(instr); + } + else { + return factory.createCoprocessorRegisterTransfer(instr); + } + } + } + /** Decodes instructions with the opcode 00010xx0 - those are the new instructions, which + * the ARM ref. manual calls "misc. instructions". + * + * @see Page A3-4 in the ARM Reference Manual (ARM DDI 0100 E) / 2000 + */ + private static <T> T decode_00010xx0(int instr, ARM_InstructionFactory<T> factory) { + // + if (getBit(instr, 6) || getBit(instr, 7)) { + //enhanced DSP multiplications, DSP add/subtracts and software breakpoints + //we might want to support these in the future, so when in debug mode, catch if any program actually uses them + if (DBT.VerifyAssertions) DBT._assert(false); + return factory.createUndefinedInstruction(instr); + } + else { + //bit 6 and 7 are clear + if (getBit(instr, 4)) { + if (getBit(instr, 22)) + return factory.createCountLeadingZeros(instr); + else + return factory.createBranchExchange(instr); + } + else { + if (getBit(instr, 21)) + return factory.createMoveToStatusRegister(instr); + else + return factory.createMoveFromStatusRegister(instr); + } + } + } + + /** This might appear even more weird, but I didn't design the ARM ISA. This function decodes + * all the operations defined on p. A3-3 in the ARM reference manual from 2000 (ARM DDI 0100 E). + * + * @see ARM Reference Manual (ARM DDI 0100 E) / 2000 + */ + private static <T> T decode_multiplies_extra_load_stores(int instr, ARM_InstructionFactory<T> factory) { + //Here, we already know that bits 4 and 7 are set, while bit 25-27 are clear + if (getBit(instr, 6)) { + //load/store signed half-word or two words + if (getBit(instr, 20)) + return factory.createSingleDataTransfer(instr); + else + return factory.createUndefinedInstruction(instr); //two words immediate offset + } + else { + if (getBit(instr, 5)) { + //load/store half-word + return factory.createSingleDataTransfer(instr); + } + else { + //Multiply, multiply long or Swap + if (getBit(instr, 24)) { + return factory.createSwap(instr); + } + else { + if (getBit(instr, 23)) + return factory.createLongMultiply(instr); + else + return factory.createIntMultiply(instr); + } + } + } + } +} Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-13 11:16:14 UTC (rev 37) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-13 15:01:40 UTC (rev 38) @@ -2,6 +2,19 @@ import org.binarytranslator.DBT; +/** + * 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. + * + * Application might derive from these decoders to implement instruction-specific functionality. + * Then, implement a version of the generic {@link ARM_InstructionFactory} interface, which returns + * your derived classes and pass it to the {@link ARM_InstructionDecoder} to let it create instances of + * your class from binary instructions. + * + * @author Michael Baer + * + */ public class ARM_InstructionDecoders { /** @@ -13,7 +26,7 @@ * @return * True, if the given bit is set within the word, false otherwise. */ - public static final boolean getBit(int word, int bit) { + private static final boolean getBit(int word, int bit) { if (DBT.VerifyAssertions) DBT._assert(bit >= 0 && bit <= 31); return (word & (1 << bit)) != 0; @@ -31,7 +44,7 @@ * @return * A zero-based version of the bit sequence. */ - public static final int getBits(int word, int from, int to) { + private static final int getBits(int word, int from, int to) { if (DBT.VerifyAssertions) DBT._assert(from < to && from >= 0 && to <= 31); return (word & ((1 << (to + 1)) - 1)) >> from; @@ -136,17 +149,17 @@ } /** Returns true, if the condition codes shall be updated by the result of this operation. */ - public boolean updateConditionCodes() { + public final boolean updateConditionCodes() { return updateConditionCodes; } /** Returns true, if this is the accumulate version of the instruction. */ - public boolean accumulate() { + public final boolean accumulate() { return accumulate; } /** Returns the register number of the Rs operand register. */ - public byte getRs() { + public final byte getRs() { return Rs; } } @@ -172,7 +185,7 @@ } /** Returns the coprocessor that shall process this instruction */ - public byte getCoprocessorNumber() { + public final byte getCoprocessorNumber() { return cpNum; } } @@ -180,6 +193,7 @@ /** Represents an operand, which might either be an immediate value, a register (shifted by an immediate) or a register shifted by a register. */ public abstract static class OperandWrapper { + /** Describes the type of the operand. */ public enum Type { Immediate, Register, @@ -187,6 +201,7 @@ RegisterShiftedRegister, } + /** Describes a type of shift, in case the operand is supposed to be shifted. */ public enum ShiftType { LogicalLeft, LogicalRight, @@ -236,6 +251,7 @@ } } + /** Returns the type of the operand that this class is actually representing. */ public abstract Type getType(); /** Returns the immediate, which is the 2nd operand of this instruction. Make sure that hasImmediate is true before calling this. */ @@ -263,8 +279,10 @@ throw new RuntimeException("Invalid call on an operand wrapper."); } + /** Represents an immediate value operand. */ protected static class ImmediateOperand extends OperandWrapper { + /** @see #getImmediate() */ protected final int immediate; protected ImmediateOperand(int immediate) { @@ -282,8 +300,10 @@ } } + /** Represents a register operand. */ protected static class RegisterOperand extends OperandWrapper { + /** @see #getRegister() */ protected final byte register; protected RegisterOperand(byte register) { @@ -301,9 +321,13 @@ } } + /** Represents an operand, which is a register shifted by an immediate value. */ protected static class RegisterShiftImmediateOperand extends RegisterOperand { + /** @see #getShiftType() */ protected final ShiftType shiftType; + + /** @see #getShiftAmount() */ protected final byte shiftAmount; protected RegisterShiftImmediateOperand(byte register, ShiftType shift, byte shiftAmount) { @@ -321,11 +345,20 @@ public byte getShiftAmount() { return shiftAmount; } + + @Override + public ShiftType getShiftType() { + return shiftType; + } } + /** Returns an operand, which is a register shifted by a register. */ protected static class RegisterShiftRegisterOperand extends RegisterOperand { + /** @see #getShiftType() */ protected final ShiftType shiftType; + + /** @see #getShiftingRegister() */ protected final byte shiftingRegister; protected RegisterShiftRegisterOperand(byte shiftedRegister, ShiftType shift, byte shiftingRegister) { @@ -343,11 +376,16 @@ public byte getShiftingRegister() { return shiftingRegister; } + + @Override + public ShiftType getShiftType() { + return shiftType; + } } } /** Represents a Data Processing instruction. */ - public final static class DataProcessing extends + public static class DataProcessing extends TwoRegistersTemplate { /** @see #hasSetConditionCodes() */ @@ -372,25 +410,20 @@ } /** Returns the opcode, that specifies the data processing operation, which is to be performed. */ - public byte getOpcode() { + public final byte getOpcode() { return opcode; } /** Returns true if the condition codes shall be set by this operation, false otherwise. */ - public boolean updateConditionCodes() { + public final boolean updateConditionCodes() { return updateConditionCodes; } /** Returns the 2nd operand of this data processing instruction. */ - public OperandWrapper getOperand2() { + public final OperandWrapper getOperand2() { return operand2; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 26, 27) == 0; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -398,17 +431,26 @@ } /** Represents a LDR/SDR instruction. */ - public final static class SingleDataTransfer extends + public static class SingleDataTransfer extends TwoRegistersTemplate { + + public enum TransferSize { + Byte, + HalfWord, + Word + } /** @see #preIndexing() */ protected final boolean preIndexing; /** @see #positiveOffset() */ protected final boolean positiveOffset; + + /** @see #signExtend() */ + protected final boolean signExtend; - /** @see #byteTransfer() */ - protected final boolean byteTransfer; + /** @see #getSize() */ + protected final TransferSize size; /** @see #writeBack() */ protected final boolean writeBack; @@ -416,58 +458,88 @@ /** @see #isLoad() */ protected final boolean isLoad; - /** @see #getOperand2() */ - protected final OperandWrapper operand2; + /** @see #getOffset() */ + protected final OperandWrapper offset; public SingleDataTransfer(int instr) { super(instr); preIndexing = getBit(instr, 24); positiveOffset = getBit(instr, 23); - byteTransfer = getBit(instr, 22); writeBack = getBit(instr, 21); isLoad = getBit(instr, 20); - if (getBit(instr, 25)) - operand2 = OperandWrapper.createImmediate(instr & 0xFF); - else - operand2 = OperandWrapper.decodeShiftedRegister(instr); + if (getBit(instr, 26)) { + //this is an unsigned byte or word transfer + signExtend = false; + + if (getBit(instr, 22)) + size = TransferSize.Byte; + else + size = TransferSize.Word; + + if (getBit(instr, 25)) + offset = OperandWrapper.createImmediate(instr & 0xFF); + else + offset = OperandWrapper.decodeShiftedRegister(instr); + } + else { + //this is a byte or half-word transfer + if (getBit(instr, 5)) + size = TransferSize.HalfWord; + else + size = TransferSize.Byte; + + signExtend = getBit(instr, 6); + + if (getBit(instr, 22)) { + //immediate offset + offset = OperandWrapper.createImmediate((getBits(instr, 8, 11) << 4) | (instr & 0xF)); + } + else { + //register offset + offset = OperandWrapper.createRegister((byte)(instr & 0xF)); + } + + //The decoder should make sure that we're never being called with this combination + if (DBT.VerifyAssertions) DBT._assert(!signExtend || isLoad); + } } + + /** Returns true, if the loaded/stored value shall be signed-extended.*/ + public final boolean signExtend() { + return signExtend; + } - /** Returns true, if a single byte is to be transfered or false if an int shall be transfered. */ - public boolean isByteTransfer() { - return byteTransfer; + /** Returns the number of bytes that have to be transferred. */ + public final TransferSize getSize() { + return size; } /** True if this is a LDM instruction, false if it is a STM instruction. */ - public boolean isLoad() { + public final boolean isLoad() { return isLoad; } /** Returns true, if the offset from the base register (see {@link #getRn()} is positive, false if it is negative. */ - public boolean positiveOffset() { + public final boolean positiveOffset() { return positiveOffset; } /** True if the base register shall be changed before the transfer, otherwise changed it after the transfer. */ - public boolean preIndexing() { + public final boolean preIndexing() { return preIndexing; } /** True if the incremented base register shall be persisted after this instruction. */ - public boolean writeBack() { + public final boolean writeBack() { return writeBack; } - /** Returns the 2nd operand of this data processing instruction. */ - public OperandWrapper getOperand2() { - return operand2; + /** Returns the offset operand for this data processing instruction. */ + public final OperandWrapper getOffset() { + return offset; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 26, 27) == 1; - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -476,17 +548,12 @@ } /** Represents a normal (not long) multiply instruction. */ - public final static class Multiply extends MultiplyTemplate { + public static class IntMultiply extends MultiplyTemplate { - protected Multiply(int instr) { + protected IntMultiply(int instr) { super(instr); } - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 22, 27) == 0 && getBits(instr, 4, 7) == 9; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -494,7 +561,7 @@ } /** Represents a long multiply instruction. */ - public final static class LongMultiply extends MultiplyTemplate { + public static class LongMultiply extends MultiplyTemplate { /** @see #isUnsigned() */ protected final boolean unsigned; @@ -506,25 +573,20 @@ } /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ - public byte getRdHigh() { + public final byte getRdHigh() { return Rd; } /** Long multiplication stores its result in two registers. This function gets the register which receives the low int. */ - public byte getRdLow() { + public final byte getRdLow() { return Rn; } /** Returns true, if this is an unsigned multiplication or false if it is a signed multiplication. */ - public boolean isUnsigned() { + public final boolean isUnsigned() { return unsigned; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 23, 27) == 1 && getBits(instr, 4, 7) == 9; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -532,7 +594,7 @@ } /** Represents a SWP/SWPB instruction. */ - public final static class Swap extends ThreeRegistersTemplate { + public static class Swap extends ThreeRegistersTemplate { /** @see #swapByte() */ protected final boolean swapByte; @@ -543,16 +605,10 @@ } /** Returns true, if a byte shall be swapped or false, if an int (32 bit) shall be swapped. */ - public boolean swapByte() { + public final boolean swapByte() { return swapByte; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 23, 27) == 2 && getBits(instr, 20, 21) == 0 - && getBits(instr, 4, 11) == 9; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -560,7 +616,7 @@ } /** Represents a LDM/STM instruction. */ - public final static class BlockDataTransfer extends Basic { + public static class BlockDataTransfer extends Basic { /** @see #preIndexing() */ protected final boolean preIndexing; @@ -595,13 +651,8 @@ registerList = instr; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 25, 27) == 4; - } - /** @return True if register r should be transferred using this instruction. */ - public boolean transferRegister(int r) { + public final boolean transferRegister(int r) { if (DBT.VerifyAssertions) DBT._assert(r >= 0 && r < 16); @@ -609,32 +660,32 @@ } /** True if the base register shall be changed before each single transfer, otherwise changed it after each transfer. */ - public boolean preIndexing() { + public final boolean preIndexing() { return preIndexing; } /** True if the base register shall be incremented, false if it should be decremented. */ - public boolean incrementBase() { + public final boolean incrementBase() { return incrementBase; } /** Force user mode during this instruction? */ - public boolean forceUser() { + public final boolean forceUser() { return forceUser; } /** True if the incremented base register shall be persisted after this instruction. */ - public boolean writeBack() { + public final boolean writeBack() { return writeBack; } /** True if this is a LDM instruction, false if it is a STM instruction. */ - public boolean isLoad() { + public final boolean isLoad() { return isLoad; } /** The number of the register which will provides the base address for this LDM/STM instruction. */ - public byte getBaseRegister() { + public final byte getBaseRegister() { return baseRegister; } @@ -645,7 +696,7 @@ } /** Represents a SWI instruction*/ - public final static class SoftwareInterrupt extends Basic { + public static class SoftwareInterrupt extends Basic { /** @see #getInterruptNumber() */ protected final int interruptNumber; @@ -656,15 +707,10 @@ } /** Returns the interrupt that is being called. The value is taken from the instruction's comment field. */ - public int getInterruptNumber() { + public final int getInterruptNumber() { return interruptNumber; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 24, 27) == 15; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -672,7 +718,7 @@ } /** Represents a branch instruction. */ - public final static class Branch extends Basic { + public static class Branch extends Basic { /** @see #isBranchAndLink() */ protected final boolean link; @@ -687,20 +733,15 @@ } /** Should the current PC be put into the lr? */ - public boolean isBranchAndLink() { + public final boolean isBranchAndLink() { return link; } /** The offset of the target address to the PC */ - public int getOffset() { + public final int getOffset() { return offset; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 25, 27) == 5; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -708,7 +749,7 @@ } /** Represents a BX instruction set */ - public final static class BranchExchange extends Basic { + public static class BranchExchange extends Basic { /** @see #getRn() */ protected final OperandWrapper target; @@ -739,16 +780,10 @@ } /** Returns, whether the return address for this jump shall be put into the lr. */ - public boolean link() { + public final boolean link() { return link; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 25, 31) == 0x7D // BLX(1) - || (getBits(instr, 20, 27) == 0x12 && getBits(instr, 6, 7) == 0); //BLX(2) && BX - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -756,7 +791,7 @@ } /** Represents a LDC/STC instruction. */ - public static final class CoprocessorDataTransfer extends CoprocessorTemplate { + public static class CoprocessorDataTransfer extends CoprocessorTemplate { /** @see #getOffset() */ protected final int offset; @@ -788,44 +823,39 @@ } /** Returns the number of the register, which contains the base address for this data transfer.*/ - public byte getBaseRegister() { + public final byte getBaseRegister() { return Rn; } /** Returns the transfer register on the coprocessor. */ - public byte getCoprocessorRegister() { + public final byte getCoprocessorRegister() { return Rd; } /** True if this is a LDC instruction, false if it is a STC instruction. */ - public boolean isLoad() { + public final boolean isLoad() { return isLoad; } /** Returns the offset that should be added to the base register. Note that the offset may be negative. */ - public int getOffset() { + public final int getOffset() { return offset; } /** True if the changed base register shall be persisted after this instruction. */ - public boolean writeBack() { + public final boolean writeBack() { return writeBack; } /** True if the base register shall be changed before the transfer, otherwise changed it after the transfer. */ - public boolean preIndexing() { + public final boolean preIndexing() { return preIndexing; } /** Returns true, if the flag which indicates a large transfer is set. The meaning of "large transfer" is dependend on the coprocessor.*/ - public boolean largeTransfer() { + public final boolean largeTransfer() { return largeTransfer; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 25, 27) == 6; - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -834,7 +864,7 @@ } /** Represents a CDP instruction. */ - public final static class CoprocessorDataProcessing extends CoprocessorTemplate { + public static class CoprocessorDataProcessing extends CoprocessorTemplate { /** @see #getOpcode() */ protected final byte opcode; @@ -854,34 +884,29 @@ } /** Returns the destination register of this operation. This register is a coprocessor register. */ - public byte getCoprocessorRd() { + public final byte getCoprocessorRd() { return Rd; } /** Returns the first operand register of this operation. This register is a coprocessor register. */ - public byte getCoprocessorRn() { + public final byte getCoprocessorRn() { return Rn; } /** Returns the second operand register of this operation. This register is a coprocessor register. */ - public byte getCoprocessorRm() { + public final byte getCoprocessorRm() { return cpRm; } /** The instruction contains three bits that may be used to control the details of the operation. This info is only of significance to the coprocessor. */ - public byte getCoprocessorInfo() { + public final byte getCoprocessorInfo() { return cpInfo; } /** Returns the opcode, that identifies the operation that shall be performed on the coprocessor. This vlaue is only of significance to the coprocessor. */ - public byte getOpcode() { + public final byte getOpcode() { return opcode; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 24, 27) == 14 && !getBit(instr, 4); - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -890,7 +915,7 @@ } /** Represents a MRC/MCR instruction. */ - public final static class CoprocessorRegisterTransfer extends CoprocessorTemplate { + public static class CoprocessorRegisterTransfer extends CoprocessorTemplate { /** @see #getOpcode() */ protected final byte opcode; @@ -914,39 +939,34 @@ } /** Returns true if this operation is a load from a coprocessor or false if it is a store to coprocessor. */ - public boolean isLoadFromCP() { + public final boolean isLoadFromCP() { return isLoad; } /** Returns the destination register of this operation.*/ - public byte getRd() { + public final byte getRd() { return Rd; } /** Returns the first operand register of this operation. This register is a coprocessor register. */ - public byte getCoprocessorRn() { + public final byte getCoprocessorRn() { return Rn; } /** Returns the second operand register of this operation. This register is a coprocessor register. */ - public byte getCoprocessorRm() { + public final byte getCoprocessorRm() { return cpRm; } /** The instruction contains three bits that may be used to control the details of the operation. This info is only of significance to the coprocessor. */ - public byte getCoprocessorInfo() { + public final byte getCoprocessorInfo() { return cpInfo; } /** Returns the opcode, that identifies the operation that shall be performed on the coprocessor. This vlaue is only of significance to the coprocessor. */ - public byte getOpcode() { + public final byte getOpcode() { return opcode; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 24, 27) == 14 && getBit(instr, 4); - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -955,7 +975,7 @@ } /** Represents a MRS instruction. */ - public final static class TransferFromStatusRegister extends Basic { + public static class MoveFromStatusRegister extends Basic { /** @see #getRd() */ protected final byte Rd; @@ -963,7 +983,7 @@ /** @see #transferSavedPSR() */ protected final boolean transferSavedPSR; - public TransferFromStatusRegister(int instr) { + public MoveFromStatusRegister(int instr) { super(instr); Rd = (byte) getBits(instr, 12, 15); @@ -971,19 +991,14 @@ } /** Returns the number of the destination register. */ - public byte getRd() { + public final byte getRd() { return Rd; } /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ - public boolean transferSavedPSR() { + public final boolean transferSavedPSR() { return transferSavedPSR; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 23, 27) == 2 && getBits(instr, 16, 21) == 0 && (instr & 0xFFF) == 0; - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -992,7 +1007,7 @@ } /** Represents a MSR instruction. */ - public final static class TransferToStatusRegister extends Basic { + public static class MoveToStatusRegister extends Basic { /** @see #transferControlField() */ protected final boolean transferControl; @@ -1012,7 +1027,7 @@ /** @see #getSourceOperand() */ protected final OperandWrapper sourceOperand; - public TransferToStatusRegister(int instr) { + public MoveToStatusRegister(int instr) { super(instr); transferControl = getBit(instr, 16); @@ -1029,39 +1044,34 @@ } /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ - public boolean transferSavedPSR() { + public final boolean transferSavedPSR() { return transferSavedPSR; } /** Returns true if the control field of the PSR shall be overwritten. */ - public boolean transferControlField() { + public final boolean transferControlField() { return transferControl; } /** Returns true if the extension field of the PSR shall be overwritten. */ - public boolean transferExtensionField() { + public final boolean transferExtensionField() { return transferExtension; } /** Returns true if the status field of the PSR shall be overwritten. */ - public boolean transferStatusField() { + public final boolean transferStatusField() { return transferStatus; } /** Returns true if the flag field of the PSR shall be overwritten. */ - public boolean transferFlagField() { + public final boolean transferFlagField() { return transferFlags; } /** Returns the operand, which is to be transfered into the status register. */ - public OperandWrapper getSourceOperand() { + public final OperandWrapper getSourceOperand() { return sourceOperand; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 26, 27) == 0 && getBits(instr, 23, 24) == 2 && getBits(instr, 12, 15) == 0; - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -1070,7 +1080,7 @@ } /** Represents a CLZ instruction. */ - public final static class CountLeadingZeros extends Basic { + public static class CountLeadingZeros extends Basic { /** @see #getRm() */ protected final byte Rm; @@ -1086,19 +1096,14 @@ } /** Returns the source register for this operation. */ - public byte getRm() { + public final byte getRm() { return Rm; } /** Returns the destination register for this operation. */ - public byte getRd() { + public final byte getRd() { return Rd; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 16, 27) == 0x16F && getBits(instr, 4, 11) == 0xF1; - } @Override public void visit(ARM_InstructionVisitor visitor) { Added: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java 2007-04-13 15:01:40 UTC (rev 38) @@ -0,0 +1,20 @@ +package org.binarytranslator.arch.arm.decoder; + +public interface ARM_InstructionFactory<T> { + T createDataProcessing(int instr); + T createSingleDataTransfer(int instr); + T createBlockDataTransfer(int instr); + T createIntMultiply(int instr); + T createLongMultiply(int instr); + T createSwap(int instr); + T createSoftwareInterrupt(int instr); + T createBranch(int instr); + T createBranchExchange(int instr); + T createCoprocessorDataTransfer(int instr); + T createCoprocessorDataProcessing(int instr); + T createCoprocessorRegisterTransfer(int instr); + T createMoveFromStatusRegister(int instr); + T createMoveToStatusRegister(int instr); + T createCountLeadingZeros(int instr); + T createUndefinedInstruction(int instr); +} Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-13 11:16:14 UTC (rev 37) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-13 15:01:40 UTC (rev 38) @@ -1,27 +1,13 @@ package org.binarytranslator.arch.arm.decoder; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.BlockDataTransfer; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Branch; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.BranchExchange; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorDataProcessing; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorDataTransfer; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorRegisterTransfer; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CountLeadingZeros; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.DataProcessing; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.LongMultiply; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Multiply; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.SingleDataTransfer; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.SoftwareInterrupt; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Swap; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.TransferFromStatusRegister; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.TransferToStatusRegister; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.*; /** An interface that supports iterating over ARM instructions using the visitor pattern. */ public interface ARM_InstructionVisitor { void visit(DataProcessing processing); void visit(SingleDataTransfer transfer); - void visit(Multiply multiply); + void visit(IntMultiply multiply); void visit(LongMultiply multiply); void visit(Swap swap); void visit(BlockDataTransfer transfer); @@ -31,7 +17,7 @@ void visit(CoprocessorDataTransfer transfer); void visit(CoprocessorDataProcessing processing); void visit(CoprocessorRegisterTransfer transfer); - void visit(TransferFromStatusRegister register); - void visit(TransferToStatusRegister register); + void visit(MoveFromStatusRegister register); + void visit(MoveToStatusRegister register); void visit(CountLeadingZeros zeros); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
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. |
From: <cap...@us...> - 2007-04-13 11:12:08
|
Revision: 36 http://svn.sourceforge.net/pearcolator/?rev=36&view=rev Author: captain5050 Date: 2007-04-13 04:12:10 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Build fixes :-( Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-04-13 10:45:30 UTC (rev 35) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-04-13 11:12:10 UTC (rev 36) @@ -179,7 +179,8 @@ @Override protected int translateInstruction(Laziness lazy, int pc) { - return ARM_InstructionDecoder.translateInstruction(this, - (ARM_ProcessSpace) ps, (ARM_Laziness) lazy, pc); + return 0xEBADC0DE; + //ARM_InstructionDecoder.translateInstruction(this, + // (ARM_ProcessSpace) ps, (ARM_Laziness) lazy, pc); } } Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-13 10:45:30 UTC (rev 35) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) @@ -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.process.ProcessSpace; public class ARM_LinuxProcessSpace extends ARM_ProcessSpace implements LinuxSystemCallGenerator { @@ -104,4 +105,7 @@ return null; } + public ProcessSpace getProcessSpace() { + return this; + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-13 10:45:32
|
Revision: 35 http://svn.sourceforge.net/pearcolator/?rev=35&view=rev Author: captain5050 Date: 2007-04-13 03:45:30 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Rename files to match class renaming Added Paths: ----------- src/org/binarytranslator/generic/gdbstub/GDBStub.java src/org/binarytranslator/generic/gdbstub/GDBTarget.java Removed Paths: ------------- src/org/binarytranslator/generic/gdbstub/GdbStub.java src/org/binarytranslator/generic/gdbstub/GdbTarget.java Copied: src/org/binarytranslator/generic/gdbstub/GDBStub.java (from rev 33, src/org/binarytranslator/generic/gdbstub/GdbStub.java) =================================================================== --- src/org/binarytranslator/generic/gdbstub/GDBStub.java (rev 0) +++ src/org/binarytranslator/generic/gdbstub/GDBStub.java 2007-04-13 10:45:30 UTC (rev 35) @@ -0,0 +1,744 @@ +/* + * 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.gdbstub; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.net.Socket; + +import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.os.process.ProcessSpace; + +/** + * Interface to GDB + */ +public final class GDBStub { + + /** + * 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; + + /** + * The currently processed Process Space + */ + private final ProcessSpace ps; + + /** + * 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 GDBStub(int port, ProcessSpace process) { + 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.ps = process; + this.target = process.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); + } + } +} Copied: src/org/binarytranslator/generic/gdbstub/GDBTarget.java (from rev 33, src/org/binarytranslator/generic/gdbstub/GdbTarget.java) =================================================================== --- src/org/binarytranslator/generic/gdbstub/GDBTarget.java (rev 0) +++ src/org/binarytranslator/generic/gdbstub/GDBTarget.java 2007-04-13 10:45:30 UTC (rev 35) @@ -0,0 +1,43 @@ +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(); +} Deleted: src/org/binarytranslator/generic/gdbstub/GdbStub.java =================================================================== --- src/org/binarytranslator/generic/gdbstub/GdbStub.java 2007-04-13 10:41:13 UTC (rev 34) +++ src/org/binarytranslator/generic/gdbstub/GdbStub.java 2007-04-13 10:45:30 UTC (rev 35) @@ -1,744 +0,0 @@ -/* - * 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.gdbstub; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.ServerSocket; -import java.net.Socket; - -import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.generic.os.process.ProcessSpace; - -/** - * Interface to GDB - */ -public final class GDBStub { - - /** - * 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; - - /** - * The currently processed Process Space - */ - private final ProcessSpace ps; - - /** - * 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 GDBStub(int port, ProcessSpace process) { - 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.ps = process; - this.target = process.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); - } - } -} Deleted: src/org/binarytranslator/generic/gdbstub/GdbTarget.java =================================================================== --- src/org/binarytranslator/generic/gdbstub/GdbTarget.java 2007-04-13 10:41:13 UTC (rev 34) +++ src/org/binarytranslator/generic/gdbstub/GdbTarget.java 2007-04-13 10:45:30 UTC (rev 35) @@ -1,43 +0,0 @@ -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(); -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-13 10:41:13
|
Revision: 34 http://svn.sourceforge.net/pearcolator/?rev=34&view=rev Author: captain5050 Date: 2007-04-13 03:41:13 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Remove unparsable character Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-13 09:02:45 UTC (rev 33) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-13 10:41:13 UTC (rev 34) @@ -376,7 +376,7 @@ return opcode; } - /** Returns true if the condition codes shall be set by this operation, false otherwise. \x80*/ + /** Returns true if the condition codes shall be set by this operation, false otherwise. */ public boolean updateConditionCodes() { return updateConditionCodes; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-13 09:02:44
|
Revision: 33 http://svn.sourceforge.net/pearcolator/?rev=33&view=rev Author: michael_baer Date: 2007-04-13 02:02:45 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Class renamed. Added Paths: ----------- src/org/binarytranslator/generic/gdbstub/GdbTarget.java Removed Paths: ------------- src/org/binarytranslator/generic/gdbstub/GDBTarget.java Deleted: src/org/binarytranslator/generic/gdbstub/GDBTarget.java =================================================================== --- src/org/binarytranslator/generic/gdbstub/GDBTarget.java 2007-04-13 09:02:24 UTC (rev 32) +++ src/org/binarytranslator/generic/gdbstub/GDBTarget.java 2007-04-13 09:02:45 UTC (rev 33) @@ -1,43 +0,0 @@ -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(); -} Copied: src/org/binarytranslator/generic/gdbstub/GdbTarget.java (from rev 32, src/org/binarytranslator/generic/gdbstub/GDBTarget.java) =================================================================== --- src/org/binarytranslator/generic/gdbstub/GdbTarget.java (rev 0) +++ src/org/binarytranslator/generic/gdbstub/GdbTarget.java 2007-04-13 09:02:45 UTC (rev 33) @@ -0,0 +1,43 @@ +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(); +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-13 09:02:25
|
Revision: 32 http://svn.sourceforge.net/pearcolator/?rev=32&view=rev Author: michael_baer Date: 2007-04-13 02:02:24 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Class renamed. Added Paths: ----------- src/org/binarytranslator/generic/gdbstub/GdbStub.java Removed Paths: ------------- src/org/binarytranslator/generic/gdbstub/GDBStub.java Deleted: src/org/binarytranslator/generic/gdbstub/GDBStub.java =================================================================== --- src/org/binarytranslator/generic/gdbstub/GDBStub.java 2007-04-12 17:34:57 UTC (rev 31) +++ src/org/binarytranslator/generic/gdbstub/GDBStub.java 2007-04-13 09:02:24 UTC (rev 32) @@ -1,744 +0,0 @@ -/* - * 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.gdbstub; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.ServerSocket; -import java.net.Socket; - -import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.generic.os.process.ProcessSpace; - -/** - * Interface to GDB - */ -public final class GDBStub { - - /** - * 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; - - /** - * The currently processed Process Space - */ - private final ProcessSpace ps; - - /** - * 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 GDBStub(int port, ProcessSpace process) { - 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.ps = process; - this.target = process.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); - } - } -} Copied: src/org/binarytranslator/generic/gdbstub/GdbStub.java (from rev 31, src/org/binarytranslator/generic/gdbstub/GDBStub.java) =================================================================== --- src/org/binarytranslator/generic/gdbstub/GdbStub.java (rev 0) +++ src/org/binarytranslator/generic/gdbstub/GdbStub.java 2007-04-13 09:02:24 UTC (rev 32) @@ -0,0 +1,744 @@ +/* + * 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.gdbstub; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.net.Socket; + +import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.os.process.ProcessSpace; + +/** + * Interface to GDB + */ +public final class GDBStub { + + /** + * 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; + + /** + * The currently processed Process Space + */ + private final ProcessSpace ps; + + /** + * 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 GDBStub(int port, ProcessSpace process) { + 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.ps = process; + this.target = process.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); + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-12 17:34:58
|
Revision: 31 http://svn.sourceforge.net/pearcolator/?rev=31&view=rev Author: michael_baer Date: 2007-04-12 10:34:57 -0700 (Thu, 12 Apr 2007) Log Message: ----------- Checked in Visitor pattern method that should have been committed in the last patch. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-12 17:31:57 UTC (rev 30) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-12 17:34:57 UTC (rev 31) @@ -50,6 +50,7 @@ return (value << (32 - bitsUsed)) >> (32 - bitsUsed); } + /** A base class for all (conditional) ARM instructions. */ private abstract static class Basic { /** @see #getCondition() */ protected final byte condition; @@ -62,6 +63,9 @@ public final byte getCondition() { return condition; } + + /** All instruction classes are meant to implement the visitor pattern. This is the pattern's visit method. */ + public abstract void visit(ARM_InstructionVisitor visitor); } /** Base class for most instructions that use two registers. */ @@ -386,6 +390,11 @@ public static boolean conforms(int instr) { return getBits(instr, 26, 27) == 0; } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a LDR/SDR instruction. */ @@ -459,6 +468,11 @@ public static boolean conforms(int instr) { return getBits(instr, 26, 27) == 1; } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a normal (not long) multiply instruction. */ @@ -472,6 +486,11 @@ public static boolean conforms(int instr) { return getBits(instr, 22, 27) == 0 && getBits(instr, 4, 7) == 9; } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a long multiply instruction. */ @@ -505,6 +524,11 @@ public static boolean conforms(int instr) { return getBits(instr, 23, 27) == 1 && getBits(instr, 4, 7) == 9; } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a SWP/SWPB instruction. */ @@ -528,6 +552,11 @@ return getBits(instr, 23, 27) == 2 && getBits(instr, 20, 21) == 0 && getBits(instr, 4, 11) == 9; } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a LDM/STM instruction. */ @@ -608,6 +637,11 @@ public byte getBaseRegister() { return baseRegister; } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a SWI instruction*/ @@ -630,6 +664,11 @@ public static boolean conforms(int instr) { return getBits(instr, 24, 27) == 15; } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a branch instruction. */ @@ -661,6 +700,11 @@ public static boolean conforms(int instr) { return getBits(instr, 25, 27) == 5; } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a BX instruction set */ @@ -704,6 +748,11 @@ return getBits(instr, 25, 31) == 0x7D // BLX(1) || (getBits(instr, 20, 27) == 0x12 && getBits(instr, 6, 7) == 0); //BLX(2) && BX } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a LDC/STC instruction. */ @@ -777,6 +826,11 @@ public static boolean conforms(int instr) { return getBits(instr, 25, 27) == 6; } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a CDP instruction. */ @@ -828,6 +882,11 @@ public static boolean conforms(int instr) { return getBits(instr, 24, 27) == 14 && !getBit(instr, 4); } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a MRC/MCR instruction. */ @@ -888,6 +947,11 @@ public static boolean conforms(int instr) { return getBits(instr, 24, 27) == 14 && getBit(instr, 4); } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a MRS instruction. */ @@ -920,6 +984,11 @@ public static boolean conforms(int instr) { return getBits(instr, 23, 27) == 2 && getBits(instr, 16, 21) == 0 && (instr & 0xFFF) == 0; } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } /** Represents a MSR instruction. */ @@ -993,5 +1062,47 @@ public static boolean conforms(int instr) { return getBits(instr, 26, 27) == 0 && getBits(instr, 23, 24) == 2 && getBits(instr, 12, 15) == 0; } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } } + + /** Represents a CLZ instruction. */ + public final static class CountLeadingZeros extends Basic { + + /** @see #getRm() */ + protected final byte Rm; + + /** @see #getRd() */ + protected final byte Rd; + + public CountLeadingZeros(int instr) { + super(instr); + + Rm = (byte) (instr & 0xF); + Rd = (byte) getBits(instr, 12, 15); + } + + /** Returns the source register for this operation. */ + public byte getRm() { + return Rm; + } + + /** Returns the destination register for this operation. */ + public byte getRd() { + return Rd; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ + public static boolean conforms(int instr) { + return getBits(instr, 16, 27) == 0x16F && getBits(instr, 4, 11) == 0xF1; + } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-12 17:32:11
|
Revision: 30 http://svn.sourceforge.net/pearcolator/?rev=30&view=rev Author: michael_baer Date: 2007-04-12 10:31:57 -0700 (Thu, 12 Apr 2007) Log Message: ----------- - Changed ARM instruction decoders to allow traversal using the visitor pattern. - Added Interface ARM_InstructionVisitor, which is to be implemented by visitors Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java Removed Paths: ------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java Deleted: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-12 17:11:46 UTC (rev 29) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-12 17:31:57 UTC (rev 30) @@ -1,163 +0,0 @@ -package org.binarytranslator.arch.arm.decoder; - -import org.binarytranslator.DBT; -import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; -import org.binarytranslator.generic.decoder.InstructionDecoder; -import org.jikesrvm.compilers.opt.ir.*; - -public class ARM_InstructionDecoder extends InstructionDecoder { - - abstract static class BasicDecoder implements OPT_Operators { - /** Return the value of a single bit. Note that the bit is 0-based.*/ - public static final boolean getBit(int word, int bit) { - if (DBT.VerifyAssertions) DBT._assert(bit >= 0 && bit <= 31); - return (word & (1 << bit)) != 0; - } - - /** Transfer a subsequence of bits within (word) into an integer. Note that all bits are 0-based. */ - public static final int getBits(int word, int from, int to) { - if (DBT.VerifyAssertions) DBT._assert(from < to && from >= 0 && to <= 31); - return (word & ((1 << (to+1)) - 1)) >> from; - } - - protected abstract int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr); - } - - /** Translates LDR and STR instructions */ - static class LDR_STR_Decoder extends BasicDecoder { - - @Override - protected int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { - boolean immediateOperand = getBit(instr, 25); - boolean preIndex = getBit(instr, 24); - boolean positiveOffset = getBit(instr, 23); - boolean transferByte = getBit(instr, 22); - boolean writeBack = getBit(instr, 21); - boolean loadOperation = getBit(instr, 20); - int offset = getBits(instr, 0, 11); - - int baseRegister = getBits(instr, 16, 19); - int destRegister = getBits(instr, 12, 15); - - System.out.println("Decoding LDR/STR with: "); - System.out.println("Imm: " + immediateOperand); - System.out.println("Pre Index: " + preIndex); - System.out.println("Offset: " + (positiveOffset ? "+" : "-") + offset); - System.out.println("Base: " + baseRegister); - System.out.println("Dest: " + destRegister); - System.out.println("Load Operation: " + loadOperation); - System.out.println("Write back: " + writeBack); - - //we are only handling a limitied subset of this instruction - if (DBT.VerifyAssertions) DBT._assert(immediateOperand == false && transferByte == false && writeBack == false && preIndex == true); - - //resolve correspoding memory address for this operation - OPT_Operand memoryAddr; - - //take the ARM pipeline into account when storing relative to the pc - if (baseRegister == 15) { - if (positiveOffset) - memoryAddr = new OPT_IntConstantOperand(pc + 8 + offset); - else - memoryAddr = new OPT_IntConstantOperand(pc + 8 - offset); - } - else { - OPT_Operand Rs = arm2ir.getRegister(baseRegister); - memoryAddr = arm2ir.getTempInt(0); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, (OPT_RegisterOperand)memoryAddr, Rs, new OPT_IntConstantOperand(offset))); - } - - //resolve dest register - OPT_RegisterOperand Rd = arm2ir.getRegister(destRegister); - - if (loadOperation) { - //load a word - ps.memory.translateLoad32(memoryAddr, Rd); - } - else { - //store a word - ps.memory.translateStore32(memoryAddr, Rd); - } - - return pc+4; - } - } - - abstract static class DataProcessingOperation_Decoder extends BasicDecoder { - - protected int Rd; - protected int Rs; - protected boolean setConditionCodes; - - protected boolean hasImmediate; - protected int immediate; - - @Override - protected final int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { - hasImmediate = getBit(instr, 25); - setConditionCodes = getBit(instr, 20); - Rd = getBits(instr, 12, 15); - Rs = getBits(instr, 16, 19); - - //we're only handling a subset of the possible instruction options - if (DBT.VerifyAssertions) DBT._assert(Rd != 15 && Rs != 15 && hasImmediate == true); - - if (hasImmediate) - immediate = getBits(instr, 0, 7) << getBits(instr, 8, 11); - - System.out.println("Decoding Data Processing Instruction with: "); - System.out.println("Rs: " + Rs); - System.out.println("Rd: " + Rd); - System.out.println("Op Code: " + getBits(instr, 21, 24)); - System.out.println("Set Condition Codes: " + setConditionCodes); - - if (hasImmediate) - System.out.println("Immediate: " + immediate); - - translateActualOpcode(arm2ir, ps, lazy, pc, instr); - - if (setConditionCodes && Rd != 15) { - throw new UnsupportedOperationException("Setting conditions codes is not yet supported"); - } - - return pc+4; - } - - protected abstract void translateActualOpcode(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr); - } - - static class ADD_Decoder extends DataProcessingOperation_Decoder { - - @Override - protected void translateActualOpcode(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { - - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, arm2ir.getRegister(Rd), arm2ir.getRegister(Rs), new OPT_IntConstantOperand(immediate))); - } - } - - static class BranchDecoder extends BasicDecoder { - - @Override - protected int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { - boolean branchAndLink = getBit(instr, 24); - int offset = getBits(instr, 0, 23); - - if (DBT.VerifyAssertions) DBT._assert(branchAndLink == false); - - return pc + 8 + offset; - } - } - - public static int translateInstruction(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc) { - int instr = ps.memory.loadInstruction32(pc); - - System.out.println("Translating Instruction:" + instr); - BasicDecoder decoder = null; - - if (BasicDecoder.getBits(instr, 26, 27) == 1) { - decoder = new LDR_STR_Decoder(); - } - - return decoder.translate(arm2ir, ps, lazy, pc, instr); - } -} Added: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-12 17:31:57 UTC (rev 30) @@ -0,0 +1,37 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.BlockDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Branch; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.BranchExchange; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorDataProcessing; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorRegisterTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CountLeadingZeros; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.DataProcessing; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.LongMultiply; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Multiply; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.SingleDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.SoftwareInterrupt; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Swap; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.TransferFromStatusRegister; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.TransferToStatusRegister; + +/** An interface that supports iterating over ARM instructions using the visitor pattern. */ +public interface ARM_InstructionVisitor { + + void visit(DataProcessing processing); + void visit(SingleDataTransfer transfer); + void visit(Multiply multiply); + void visit(LongMultiply multiply); + void visit(Swap swap); + void visit(BlockDataTransfer transfer); + void visit(SoftwareInterrupt interrupt); + void visit(Branch branch); + void visit(BranchExchange exchange); + void visit(CoprocessorDataTransfer transfer); + void visit(CoprocessorDataProcessing processing); + void visit(CoprocessorRegisterTransfer transfer); + void visit(TransferFromStatusRegister register); + void visit(TransferToStatusRegister register); + void visit(CountLeadingZeros zeros); +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-12 17:12:37
|
Revision: 29 http://svn.sourceforge.net/pearcolator/?rev=29&view=rev Author: michael_baer Date: 2007-04-12 10:11:46 -0700 (Thu, 12 Apr 2007) Log Message: ----------- Initial version of the instruction decoder classes for ARM. Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java Added: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-12 17:11:46 UTC (rev 29) @@ -0,0 +1,997 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.DBT; + +public class ARM_InstructionDecoders { + + /** + * Checks if a bit is set within a word. + * @param word + * The word that is being examined. + * @param bit + * The number of the bit that is to be checked, starting from zero. + * @return + * True, if the given bit is set within the word, false otherwise. + */ + public static final boolean getBit(int word, int bit) { + if (DBT.VerifyAssertions) + DBT._assert(bit >= 0 && bit <= 31); + return (word & (1 << bit)) != 0; + } + + /** + * Extracts a subsequence of bits from a word. + * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. + * @param word + * The word that is to be examined. + * @param from + * The first bit (starting from 0) that is to be extracted. + * @param to + * The last bit (starting from 0) that is to be extracted from the word. + * @return + * A zero-based version of the bit sequence. + */ + public static final int getBits(int word, int from, int to) { + if (DBT.VerifyAssertions) + DBT._assert(from < to && from >= 0 && to <= 31); + return (word & ((1 << (to + 1)) - 1)) >> from; + } + + /** + * Sign extends a given value. + * @param value + * The value to sign extends. + * @param bitsUsed + * The number bits used within this values. + * @return + * A sign extended value. + */ + public static int signExtend(int value, int bitsUsed) { + return (value << (32 - bitsUsed)) >> (32 - bitsUsed); + } + + private abstract static class Basic { + /** @see #getCondition() */ + protected final byte condition; + + public Basic(int instr) { + condition = (byte) getBits(instr, 28, 31); + } + + /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ + public final byte getCondition() { + return condition; + } + } + + /** Base class for most instructions that use two registers. */ + private abstract static class TwoRegistersTemplate extends Basic { + + /** @see #getRn() */ + protected final byte Rn; + + /** @see #getRd() */ + protected final byte Rd; + + public TwoRegistersTemplate(int instr) { + super(instr); + + Rd = (byte) getBits(instr, 12, 15); + Rn = (byte) getBits(instr, 16, 19); + } + + /** Returns the number of the operation's destination register, starting from 0.*/ + public final byte getRd() { + return Rd; + } + + /** Returns the number of the operation's first operand register, starting from 0.*/ + public final byte getRn() { + return Rn; + } + } + + /** Base class for most instructions that use three registers. */ + private abstract static class ThreeRegistersTemplate extends + TwoRegistersTemplate { + + /** @see #getRm() */ + protected final byte Rm; + + public ThreeRegistersTemplate(int instr) { + super(instr); + + Rm = (byte) getBits(instr, 0, 3); + } + + /** Returns the number of the second operand register, starting from 0.*/ + public final byte getRm() { + return Rm; + } + } + + /** Base class for multiply operations. */ + protected abstract static class MultiplyTemplate + extends ThreeRegistersTemplate { + + /** @see #updateConditionCodes() */ + protected final boolean updateConditionCodes; + + /** @see #accumulate() */ + protected final boolean accumulate; + + /** @see #getRs() */ + protected final byte Rs; + + protected MultiplyTemplate(int instr) { + super(instr); + + updateConditionCodes = getBit(instr, 20); + accumulate = getBit(instr, 21); + Rs = (byte) getBits(instr, 8, 11); + } + + /** Returns true, if the condition codes shall be updated by the result of this operation. */ + public boolean updateConditionCodes() { + return updateConditionCodes; + } + + /** Returns true, if this is the accumulate version of the instruction. */ + public boolean accumulate() { + return accumulate; + } + + /** Returns the register number of the Rs operand register. */ + public byte getRs() { + return Rs; + } + } + + /** Base class for coprocessor instructions. */ + protected static abstract class CoprocessorTemplate extends Basic { + + /** This is a register id, which can either refer to the CPU or the coprocessor, depending on the instruction. */ + protected final byte Rd; + + /** This is a register id, which can either refer to the CPU or the coprocessor, depending on the instruction. */ + protected final byte Rn; + + /** @see #getCoprocessorNumber() */ + protected final byte cpNum; + + public CoprocessorTemplate(int instr) { + super(instr); + + cpNum = (byte) getBits(instr, 8, 11); + Rd = (byte) getBits(instr, 12, 15); + Rn = (byte) getBits(instr, 16, 19); + } + + /** Returns the coprocessor that shall process this instruction */ + public byte getCoprocessorNumber() { + return cpNum; + } + } + + /** Represents an operand, which might either be an immediate value, a register (shifted by an immediate) or a register shifted by a register. */ + public abstract static class OperandWrapper { + + public enum Type { + Immediate, + Register, + ImmediateShiftedRegister, + RegisterShiftedRegister, + } + + public enum ShiftType { + LogicalLeft, + LogicalRight, + ArithmeticRight, + RotateRight, + RotateRightExtend + } + + /** Creates an operand wrapper around a 12 bit immediate value. */ + public static OperandWrapper createImmediate(int immediate) { + return new ImmediateOperand(immediate); + } + + /** Creates an operand wrapper that is a nromal register value. */ + public static OperandWrapper createRegister(byte register) { + return new RegisterOperand(register); + } + + /** Creates an operand wrapper, that represents a register shifted by an immediate or a register, depending on the instruction. */ + public static OperandWrapper decodeShiftedRegister(int instr) { + ShiftType shift = ShiftType.values()[getBits(instr, 5, 6)]; + byte shiftedRegister = (byte) (instr & 0xF); + + if (getBit(instr, 4)) { + //shift by a register + byte shiftingRegister = (byte)getBits(instr, 8, 11); + return new RegisterShiftRegisterOperand(shiftedRegister, shift, shiftingRegister); + } + else { + //shift by an immediate + byte immediate = (byte)getBits(instr, 7, 11); + + if (immediate == 0) { + //if we are shifting by zero, we might forget about the shift + if (shift == ShiftType.RotateRight) { + //However, if the shift type was RotateRight, then ARM meant do a RotateRightExtend by 1 + return new RegisterShiftImmediateOperand(shiftedRegister, shift, (byte)1); + } + else { + //Otherwise, really forget about the shifting + return new RegisterOperand(shiftedRegister); + } + } + else { + return new RegisterShiftImmediateOperand(shiftedRegister, shift, immediate); + } + } + } + + public abstract Type getType(); + + /** Returns the immediate, which is the 2nd operand of this instruction. Make sure that hasImmediate is true before calling this. */ + public int getImmediate() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + + /** Returns the number of the register, which forms the 2nd operand. Only applicable if {@link #hasImmediate()} is false.*/ + public byte getRegister() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + + /** Returns the number of the register which is performing the shift. */ + public byte getShiftingRegister() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + + /** Returns the amount by which a value is supposed to be shifted*/ + public byte getShiftAmount() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + + /** Returns the shift type, in case this Operand includes shifting. */ + public ShiftType getShiftType() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + + protected static class ImmediateOperand extends OperandWrapper { + + protected final int immediate; + + protected ImmediateOperand(int immediate) { + this.immediate = immediate; + } + + @Override + public int getImmediate() { + return immediate; + } + + @Override + public Type getType() { + return Type.Immediate; + } + } + + protected static class RegisterOperand extends OperandWrapper { + + protected final byte register; + + protected RegisterOperand(byte register) { + this.register = register; + } + + @Override + public byte getRegister() { + return register; + } + + @Override + public Type getType() { + return Type.Register; + } + } + + protected static class RegisterShiftImmediateOperand extends RegisterOperand { + + protected final ShiftType shiftType; + protected final byte shiftAmount; + + protected RegisterShiftImmediateOperand(byte register, ShiftType shift, byte shiftAmount) { + super(register); + this.shiftAmount = shiftAmount; + this.shiftType = shift; + } + + @Override + public Type getType() { + return Type.ImmediateShiftedRegister; + } + + @Override + public byte getShiftAmount() { + return shiftAmount; + } + } + + protected static class RegisterShiftRegisterOperand extends RegisterOperand { + + protected final ShiftType shiftType; + protected final byte shiftingRegister; + + protected RegisterShiftRegisterOperand(byte shiftedRegister, ShiftType shift, byte shiftingRegister) { + super(shiftedRegister); + this.shiftType = shift; + this.shiftingRegister = shiftingRegister; + } + + @Override + public Type getType() { + return Type.RegisterShiftedRegister; + } + + @Override + public byte getShiftingRegister() { + return shiftingRegister; + } + } + } + + /** Represents a Data Processing instruction. */ + public final static class DataProcessing extends + TwoRegistersTemplate { + + /** @see #hasSetConditionCodes() */ + protected final boolean updateConditionCodes; + + /** @see #getOpcode() */ + protected final byte opcode; + + /** @see #getOperand2() */ + protected final OperandWrapper operand2; + + public DataProcessing(int instr) { + super(instr); + + updateConditionCodes = getBit(instr, 20); + opcode = (byte) getBits(instr, 21, 24); + + if (getBit(instr, 25)) + operand2 = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); + else + operand2 = OperandWrapper.decodeShiftedRegister(instr); + } + + /** Returns the opcode, that specifies the data processing operation, which is to be performed. */ + public byte getOpcode() { + return opcode; + } + + /** Returns true if the condition codes shall be set by this operation, false otherwise. \x80*/ + public boolean updateConditionCodes() { + return updateConditionCodes; + } + + /** Returns the 2nd operand of this data processing instruction. */ + public OperandWrapper getOperand2() { + return operand2; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ + public static boolean conforms(int instr) { + return getBits(instr, 26, 27) == 0; + } + } + + /** Represents a LDR/SDR instruction. */ + public final static class SingleDataTransfer extends + TwoRegistersTemplate { + + /** @see #preIndexing() */ + protected final boolean preIndexing; + + /** @see #positiveOffset() */ + protected final boolean positiveOffset; + + /** @see #byteTransfer() */ + protected final boolean byteTransfer; + + /** @see #writeBack() */ + protected final boolean writeBack; + + /** @see #isLoad() */ + protected final boolean isLoad; + + /** @see #getOperand2() */ + protected final OperandWrapper operand2; + + public SingleDataTransfer(int instr) { + super(instr); + + preIndexing = getBit(instr, 24); + positiveOffset = getBit(instr, 23); + byteTransfer = getBit(instr, 22); + writeBack = getBit(instr, 21); + isLoad = getBit(instr, 20); + + if (getBit(instr, 25)) + operand2 = OperandWrapper.createImmediate(instr & 0xFF); + else + operand2 = OperandWrapper.decodeShiftedRegister(instr); + } + + /** Returns true, if a single byte is to be transfered or false if an int shall be transfered. */ + public boolean isByteTransfer() { + return byteTransfer; + } + + /** True if this is a LDM instruction, false if it is a STM instruction. */ + public boolean isLoad() { + return isLoad; + } + + /** Returns true, if the offset from the base register (see {@link #getRn()} is positive, false if it is negative. */ + public boolean positiveOffset() { + return positiveOffset; + } + + /** True if the base register shall be changed before the transfer, otherwise changed it after the transfer. */ + public boolean preIndexing() { + return preIndexing; + } + + /** True if the incremented base register shall be persisted after this instruction. */ + public boolean writeBack() { + return writeBack; + } + + /** Returns the 2nd operand of this data processing instruction. */ + public OperandWrapper getOperand2() { + return operand2; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ + public static boolean conforms(int instr) { + return getBits(instr, 26, 27) == 1; + } + } + + /** Represents a normal (not long) multiply instruction. */ + public final static class Multiply extends MultiplyTemplate { + + protected Multiply(int instr) { + super(instr); + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ + public static boolean conforms(int instr) { + return getBits(instr, 22, 27) == 0 && getBits(instr, 4, 7) == 9; + } + } + + /** Represents a long multiply instruction. */ + public final static class LongMultiply extends MultiplyTemplate { + + /** @see #isUnsigned() */ + protected final boolean unsigned; + + public LongMultiply(int instr) { + super(instr); + + unsigned = getBit(instr, 22); + } + + /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ + public byte getRdHigh() { + return Rd; + } + + /** Long multiplication stores its result in two registers. This function gets the register which receives the low int. */ + public byte getRdLow() { + return Rn; + } + + /** Returns true, if this is an unsigned multiplication or false if it is a signed multiplication. */ + public boolean isUnsigned() { + return unsigned; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ + public static boolean conforms(int instr) { + return getBits(instr, 23, 27) == 1 && getBits(instr, 4, 7) == 9; + } + } + + /** Represents a SWP/SWPB instruction. */ + public final static class Swap extends ThreeRegistersTemplate { + + /** @see #swapByte() */ + protected final boolean swapByte; + + public Swap(int instr) { + super(instr); + swapByte = getBit(instr, 22); + } + + /** Returns true, if a byte shall be swapped or false, if an int (32 bit) shall be swapped. */ + public boolean swapByte() { + return swapByte; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ + public static boolean conforms(int instr) { + return getBits(instr, 23, 27) == 2 && getBits(instr, 20, 21) == 0 + && getBits(instr, 4, 11) == 9; + } + } + + /** Represents a LDM/STM instruction. */ + public final static class BlockDataTransfer extends Basic { + + /** @see #preIndexing() */ + protected final boolean preIndexing; + + /** @see #incrementBase() */ + protected final boolean incrementBase; + + /** @see #forceUser() */ + protected final boolean forceUser; + + /** @see #writeBack() */ + protected final boolean writeBack; + + /** @see #isLoad() */ + protected final boolean isLoad; + + /** @see #getBaseRegister() */ + protected final byte baseRegister; + + /** Contains a set bit at position N if rN should be transferred using this instruction.*/ + protected final int registerList; + + public BlockDataTransfer(int instr) { + super(instr); + + preIndexing = getBit(instr, 24); + incrementBase = getBit(instr, 23); + forceUser = getBit(instr, 22); + writeBack = getBit(instr, 21); + isLoad = getBit(instr, 20); + baseRegister = (byte) getBits(instr, 16, 19); + registerList = instr; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ + public static boolean conforms(int instr) { + return getBits(instr, 25, 27) == 4; + } + + /** @return True if register r should be transferred using this instruction. */ + public boolean transferRegister(int r) { + if (DBT.VerifyAssertions) + DBT._assert(r >= 0 && r < 16); + + return getBit(registerList, r); + } + + /** True if the base register shall be changed before each single transfer, otherwise changed it after each transfer. */ + public boolean preIndexing() { + return preIndexing; + } + + /** True if the base register shall be incremented, false if it should be decremented. */ + public boolean incrementBase() { + return incrementBase; + } + + /** Force user mode during this instruction? */ + public boolean forceUser() { + return forceUser; + } + + /** True if the incremented base register shall be persisted after this instruction. */ + public boolean writeBack() { + return writeBack; + } + + /** True if this is a LDM instruction, false if it is a STM instruction. */ + public boolean isLoad() { + return isLoad; + } + + /** The number of the register which will provides the base address for this LDM/STM instruction. */ + public byte getBaseRegister() { + return baseRegister; + } + } + + /** Represents a SWI instruction*/ + public final static class SoftwareInterrupt extends Basic { + + /** @see #getInterruptNumber() */ + protected final int interruptNumber; + + public SoftwareInterrupt(int instr) { + super(instr); + interruptNumber = instr & 0xFFFFFF; + } + + /** Returns the interrupt that is being called. The value is taken from the instruction's comment field. */ + public int getInterruptNumber() { + return interruptNumber; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ + public static boolean conforms(int instr) { + return getBits(instr, 24, 27) == 15; + } + } + + /** Represents a branch instruction. */ + public final static class Branch extends Basic { + + /** @see #isBranchAndLink() */ + protected final boolean link; + + /** @see #getOffset() */ + protected final int offset; + + public Branch(int instr) { + super(instr); + link = getBit(instr, 24); + offset = instr & 0xFFF; + } + + /** Should the current PC be put into the lr? */ + public boolean isBranchAndLink() { + return link; + } + + /** The offset of the target address to the PC */ + public int getOffset() { + return offset; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ + public static boolean conforms(int instr) { + return getBits(instr, 25, 27) == 5; + } + } + + /** Represents a BX instruction set */ + public final static class BranchExchange extends Basic { + + /** @see #getRn() */ + protected final OperandWrapper target; + + /** @see #link() */ + protected final boolean link; + + public BranchExchange(int instr) { + super(getBit(instr, 27) ? 0xE0000000 : instr); + + if (getBit(instr, 27)) { + //this is the immediate version of a BLX + link = true; + + //sign extend jump target + int jumpTarget = signExtend(instr & 0xFFF, 24); + + //are we addressing a half-byte? + if (getBit(instr, 24)) + jumpTarget += 2; + + target = OperandWrapper.createImmediate(jumpTarget); + } + else { + link = getBit(instr, 5); + target = OperandWrapper.createRegister((byte) (instr & 0xF)); + } + } + + /** Returns, whether the return address for this jump shall be put into the lr. */ + public boolean link() { + return link; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ + public static boolean conforms(int instr) { + return getBits(instr, 25, 31) == 0x7D // BLX(1) + || (getBits(instr, 20, 27) == 0x12 && getBits(instr, 6, 7) == 0); //BLX(2) && BX + } + } + + /** Represents a LDC/STC instruction. */ + public static final class CoprocessorDataTransfer extends CoprocessorTemplate { + + /** @see #getOffset() */ + protected final int offset; + + /** @see #preIndexing() */ + protected final boolean preIndexing; + + /** @see #largeTransfer() */ + protected final boolean largeTransfer; + + /** @see #writeBack() */ + protected final boolean writeBack; + + /** @see #isLoad() */ + protected final boolean isLoad; + + public CoprocessorDataTransfer(int instr) { + super(instr); + + preIndexing = getBit(instr, 24); + largeTransfer = getBit(instr, 22); + writeBack = getBit(instr, 21); + isLoad = getBit(instr, 20); + + if (getBit(instr, 23)) + offset = (instr & 0xFF) << 2; + else + offset = - ((instr & 0xFF) << 2); + } + + /** Returns the number of the register, which contains the base address for this data transfer.*/ + public byte getBaseRegister() { + return Rn; + } + + /** Returns the transfer register on the coprocessor. */ + public byte getCoprocessorRegister() { + return Rd; + } + + /** True if this is a LDC instruction, false if it is a STC instruction. */ + public boolean isLoad() { + return isLoad; + } + + /** Returns the offset that should be added to the base register. Note that the offset may be negative. */ + public int getOffset() { + return offset; + } + + /** True if the changed base register shall be persisted after this instruction. */ + public boolean writeBack() { + return writeBack; + } + + /** True if the base register shall be changed before the transfer, otherwise changed it after the transfer. */ + public boolean preIndexing() { + return preIndexing; + } + + /** Returns true, if the flag which indicates a large transfer is set. The meaning of "large transfer" is dependend on the coprocessor.*/ + public boolean largeTransfer() { + return largeTransfer; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ + public static boolean conforms(int instr) { + return getBits(instr, 25, 27) == 6; + } + } + + /** Represents a CDP instruction. */ + public final static class CoprocessorDataProcessing extends CoprocessorTemplate { + + /** @see #getOpcode() */ + protected final byte opcode; + + /** @see #getCoprocessorRm() */ + protected final byte cpRm; + + /** @see #getCoprocessorInfo() */ + protected final byte cpInfo; + + public CoprocessorDataProcessing(int instr) { + super(instr); + + opcode = (byte) getBits(instr, 20, 23); + cpInfo = (byte) getBits(instr, 5, 7); + cpRm = (byte) (instr & 0xF); + } + + /** Returns the destination register of this operation. This register is a coprocessor register. */ + public byte getCoprocessorRd() { + return Rd; + } + + /** Returns the first operand register of this operation. This register is a coprocessor register. */ + public byte getCoprocessorRn() { + return Rn; + } + + /** Returns the second operand register of this operation. This register is a coprocessor register. */ + public byte getCoprocessorRm() { + return cpRm; + } + + /** The instruction contains three bits that may be used to control the details of the operation. This info is only of significance to the coprocessor. */ + public byte getCoprocessorInfo() { + return cpInfo; + } + + /** Returns the opcode, that identifies the operation that shall be performed on the coprocessor. This vlaue is only of significance to the coprocessor. */ + public byte getOpcode() { + return opcode; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ + public static boolean conforms(int instr) { + return getBits(instr, 24, 27) == 14 && !getBit(instr, 4); + } + } + + /** Represents a MRC/MCR instruction. */ + public final static class CoprocessorRegisterTransfer extends CoprocessorTemplate { + + /** @see #getOpcode() */ + protected final byte opcode; + + /** @see #getCoprocessorRm() */ + protected final byte cpRm; + + /** @see #getCoprocessorInfo() */ + protected final byte cpInfo; + + /** @see #isLoadFromCP() */ + protected final boolean isLoad; + + public CoprocessorRegisterTransfer(int instr) { + super(instr); + + opcode = (byte) getBits(instr, 21, 23); + cpInfo = (byte) getBits(instr, 5, 7); + cpRm = (byte) (instr & 0xF); + isLoad = getBit(instr, 20); + } + + /** Returns true if this operation is a load from a coprocessor or false if it is a store to coprocessor. */ + public boolean isLoadFromCP() { + return isLoad; + } + + /** Returns the destination register of this operation.*/ + public byte getRd() { + return Rd; + } + + /** Returns the first operand register of this operation. This register is a coprocessor register. */ + public byte getCoprocessorRn() { + return Rn; + } + + /** Returns the second operand register of this operation. This register is a coprocessor register. */ + public byte getCoprocessorRm() { + return cpRm; + } + + /** The instruction contains three bits that may be used to control the details of the operation. This info is only of significance to the coprocessor. */ + public byte getCoprocessorInfo() { + return cpInfo; + } + + /** Returns the opcode, that identifies the operation that shall be performed on the coprocessor. This vlaue is only of significance to the coprocessor. */ + public byte getOpcode() { + return opcode; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ + public static boolean conforms(int instr) { + return getBits(instr, 24, 27) == 14 && getBit(instr, 4); + } + } + + /** Represents a MRS instruction. */ + public final static class TransferFromStatusRegister extends Basic { + + /** @see #getRd() */ + protected final byte Rd; + + /** @see #transferSavedPSR() */ + protected final boolean transferSavedPSR; + + public TransferFromStatusRegister(int instr) { + super(instr); + + Rd = (byte) getBits(instr, 12, 15); + transferSavedPSR = getBit(instr, 22); + } + + /** Returns the number of the destination register. */ + public byte getRd() { + return Rd; + } + + /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ + public boolean transferSavedPSR() { + return transferSavedPSR; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ + public static boolean conforms(int instr) { + return getBits(instr, 23, 27) == 2 && getBits(instr, 16, 21) == 0 && (instr & 0xFFF) == 0; + } + } + + /** Represents a MSR instruction. */ + public final static class TransferToStatusRegister extends Basic { + + /** @see #transferControlField() */ + protected final boolean transferControl; + + /** @see #transferExtensionField() */ + protected final boolean transferExtension; + + /** @see #transferStatusField() */ + protected final boolean transferStatus; + + /** @see #transferFlagField() */ + protected final boolean transferFlags; + + /** @see #transferSavedPSR() */ + protected final boolean transferSavedPSR; + + /** @see #getSourceOperand() */ + protected final OperandWrapper sourceOperand; + + public TransferToStatusRegister(int instr) { + super(instr); + + transferControl = getBit(instr, 16); + transferExtension = getBit(instr, 17); + transferStatus = getBit(instr, 18); + transferFlags = getBit(instr, 19); + + transferSavedPSR = getBit(instr, 22); + + if (getBit(instr, 25)) + sourceOperand = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); + else + sourceOperand = OperandWrapper.decodeShiftedRegister(instr); + } + + /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ + public boolean transferSavedPSR() { + return transferSavedPSR; + } + + /** Returns true if the control field of the PSR shall be overwritten. */ + public boolean transferControlField() { + return transferControl; + } + + /** Returns true if the extension field of the PSR shall be overwritten. */ + public boolean transferExtensionField() { + return transferExtension; + } + + /** Returns true if the status field of the PSR shall be overwritten. */ + public boolean transferStatusField() { + return transferStatus; + } + + /** Returns true if the flag field of the PSR shall be overwritten. */ + public boolean transferFlagField() { + return transferFlags; + } + + /** Returns the operand, which is to be transfered into the status register. */ + public OperandWrapper getSourceOperand() { + return sourceOperand; + } + + /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ + public static boolean conforms(int instr) { + return getBits(instr, 26, 27) == 0 && getBits(instr, 23, 24) == 2 && getBits(instr, 12, 15) == 0; + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-12 15:15:12
|
Revision: 28 http://svn.sourceforge.net/pearcolator/?rev=28&view=rev Author: michael_baer Date: 2007-04-12 08:15:11 -0700 (Thu, 12 Apr 2007) Log Message: ----------- Refactored reading of command line arguments to use a state pattern. Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-04-12 09:35:57 UTC (rev 27) +++ src/org/binarytranslator/DBT_Options.java 2007-04-12 15:15:11 UTC (rev 28) @@ -9,6 +9,7 @@ package org.binarytranslator; import java.util.HashMap; +import java.util.Map; import java.util.Vector; import java.util.Map.Entry; @@ -245,25 +246,59 @@ } } + /** A helper class that uses a state pattern to parse arguments, as given by a Java Main() function. + * The class distinguishes two argument types: Key-Value-Pairs and Remaining arguments. + * Key Value pairs take the form KEY = VALUE and must appear as the first arguments. Remaining arguments + * take the form ARGUMENT1 ARGUMENT2 ARGUMENT3.*/ private static class ArgumentParser { + /** The current parsing state. The class is using a state pattern. */ protected State state; - protected final HashMap<String, String> arguments; + + /** A Key-Value mapping of key to arguments. */ + protected final Map<String, String> arguments; + + /** A list of remaining arguments. See the class documentation to learn about the difference + * between Key-Value and remaining arguments. */ protected final Vector<String> remainingArguments; - public static ArgumentParser parse(String[] args, HashMap<String, String> keyValueArguments, Vector<String> remainingArguments) + /** + * Parses command line arguments. + * @param args + * An array of arguments to parse. This array is usually supplied by a Java Main() method. + * @param keyValueArguments + * Parsed Key-Value argument pairs are stored within this map. + * @param remainingArguments + * Remaining arguments are being stored into this vector. + * @throws ParseException + * A ArgumentParser.ParseException is thrown in case arguments are not properly formatted and could not be parsed. + */ + public static void parse(String[] args, Map<String, String> keyValueArguments, Vector<String> remainingArguments) throws ParseException { ArgumentParser parser = new ArgumentParser(keyValueArguments, remainingArguments); parser.parseArguments(args); - return parser; } - private ArgumentParser(HashMap<String, String> arguments, Vector<String> remainingArguments) { + /** + * Creates a new ArgumentParser instance + * @param arguments + * Parsed Key-Value argument pairs are stored within this map. + * @param remainingArguments + * Remaining arguments are being stored into this vector. + */ + private ArgumentParser(Map<String, String> arguments, Vector<String> remainingArguments) { this.arguments = arguments; this.remainingArguments = remainingArguments; } + /** + * Parses the given arguments into {@link #arguments} and {@link #remainingArguments}. + * @param args + * The arguments that are to be parsed. This array is usually supplied by a Java Main() method. + * @throws ParseException + * A ArgumentParser.ParseException is thrown in case arguments are not properly formatted and could not be parsed. + */ private void parseArguments(String[] args) throws ParseException { switchState(new AwaitingKeyState()); @@ -300,10 +335,12 @@ state.onEnd(); } + /** Switches the parser state to a new state. */ protected void switchState(State s) { state = s; } + /** An exception that is being thrown if parsing fails. */ public static class ParseException extends Exception { protected ParseException(String msg) { @@ -311,12 +348,20 @@ } } + /** Every parser state must implement this interface. Its methods denote the possible inputs + * that might occur during argument parsing. */ private interface State { + /** A text input token has been recognized by the parser. */ void onText(String text) throws ParseException; + + /** An assignment input token (usually the equality symbol) has been recognized by the parser. */ void onAssignment() throws ParseException; + + /** No more input tokens are available. */ void onEnd() throws ParseException; } + /** In this state, key-value arguments are being parsed and the parser awaits a new key. */ private final class AwaitingKeyState implements State { public void onAssignment() throws ParseException { @@ -332,8 +377,10 @@ } } + /** In this state, key-value arguments are being parsed and the parser awaits an assignment operator. */ private final class AwaitingAssignmentState implements State { + /** The previously input key. */ private final String previousInput; public AwaitingAssignmentState(String previousInput) { @@ -358,8 +405,10 @@ } } + /** In this state, key-value arguments are being parsed and the parser awaits a value for a key-value pair. */ private final class ParseValueArgumentState implements State { + /** The previously input key. */ private final String previousInput; public ParseValueArgumentState(String previousInput) { @@ -384,6 +433,7 @@ } } + /** In this state, no more key-value arguments are parsed. All further text nodes are treated as remaining arguments.*/ private final class ParseRemainingArgumentsState implements State { public void onAssignment() throws ParseException { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-12 09:35:56
|
Revision: 27 http://svn.sourceforge.net/pearcolator/?rev=27&view=rev Author: michael_baer Date: 2007-04-12 02:35:57 -0700 (Thu, 12 Apr 2007) Log Message: ----------- Refactored argument parsing to use the state pattern. Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-04-11 21:29:52 UTC (rev 26) +++ src/org/binarytranslator/DBT_Options.java 2007-04-12 09:35:57 UTC (rev 27) @@ -9,6 +9,7 @@ package org.binarytranslator; import java.util.HashMap; +import java.util.Vector; import java.util.Map.Entry; /** @@ -171,7 +172,23 @@ * Read and parse the command line arguments. */ public static void parseArguments(String[] args) { - parseArgumentsToHashmap(args); + + try { + Vector<String> remainingArguments = new Vector<String>(); + ArgumentParser.parse(args, dbtArguments, remainingArguments); + + //did the user give an executable to execute? + if (remainingArguments.size() > 0) { + executableFile = remainingArguments.get(0); + remainingArguments.remove(0); + + executableArguments = new String[remainingArguments.size()]; + remainingArguments.toArray(executableArguments); + } + } + catch (ArgumentParser.ParseException e) { + throw new Error(e.getMessage()); + } for (Entry<String, String> argument : dbtArguments.entrySet()) { String arg = argument.getKey(); @@ -228,67 +245,158 @@ } } - /** - * Takes an array of arguments and parses them as key=value pairs into the hashmap arguments. - */ - private static void parseArgumentsToHashmap(String[] args) { + private static class ArgumentParser { - String key = null; - String value; - int next = 0; + protected State state; + protected final HashMap<String, String> arguments; + protected final Vector<String> remainingArguments; - try { - //are there further arguments? - if (next == args.length) { - return; - } + public static ArgumentParser parse(String[] args, HashMap<String, String> keyValueArguments, Vector<String> remainingArguments) + throws ParseException { - key = args[next++].trim(); + ArgumentParser parser = new ArgumentParser(keyValueArguments, remainingArguments); + parser.parseArguments(args); + return parser; + } + + private ArgumentParser(HashMap<String, String> arguments, Vector<String> remainingArguments) { + this.arguments = arguments; + this.remainingArguments = remainingArguments; + } + + private void parseArguments(String[] args) + throws ParseException { + switchState(new AwaitingKeyState()); - if (!key.startsWith("-")) { - //this is not an argument to the DBT, so it must the file we're trying to execute. - executableFile = key; + int next = 0; + + while (next < args.length) { + String input = args[next++].trim(); - //the remaining arguments may be passed to the executable - executableArguments = new String[args.length - next]; - for (int i = next; i < args.length; i++) - executableArguments[i] = args[next + i]; + int pos = input.indexOf("="); - return; + if (pos == 0) { + //this token has the form "=TEXT" + do { + state.onAssignment(); + input = input.substring(1); + } + while (input.startsWith("=")); + } + else if (pos > 0) { + //the token has the form "TEXT=" + state.onText(input.substring(0, pos)); + state.onAssignment(); + + //handle remaining text (form TEXT=TEXT) + input = input.substring(pos + 1); + } + + if (input.length() > 1) { + state.onText(input); + } } + + state.onEnd(); + } + + protected void switchState(State s) { + state = s; + } + + public static class ParseException extends Exception { + + protected ParseException(String msg) { + super(msg); + } + } + + private interface State { + void onText(String text) throws ParseException; + void onAssignment() throws ParseException; + void onEnd() throws ParseException; + } + + private final class AwaitingKeyState implements State { - //did the user give an argument without spaces in it? - int pos = key.indexOf('='); - if (pos != -1) { - value = key.substring(pos + 1); - key = key.substring(0, pos); + public void onAssignment() throws ParseException { + throw new ParseException("Unexpected token '=' while parsing arguments."); } - else { + + public void onEnd() throws ParseException { + //no further arguments, stop parsing + } + + public void onText(String text) throws ParseException { + switchState(new AwaitingAssignmentState(text)); + } + } + + private final class AwaitingAssignmentState implements State { + + private final String previousInput; + + public AwaitingAssignmentState(String previousInput) { + this.previousInput = previousInput; + } + + public void onAssignment() throws ParseException { + switchState(new ParseValueArgumentState(previousInput)); + } + + public void onEnd() throws ParseException { + //the key has obviously been a single remaining argument + remainingArguments.add(previousInput); + } + + public void onText(String text) throws ParseException { + //the key has obviously been a single remaining argument and now we received the next one + remainingArguments.add(previousInput); + remainingArguments.add(text); - //extract the argument's value - do { - value = args[next++].trim(); - - if (value.startsWith("=")) - { - if (value.length() > 1) - value = value.substring(1); - else - value = ""; - } - } - while ( value.length() == 0 ); + switchState(new ParseRemainingArgumentsState()); } + } + + private final class ParseValueArgumentState implements State { - //store the argument's key and value - if (dbtArguments.containsKey(key)) { - throw new Error(String.format("Parameter %s already defined", key)); + private final String previousInput; + + public ParseValueArgumentState(String previousInput) { + this.previousInput = previousInput; } - - dbtArguments.put(key, value); + + public void onAssignment() throws ParseException { + throw new ParseException("Invalid value for argument '" + previousInput + "'."); + } + + public void onEnd() throws ParseException { + throw new ParseException("Missing value for argument '" + previousInput + "'."); + } + + public void onText(String text) throws ParseException { + if (arguments.containsKey(text)) { + throw new ParseException("Duplicate argument '" + previousInput + "' while parsing arguments."); + } + + arguments.put(previousInput, text); + switchState(new AwaitingKeyState()); + } } - catch (Exception e) { - throw new Error("Invalid argument format for argument " + key); + + private final class ParseRemainingArgumentsState implements State { + + public void onAssignment() throws ParseException { + remainingArguments.add("="); + } + + public void onEnd() throws ParseException { + //no-op + } + + public void onText(String text) throws ParseException { + remainingArguments.add(text); + } } } } Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-04-11 21:29:52 UTC (rev 26) +++ src/org/binarytranslator/Main.java 2007-04-12 09:35:57 UTC (rev 27) @@ -47,18 +47,21 @@ */ public static void main(String[] args) { - if (args.length < 1) { - showUsage(); - return; - } - // Process any arguments for the emulator try { DBT_Options.parseArguments(args); } catch (Exception e) { System.err.println("Error while parsing command line arguments."); System.err.println(e.getMessage()); + showUsage(); + return; } + + if (DBT_Options.executableFile == null) { + System.err.println("Missing executable file name"); + showUsage(); + return; + } ProcessSpace ps; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-11 21:29:52
|
Revision: 26 http://svn.sourceforge.net/pearcolator/?rev=26&view=rev Author: michael_baer Date: 2007-04-11 14:29:52 -0700 (Wed, 11 Apr 2007) Log Message: ----------- Moved memory access functions from GDBTarget to the Memory class Modified Paths: -------------- src/org/binarytranslator/generic/gdbstub/GDBStub.java src/org/binarytranslator/generic/gdbstub/GDBTarget.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Modified: src/org/binarytranslator/generic/gdbstub/GDBStub.java =================================================================== --- src/org/binarytranslator/generic/gdbstub/GDBStub.java 2007-04-11 21:25:11 UTC (rev 25) +++ src/org/binarytranslator/generic/gdbstub/GDBStub.java 2007-04-11 21:29:52 UTC (rev 26) @@ -15,6 +15,7 @@ import java.net.Socket; import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.os.process.ProcessSpace; /** * Interface to GDB @@ -45,6 +46,11 @@ * The process being debugged */ private final GDBTarget target; + + /** + * The currently processed Process Space + */ + private final ProcessSpace ps; /** * Thread to continue or step, a value of -1 means all threads, 0 means any @@ -117,7 +123,7 @@ /** * Constructor */ - public GDBStub(int port, GDBTarget target) { + public GDBStub(int port, ProcessSpace process) { try { ServerSocket connectionSocket = new ServerSocket(port); socket = connectionSocket.accept(); @@ -129,7 +135,8 @@ throw new Error("Error opening socket", e); } breakpoints = new int[0]; - this.target = target; + this.ps = process; + this.target = process.getGDBTarget(); } /** @@ -464,7 +471,7 @@ try { byte value[] = new byte[count * 2]; for (int i = 0; i < count; i++) { - byte byteVal = target.memoryLoad8(address + i); + byte byteVal = (byte)ps.memory.loadUnsigned8(address + i); value[i * 2] = intToHex(byteVal >> 4); value[(i * 2) + 1] = intToHex(byteVal); } @@ -489,7 +496,7 @@ for (int i = 0; i < count; i++) { byte byteVal = (byte) ((hexToInt(buffer[start + (i * 2)]) << 4) | (hexToInt(buffer[start + (i * 2) + 1]))); - target.memoryStore8(address + i, byteVal); + ps.memory.store8(address + i, byteVal); } replyOK(); } catch (NullPointerException e) { Modified: src/org/binarytranslator/generic/gdbstub/GDBTarget.java =================================================================== --- src/org/binarytranslator/generic/gdbstub/GDBTarget.java 2007-04-11 21:25:11 UTC (rev 25) +++ src/org/binarytranslator/generic/gdbstub/GDBTarget.java 2007-04-11 21:29:52 UTC (rev 26) @@ -40,14 +40,4 @@ * 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/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-11 21:25:11 UTC (rev 25) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-11 21:29:52 UTC (rev 26) @@ -66,20 +66,6 @@ */ public Memory memory; - /** - * Load a 8bit value from memory - */ - public byte memoryLoad8(int address) { - return (byte) memory.loadSigned8(address); - } - - /** - * Store a 8bit value to memory - */ - public void memoryStore8(int address, byte data) { - memory.store8(address, data); - } - /* * Utility functions */ @@ -334,7 +320,7 @@ System.out.println(e.toString()); } } else { - GDBStub gdbStub = new GDBStub(DBT_Options.gdbStubPort, getGDBTarget()); + GDBStub gdbStub = new GDBStub(DBT_Options.gdbStubPort, this); gdbStub.run(); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-11 21:25:11
|
Revision: 25 http://svn.sourceforge.net/pearcolator/?rev=25&view=rev Author: michael_baer Date: 2007-04-11 14:25:11 -0700 (Wed, 11 Apr 2007) Log Message: ----------- Moved memory access functions from interface LinuxSystemCallGenerator to the Memory class Modified Paths: -------------- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-11 21:25:11 UTC (rev 25) @@ -231,7 +231,7 @@ */ public PPC_InstructionDecoder interpretInstruction(PPC_ProcessSpace ps) throws BadInstructionException { - ps.currentInstruction = ps.memoryLoad32(ps.getCurrentInstructionAddress()); + ps.currentInstruction = ps.memory.load32(ps.getCurrentInstructionAddress()); try { return getDecoder(ps.currentInstruction).interpretInstruction(ps); } catch (NullPointerException e) { @@ -246,7 +246,7 @@ protected static PPC_InstructionDecoder moveInstructionOnAndReturnDecoder( PPC_ProcessSpace ps) { ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress() + 4); - ps.currentInstruction = ps.memoryLoad32(ps.getCurrentInstructionAddress()); + ps.currentInstruction = ps.memory.load32(ps.getCurrentInstructionAddress()); return findDecoder(ps.currentInstruction); } @@ -264,7 +264,7 @@ */ public static int translateInstruction(PPC2IR ppc2ir, PPC_ProcessSpace ps, PPC_Laziness lazy, int pc) { - int instr = ps.memoryLoad32(pc); + int instr = ps.memory.load32(pc); if (DBT_Options.debugInstr) { System.out.println(lazy.makeKey(pc) + PPC_Disassembler.disasm(instr, pc) @@ -3593,7 +3593,7 @@ int d = EXTS(bits(ps.currentInstruction, 16, 31), 16); int EA = (rA == 0) ? d : (ps.getRegister(rA) + d); int value = Float.floatToIntBits((float) ps.getFPregister(frS)); - ps.memoryStore32(EA, value); + ps.memory.store32(EA, value); return moveInstructionOnAndReturnDecoder(ps); } @@ -3654,7 +3654,7 @@ int d = EXTS(bits(ps.currentInstruction, 16, 31), 16); int EA = (rA == 0) ? d : (ps.getRegister(rA) + d); int value = Float.floatToIntBits((float) ps.getFPregister(frS)); - ps.memoryStore32(EA, value); + ps.memory.store32(EA, value); ps.setRegister(rA, EA); return moveInstructionOnAndReturnDecoder(ps); } @@ -3965,7 +3965,7 @@ } } ps.setCurrentInstructionAddress(target_address); - ps.currentInstruction = ps.memoryLoad32(target_address); + ps.currentInstruction = ps.memory.load32(target_address); return findDecoder(ps.currentInstruction); } @@ -4626,7 +4626,7 @@ } } ps.setCurrentInstructionAddress(target_address); - ps.currentInstruction = ps.memoryLoad32(target_address); + ps.currentInstruction = ps.memory.load32(target_address); return findDecoder(ps.currentInstruction); } @@ -11662,7 +11662,7 @@ } } ps.setCurrentInstructionAddress(target_address); - ps.currentInstruction = ps.memoryLoad32(target_address); + ps.currentInstruction = ps.memory.load32(target_address); return findDecoder(ps.currentInstruction); } @@ -11806,7 +11806,7 @@ .getCurrentInstructionAddress() + 4, target_address); } ps.setCurrentInstructionAddress(target_address); - ps.currentInstruction = ps.memoryLoad32(target_address); + ps.currentInstruction = ps.memory.load32(target_address); return findDecoder(ps.currentInstruction); } Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-11 21:25:11 UTC (rev 25) @@ -992,7 +992,7 @@ * Run a single instruction */ public void runOneInstruction() throws BadInstructionException { - currentInstruction = memoryLoad32(pc); + currentInstruction = memory.load32(pc); try { PPC_InstructionDecoder.findDecoder(currentInstruction) .interpretInstruction(this); 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-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-11 21:25:11 UTC (rev 25) @@ -16,6 +16,7 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.process.ProcessSpace; /** * Simulate the process address space for our PowerPC ELF binary. Also keep @@ -203,4 +204,8 @@ return false; } + public ProcessSpace getProcessSpace() { + 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-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-11 21:25:11 UTC (rev 25) @@ -16,6 +16,7 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.process.ProcessSpace; /** * Linux specific parts of the process @@ -166,4 +167,8 @@ public byte[] getPlatformString() { return new byte[] {'\0', '6', '8', '6', 'i'}; } + + public ProcessSpace getProcessSpace() { + return this; + } } Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-04-11 21:25:11 UTC (rev 25) @@ -9,6 +9,7 @@ package org.binarytranslator.generic.os.abi.linux; import org.binarytranslator.generic.memory.MemoryMapException; +import org.binarytranslator.generic.os.process.ProcessSpace; /** * Class encapsulating the interface between Linux system calls and @@ -56,39 +57,13 @@ * @param address where to write * @param data value to store */ - public void memoryStore32(int address, int data); + /** - * Write to the memory of the system call generator an 8bit value - * @param address where to write - * @param data value to store - */ - public void memoryStore8(int address, byte data); + * Returns the process space that this call originated from. + */ + public ProcessSpace getProcessSpace(); + /** - * Load from memory of the system call generator an 8bit value - * @param address where to read - * @return value read - */ - public byte memoryLoad8(int address); - /** - * Load from memory of the system call generator a 32bit value - * @param address where to read - * @return value read - */ - public int memoryLoad32(int address); - /** - * 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 - */ - public String memoryReadString(int address); - /** - * 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); - /** * Get the top of the BSS segment (the heap that reside below the * stack in memory) * @return top of BSS segment @@ -100,13 +75,4 @@ * @param address new top of BSS segment */ public void setBrk(int address); - /** - * 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 - */ - public int memoryMap(int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException; } Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-11 21:25:11 UTC (rev 25) @@ -10,6 +10,7 @@ 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; @@ -62,7 +63,44 @@ * 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) { @@ -489,13 +527,15 @@ 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++) { - src.memoryStore32(buf + i, b[i]); + mem.store32(buf + i, b[i]); } src.setSysCallReturn(len); } @@ -518,7 +558,7 @@ while((b < count) && ((i = raFile.read()) != -1)) { byte by = (byte)i; b++; - src.memoryStore8(addr++, by); + mem.store8(addr++, by); } src.setSysCallReturn(b); // Return number of bytes read. } @@ -538,15 +578,17 @@ 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) src.memoryLoad8(buf + 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) src.memoryLoad8(buf + c)); + System.err.print((char) mem.loadUnsigned8(buf + c)); } src.setSysCallReturn(count); } else { @@ -564,7 +606,7 @@ try { for(b = 1 ; b <= count ; b++) { - by = src.memoryLoad8(addr++); + by = (byte) mem.loadUnsigned8(addr++); raFile.write(by); } // Return number of bytes written, having accounted for b @@ -588,20 +630,21 @@ int fd = arguments.nextInt(); int vector = arguments.nextInt(); int count = arguments.nextInt(); + Memory mem = src.getProcessSpace().memory; if((fd == 1)||(fd == 2)) { // stdout || stderr - int base = src.memoryLoad32(vector); - int len = src.memoryLoad32(vector+4); + 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 = src.memoryLoad32(vector+(currentVector*8)); - len = src.memoryLoad32(vector+(currentVector*8)+4); + base = mem.load32(vector+(currentVector*8)); + len = mem.load32(vector+(currentVector*8)+4); curVectorPos = 0; } - System.out.print((char) src.memoryLoad8(base + curVectorPos)); + System.out.print((char) mem.loadUnsigned8(base + curVectorPos)); curVectorPos++; } src.setSysCallReturn(count); @@ -618,7 +661,7 @@ // Examine the flags argument and open read or read-write // accordingly. args[0] points to the file name. - String fileName = src.memoryReadString(pathname); + String fileName = memoryReadString(pathname); // Create a File object so we can test for the existance and // properties of the file. @@ -760,12 +803,12 @@ hostName = localhostString.substring(0,index); } // Fill in utsname struct - see /usr/include/sys/utsname.h - 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 + 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 { @@ -786,7 +829,9 @@ int offset = arguments.nextInt(); if((flags & mman.MAP_ANONYMOUS) != 0 ) { try { - src.setSysCallReturn(src.memoryMap(start, length, + 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)); Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-11 21:25:11 UTC (rev 25) @@ -67,34 +67,6 @@ public Memory memory; /** - * Load a 32bit value from memory - */ - public int memoryLoad32(int wordAddr) { - return memory.load32(wordAddr); - } - - /** - * Store a 32bit value to memory - */ - public void memoryStore32(int address, int data) { - memory.store32(address, data); - } - - /** - * Load a 16bit value from memory - */ - public int memoryLoad16(int hwAddr) { - return memory.loadSigned16(hwAddr); - } - - /** - * Store a 16bit value to memory - */ - public void memoryStore16(int hwAddr, int iValue) { - memory.store16(hwAddr, iValue); - } - - /** * Load a 8bit value from memory */ public byte memoryLoad8(int address) { @@ -108,63 +80,6 @@ memory.store8(address, data); } - /** - * Read an ASCIIZ string from the process' memory into a Java String - */ - public String memoryReadString(int address) { - StringBuffer str = new StringBuffer(); - char c; - - while ((c = (char) memoryLoad8(address++)) != 0) - str.append(c); - - return str.toString(); - } - - /** - * Write a Java string (crudely) to an ASCIIZ string in the process' memory - */ - public void memoryWriteString(int byteAddr, String value) { - if (value != null) { - for (int i = 0; i < value.length(); i++) { - memoryStore8(byteAddr + i, (byte) value.charAt(i)); - } - memoryStore8(byteAddr + value.length(), (byte) 0); - } - } - - /** - * 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 - */ - public int memoryMap(int addr, int len, boolean read, boolean write, - boolean exec) throws MemoryMapException { - return memory.map(addr, len, read, write, exec); - } - - /** - * Simulate an munmap system call. - * - * @param start - * start of memory area to unmap. - * @param length - * length of area. - */ - public int munmap(int start, int length) { - memory.unmap(start, length); - return 0; - } - /* * Utility functions */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |