diff src/disasm.d @ 1:4a9dcbd9e54f

-files of 0.13 beta -fixes so that it now compiles with the current dmd version
author marton@basel.hu
date Tue, 05 Apr 2011 20:44:01 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/disasm.d	Tue Apr 05 20:44:01 2011 +0200
@@ -0,0 +1,162 @@
+/*  Ddbg - Win32 Debugger for the D programming language
+ *  Copyright (c) 2007 Jascha Wetzel
+ *  All rights reserved. See LICENSE.TXT for details.
+ */
+
+import util;
+import dbgprocess;
+import dbgthread;
+public import udis86;
+import util;
+
+import std.string;
+
+import win32.winnt;
+
+class DisAsm
+{
+    /**********************************************************************************************
+        Calculates the absolute destination address of a jxx or call instruction.
+        Params: is_imm = if true, only JIMM destinations will be considered. Out value is whether destination was JIMM
+    **********************************************************************************************/
+	static int calcJumpDestination(DbgProcess process, DbgThread thread, ud_t* ud_obj, inout bool is_imm)
+	{
+		if ( !isConditionalJump(ud_obj.mnemonic)
+			&& ud_obj.mnemonic != ud_mnemonic_code.UD_Icall
+			&& ud_obj.mnemonic != ud_mnemonic_code.UD_Ijmp )
+			return 0;
+
+		uint address, destination;
+		if ( ud_obj.operand[0].type == ud_type.UD_OP_MEM || ud_obj.operand[0].type == ud_type.UD_OP_REG )
+		{
+			if ( is_imm ) {
+				is_imm = false;
+				return 0;
+			}
+			is_imm = false;
+			CONTEXT ctx;
+			thread.getContext(ctx, CONTEXT_FULL);
+			switch ( ud_obj.operand[0].base )
+			{
+			    case ud_type.UD_NONE:   break;
+				case ud_type.UD_R_EAX:	address = ctx.Eax;	break;
+				case ud_type.UD_R_EBX:	address = ctx.Ebx;	break;
+				case ud_type.UD_R_ECX:	address = ctx.Ecx;	break;
+				case ud_type.UD_R_EDX:	address = ctx.Edx;	break;
+				case ud_type.UD_R_ESI:	address = ctx.Esi;	break;
+				case ud_type.UD_R_EDI:	address = ctx.Edi;	break;
+				default:
+					DbgIO.println("WARNING: yet unsupported register 0x%x used in jmp/call destination", ud_obj.operand[0].base);
+					break;
+			}
+			if ( ud_obj.operand[0].type == ud_type.UD_OP_MEM )
+			{
+                switch ( ud_obj.operand[0].offset )
+                {
+                    case 8:		address += ud_obj.operand[0].lval._ubyte;	break;
+                    case 16:	address += ud_obj.operand[0].lval.uword;	break;
+                    case 32:	address += ud_obj.operand[0].lval.udword;	break;
+                    default:
+                        DbgIO.println("WARNING: yet unsupported offset size used in jmp/call destination");
+                        break;
+                }
+                process.readProcessMemory(address, &destination, uint.sizeof);
+			}
+			else
+                destination = address;
+		}
+		else if ( ud_obj.operand[0].type == ud_type.UD_OP_JIMM )
+		{
+			is_imm = true;
+			address		= cast(uint)ud_insn_off(ud_obj);
+			destination	= address+ud_insn_len(ud_obj);
+			switch ( ud_obj.operand[0].size )
+			{
+				case 8:
+					destination += ud_obj.operand[0].lval.sbyte;
+					break;
+				case 16:
+					destination += ud_obj.operand[0].lval.sword;
+					break;
+				case 32:
+					destination += ud_obj.operand[0].lval.sdword;
+					break;
+				case 48:
+					DbgIO.println("WARNING: 48bit immediate jump destinations not implemented, yet");
+					break;
+				case 64:
+					DbgIO.println("WARNING: 64bit immediate jump destinations not implemented, yet");
+					break;
+                default:
+                    assert(0);
+			}
+		}
+		else
+			DbgIO.println("yet unsupported jmp/call destination");
+		return destination;
+	}
+
+    /**********************************************************************************************
+        Test if given mnemonic a a conditional jump (i.e. jxx, not jmp).
+    **********************************************************************************************/
+	static bool isConditionalJump(ud_mnemonic_code opcode)
+	{
+		if ( ud_mnemonic_code.UD_Ijmp == opcode )
+			return false;
+		if ( ud_mnemonic_code.UD_Ijcxz <= opcode && ud_mnemonic_code.UD_Ijnle >= opcode )
+			return true;
+		if ( ud_mnemonic_code.UD_Ija <= opcode && ud_mnemonic_code.UD_Ijnc >= opcode )
+			return true;
+		if ( ud_mnemonic_code.UD_Iloop <= opcode && ud_mnemonic_code.UD_Iloopz >= opcode )
+			return true;
+		return false;
+	}
+
+    /**********************************************************************************************
+        Wrapper function for disassembly. Calls the delegate callback for each instruction.
+    **********************************************************************************************/
+	static void disasm(DbgProcess process, uint start, uint stop, bool delegate(ud_t*) callback)
+	{
+		ubyte[]	code;
+
+		bool disasm(uint length, bool abort_at_ret)
+		{
+			ud_t	ud_obj;
+			ud_init(&ud_obj);
+			ud_set_pc(&ud_obj, start);
+			ud_set_input_buffer(&ud_obj, code.ptr, length);
+			ud_set_mode(&ud_obj, 32);
+			ud_set_syntax(&ud_obj, &ud_translate_intel);
+
+			// init callback
+			callback(cast(ud_t*)null);
+
+			while ( ud_disassemble(&ud_obj) )
+			{
+				if ( !callback(&ud_obj) )
+					return false;
+				if ( abort_at_ret && (ud_obj.mnemonic == ud_mnemonic_code.UD_Iret || ud_obj.mnemonic == ud_mnemonic_code.UD_Iretf) )
+					return false;
+			}
+			return true;
+		}
+
+		if ( stop > 0 && stop <= start ) {
+			DbgIO.println("ERROR: invalid address range: Eip=0x%x >= 0x%x", start, stop);
+			return;
+		}
+
+		code.length = stop>0?stop-start:512;
+		bool more;
+		uint read;
+		do
+		{
+			read = process.readProcessMemory(start, code.ptr, code.length);
+			if ( read == 0 )
+				DbgIO.println("ERROR: Couldn't read from process' memory for disassembly: %s", lastError);
+			if ( read > 0 )
+				more = disasm(read, stop==0);
+			start += code.length;
+		} while ( stop == 0 && more && read > 0 );
+	}
+}