Index: frysk-imports/lib/opcodes/Disassembler.java =================================================================== RCS file: /cvs/frysk/frysk-imports/lib/opcodes/Disassembler.java,v retrieving revision 1.4 diff -u -r1.4 Disassembler.java --- frysk-imports/lib/opcodes/Disassembler.java 14 Jul 2006 14:51:29 -0000 1.4 +++ frysk-imports/lib/opcodes/Disassembler.java 3 Sep 2006 06:53:31 -0000 @@ -59,7 +59,7 @@ } public LinkedList disassembleInstructions (long address, long count) - throws OpcodesException + throws OpcodesException { this.isnList = new LinkedList(); current = new Instruction(); @@ -79,7 +79,15 @@ // It is not private because it is called from CNI protected void setCurrentInstruction (String inst) { - current.instruction = inst; + // libopcdes will call this function for more than one time to print + // one instruction. So append INST to INSTRUCTION to avoid overwrite. + current.instruction += inst; + } + // THIS SHOULD NOT BE CALLED FROM JAVA! + // It is not private because it is called from CNI + protected void setCurrentInstructionLength (int len) + { + current.length = len; } // THIS SHOULD NOT BE CALLED FROM JAVA! Index: frysk-imports/lib/opcodes/Instruction.java =================================================================== RCS file: /cvs/frysk/frysk-imports/lib/opcodes/Instruction.java,v retrieving revision 1.2 diff -u -r1.2 Instruction.java --- frysk-imports/lib/opcodes/Instruction.java 15 May 2006 20:31:42 -0000 1.2 +++ frysk-imports/lib/opcodes/Instruction.java 3 Sep 2006 06:53:32 -0000 @@ -38,12 +38,21 @@ // exception. package lib.opcodes; -public class Instruction { +public class Instruction +{ + public long address; + public int length; + public String instruction; - public long address; - public String instruction; - - public String toString(){ - return "0x"+Long.toHexString(address)+"\t"+instruction; - } + public String toString() + { + return "0x"+Long.toHexString(address)+"\t"+instruction; + } + + Instruction() + { + address = -1; + length = 0; + instruction = new String(); + } } Index: frysk-imports/lib/opcodes/cni/Disassembler.cxx =================================================================== RCS file: /cvs/frysk/frysk-imports/lib/opcodes/cni/Disassembler.cxx,v retrieving revision 1.6 diff -u -r1.6 Disassembler.cxx --- frysk-imports/lib/opcodes/cni/Disassembler.cxx 14 Jul 2006 14:51:29 -0000 1.6 +++ frysk-imports/lib/opcodes/cni/Disassembler.cxx 3 Sep 2006 06:53:33 -0000 @@ -64,7 +64,7 @@ // reads number of bytes from the byte buffer int read_from_byte_buffer(bfd_vma memaddr, bfd_byte* myadd, unsigned int length, - struct disassemble_info *info); + struct disassemble_info *info); // throws an OpcodesException void error_func(int status, bfd_vma memaddr, struct disassemble_info *info); @@ -79,79 +79,84 @@ lib::opcodes::Disassembler::disassemble (jlong address, jlong instructions) { - disassemble_info disasm_info; - int (*disasm_func) (bfd_vma, disassemble_info*); + disassemble_info disasm_info; + int (*disasm_func) (bfd_vma, disassemble_info*); + int instr_length; - ::init_disassemble_info (&disasm_info, (void*) this, save_instruction); + ::init_disassemble_info (&disasm_info, (void*) this, save_instruction); - disasm_info.flavour = bfd_target_unknown_flavour; + disasm_info.flavour = bfd_target_unknown_flavour; #ifdef __x86_64__ - disasm_info.arch = bfd_arch_i386; - disasm_info.mach = bfd_mach_x86_64; - disasm_func = &(::print_insn_i386_intel); + disasm_info.arch = bfd_arch_i386; + disasm_info.mach = bfd_mach_x86_64; + disasm_func = &(::print_insn_i386_att); #elif defined (__i386__) - disasm_info.arch = bfd_arch_i386; - disasm_info.mach = bfd_mach_i386_i386; - disasm_func = &(::print_insn_i386_intel); + disasm_info.arch = bfd_arch_i386; + disasm_info.mach = bfd_mach_i386_i386; + disasm_func = &(::print_insn_i386_att); #elif defined (__powerpc64__) - disasm_info.arch = bfd_arch_powerpc; - disasm_info.mach = bfd_mach_ppc64; - disasm_func = &(::print_insn_big_powerpc); + disasm_info.arch = bfd_arch_powerpc; + disasm_info.mach = bfd_mach_ppc64; + disasm_func = &(::print_insn_big_powerpc); #elif defined (__powerpc__) - disasm_info.arch = bfd_arch_powerpc; - disasm_info.mach = bfd_mach_ppc; - disasm_func = &(::print_insn_big_powerpc); + disasm_info.arch = bfd_arch_powerpc; + disasm_info.mach = bfd_mach_ppc; + disasm_func = &(::print_insn_big_powerpc); #elif defined (__ia64__) - disasm_info.arch = bfd_arch_ia64; - disasm_info.mach = bfd_mach_ia64_elf64; // TODO: which mach? elf32 or elf64? - disasm_func =&(::print_insn_ia64); + disasm_info.arch = bfd_arch_ia64; + disasm_info.mach = bfd_mach_ia64_elf64; // TODO: which mach? elf32 or elf64? + disasm_func =&(::print_insn_ia64); #elif defined (__s390__) - disasm_info.arch = bfd_arch_s390; - disasm_info.mach = bfd_mach_s390_31; - disasm_func = &(::print_insn_s390); + disasm_info.arch = bfd_arch_s390; + disasm_info.mach = bfd_mach_s390_31; + disasm_func = &(::print_insn_s390); #elif defined (__s390x__) - disasm_info.arch = bfd_arch_s390; - disasm_info.mach = bfd_mach_s390_64; - disasm_func = &(::print_insn_s390); + disasm_info.arch = bfd_arch_s390; + disasm_info.mach = bfd_mach_s390_64; + disasm_func = &(::print_insn_s390); #endif - if (!disasm_func) - throw new lib::opcodes::OpcodesException( - JvNewStringUTF("Error: Unsupported architechture")); + if (!disasm_func) + throw new lib::opcodes::OpcodesException(JvNewStringUTF("Error: Unsupported architechture")); - disasm_info.read_memory_func = read_from_byte_buffer; - disasm_info.memory_error_func = error_func; - disasm_info.print_address_func = print_addr; - - bfd_vma current_address = (bfd_vma) address; - - for (int i = 0; i < instructions; i++) - { - this->setCurrentAddress(current_address); - current_address += disasm_func(current_address, &disasm_info); - this->moveToNext(); - } + disasm_info.read_memory_func = read_from_byte_buffer; + disasm_info.memory_error_func = error_func; + disasm_info.print_address_func = print_addr; + + bfd_vma current_address = (bfd_vma) address; + + for (int i = 0; i < instructions; i++) + { + this->setCurrentAddress(current_address); + instr_length = disasm_func(current_address, &disasm_info); + current_address += instr_length; + + this->setCurrentInstructionLength(instr_length); + this->moveToNext(); + } } /* * Instead of copying memory from memaddr to myadd, we get the section * starting at memaddr in the ByteBuffer. */ -int read_from_byte_buffer (bfd_vma memaddr, bfd_byte* myadd, unsigned int length, - struct disassemble_info *info) +int read_from_byte_buffer (bfd_vma memaddr, bfd_byte* myadd, + unsigned int length, + struct disassemble_info *info) { - lib::opcodes::Disassembler *obj = (lib::opcodes::Disassembler*) info->stream; - inua::eio::ByteBuffer *buffer = obj->buffer; - - char tmp[length]; - for(unsigned int i = 0; i < length; i++){ - long offset = ((long) memaddr) + i; - tmp[i] = (char) buffer->getByte (offset); - } - - memcpy ((void*) myadd, (void*) tmp, length); - - return 0; + lib::opcodes::Disassembler *obj = (lib::opcodes::Disassembler*) info->stream; + inua::eio::ByteBuffer *buffer = obj->buffer; + + char tmp[length]; + for(unsigned int i = 0; i < length; i++) + { + long offset = ((long) memaddr) + i; + tmp[i] = (char) buffer->getByte (offset); + } + + memcpy ((void*) myadd, (void*) tmp, length); + + return 0; } /* @@ -159,9 +164,12 @@ */ void error_func (int status, bfd_vma memaddr, struct disassemble_info *info) { - throw new lib::opcodes::OpcodesException( - JvNewStringUTF("Error occured while disassembling."), (jint) status, (jlong) memaddr - ); + throw new + lib::opcodes::OpcodesException( + JvNewStringUTF("Error occured while disassembling."), + (jint) status, + (jlong) memaddr + ); } void print_addr (bfd_vma addr, struct disassemble_info *info) {} @@ -171,23 +179,24 @@ */ int save_instruction (void* disassembler, const char *args, ...) { - lib::opcodes::Disassembler* obj = (lib::opcodes::Disassembler*) disassembler; - - va_list ap; - ::va_start (ap, args); - char * mystr; - if(::vasprintf (&mystr, args, ap) > 0){ - obj->setCurrentInstruction (JvNewStringUTF (mystr)); - ::free (mystr); - } - else - { - throw new lib::opcodes::OpcodesException( - JvNewStringUTF("Could not parse variable argument list")); - } - ::va_end(ap); + lib::opcodes::Disassembler* obj = (lib::opcodes::Disassembler*) disassembler; - int len = strlen (mystr); + va_list ap; + ::va_start (ap, args); + char * mystr; + if(::vasprintf (&mystr, args, ap) > 0) + { + obj->setCurrentInstruction (JvNewStringUTF (mystr)); + ::free (mystr); + } + else + { + throw new + lib::opcodes::OpcodesException(JvNewStringUTF("Could not parse variable argument list")); + } + ::va_end(ap); - return len; + int len = strlen (mystr); + + return len; } Index: frysk-imports/lib/opcodes/tests/DummyByteBuffer.java =================================================================== RCS file: /cvs/frysk/frysk-imports/lib/opcodes/tests/DummyByteBuffer.java,v retrieving revision 1.2 diff -u -r1.2 DummyByteBuffer.java --- frysk-imports/lib/opcodes/tests/DummyByteBuffer.java 24 May 2006 19:07:27 -0000 1.2 +++ frysk-imports/lib/opcodes/tests/DummyByteBuffer.java 3 Sep 2006 06:53:33 -0000 @@ -39,25 +39,68 @@ package lib.opcodes.tests; import inua.eio.ByteBuffer; +import frysk.imports.Build; -public class DummyByteBuffer extends ByteBuffer { +public class DummyByteBuffer + extends ByteBuffer +{ - private byte[] bytes = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7}; - - public DummyByteBuffer(){ - super(0, 8); - } - - protected int peek(long caret) { - if(caret < bytes.length && caret > 0) - return bytes[(int) caret]; - - return -1; - } - - protected void poke(long caret, int val) { - if(caret < bytes.length && caret > 0) - bytes[(int) caret] = (byte) val; - } + private byte bytes[]; + + public DummyByteBuffer() + { + super(0, 8); + if (Build.BUILD_ARCH.indexOf("powerpc") != - 1) + { + bytes = new byte[] + { + 0x4e, (byte)0x80, 0x04, 0x20, // bctr + 0x44, 0x00, 0x00, 0x02, // sc + 0x4e, (byte)0x80, 0x00, 0x20, // blr + 0x60, 0x00, 0x00, 0x00, // nop + 0x38, 0x00, 0x00, 0x02, // li r0,2 + 0x39, (byte)0x8c, 0x03, 0x68, // addi r12,r12,872 + 0x38, 0x21, 0x00, 0x70, // addi r1,r1,112 + (byte)0x7d, 0x69, 0x03, (byte)0xa6, // mtctr r11 + (byte)0x78, (byte)0xa5, 0x26, (byte) 0xc6 // rldicr r5,r5,36,27 + }; + + } + else if (Build.BUILD_ARCH.indexOf("_64") != - 1) + { + bytes = new byte[] + { + 0, 1, // add %al,(%rcx) + 2, 3, // add (%rbx),%al + 4, 5, // add $0x5,%al + 6, // (bad) + 7 // (bad) + }; + } + else + { + bytes = new byte[] + { + 0, 1, // add %al,(%ecx) + 2, 3, // add (%ebx),$al + 4, 5, // add $0x5,%al + 6, // push %es + 7 // pop %es + }; + } + } + + protected int peek(long caret) + { + if(caret < bytes.length && caret >= 0) + return bytes[(int) caret]; + return -1; + } + + protected void poke(long caret, int val) + { + if(caret < bytes.length && caret >= 0) + bytes[(int) caret] = (byte) val; + } } Index: frysk-imports/lib/opcodes/tests/TestOpcodes.java =================================================================== RCS file: /cvs/frysk/frysk-imports/lib/opcodes/tests/TestOpcodes.java,v retrieving revision 1.10 diff -u -r1.10 TestOpcodes.java --- frysk-imports/lib/opcodes/tests/TestOpcodes.java 28 Aug 2006 17:36:37 -0000 1.10 +++ frysk-imports/lib/opcodes/tests/TestOpcodes.java 3 Sep 2006 06:53:33 -0000 @@ -51,17 +51,10 @@ import frysk.imports.Build; public class TestOpcodes - extends TestCase + extends TestCase { - /* - * Note: this test is expected to fail on anything but i386 for the time - * being. TODO: come up with a way of doing the correct assertEquals for other - * archs - */ public void testDisassembler () { - if (brokenPpcXXX(2712)) - return; ByteBuffer buffer = new DummyByteBuffer(); final int numInstructions = 16; @@ -81,39 +74,62 @@ assertNotNull(list); assertEquals(list.size(), numInstructions); - String[] addrs = { "0", "2", "4", "6", "7", "8", "a", "c", "e", "f", "10", - "12", "14", "16", "17", "18" }; + String[] insts = new String[0]; + // Address for DummyByteBuffer is started at 0x00. + int address = 0; - String[] insts; - - boolean is64 = Build.BUILD_ARCH.indexOf("_64") != - 1; - - if (! is64) + // for powerpc and powerpc64. + if (Build.BUILD_ARCH.indexOf("powerpc") != - 1) { - insts = new String[] { "DWORD PTR [ecx]", "BYTE PTR [ebx]", "0x5", - "es", "es", "al", "BYTE PTR [ebx]", "0x5", "es", - "es", "al", "BYTE PTR [ebx]", "0x5", "es", "es", - "al" }; - + insts = new String[] + { + "bctr", + "sc", + "blr", + "nop", + "li r0,2", + "addi r12,r12,872", + "addi r1,r1,112", + "mtctr r11", + "rldicr r5,r5,36,27" + }; } - else + // for X86_64. + else if (Build.BUILD_ARCH.indexOf("_64") != - 1) { - insts = new String[] { "DWORD PTR [rcx]", "BYTE PTR [rbx]", "0x5", - "(bad) ", "(bad) ", "al", "BYTE PTR [rbx]", - "0x5", "(bad) ", "(bad) ", "al" }; + insts = new String[] + { + "add %al,(%rcx)", + "add (%rbx),%al", + "add $0x5,%al", + "(bad)", + "(bad)" + }; + } + // for X86. + else if(Build.BUILD_ARCH.indexOf("86") != - 1) + { + insts = new String[] + { "add %al,(%ecx)", + "add (%ebx),%al", + "add $0x5,%al", + "push %es", + "pop %es", + }; } assertNotNull(insts); - int instCount = is64 ? 11 : 16; - - for (int i = 0; i < instCount; i++) + for (int i = 0; i < insts.length; i++) { Instruction inst = (Instruction) list.get(i); assertNotNull(inst); - assertEquals(addrs[i], Long.toHexString(inst.address)); - assertEquals(insts[i], inst.instruction); + assertEquals(address, inst.address); + // Remve tailing whiespace before compare. + assertEquals(insts[i], inst.instruction.trim()); + + address += inst.length; } } }