Mercurial > projects > ddbg_continued
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 ); + } +}