Mercurial > projects > ddbg_continued
view 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 source
/* 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 ); } }