comparison 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
comparison
equal deleted inserted replaced
0:586e4a649642 1:4a9dcbd9e54f
1 /* Ddbg - Win32 Debugger for the D programming language
2 * Copyright (c) 2007 Jascha Wetzel
3 * All rights reserved. See LICENSE.TXT for details.
4 */
5
6 import util;
7 import dbgprocess;
8 import dbgthread;
9 public import udis86;
10 import util;
11
12 import std.string;
13
14 import win32.winnt;
15
16 class DisAsm
17 {
18 /**********************************************************************************************
19 Calculates the absolute destination address of a jxx or call instruction.
20 Params: is_imm = if true, only JIMM destinations will be considered. Out value is whether destination was JIMM
21 **********************************************************************************************/
22 static int calcJumpDestination(DbgProcess process, DbgThread thread, ud_t* ud_obj, inout bool is_imm)
23 {
24 if ( !isConditionalJump(ud_obj.mnemonic)
25 && ud_obj.mnemonic != ud_mnemonic_code.UD_Icall
26 && ud_obj.mnemonic != ud_mnemonic_code.UD_Ijmp )
27 return 0;
28
29 uint address, destination;
30 if ( ud_obj.operand[0].type == ud_type.UD_OP_MEM || ud_obj.operand[0].type == ud_type.UD_OP_REG )
31 {
32 if ( is_imm ) {
33 is_imm = false;
34 return 0;
35 }
36 is_imm = false;
37 CONTEXT ctx;
38 thread.getContext(ctx, CONTEXT_FULL);
39 switch ( ud_obj.operand[0].base )
40 {
41 case ud_type.UD_NONE: break;
42 case ud_type.UD_R_EAX: address = ctx.Eax; break;
43 case ud_type.UD_R_EBX: address = ctx.Ebx; break;
44 case ud_type.UD_R_ECX: address = ctx.Ecx; break;
45 case ud_type.UD_R_EDX: address = ctx.Edx; break;
46 case ud_type.UD_R_ESI: address = ctx.Esi; break;
47 case ud_type.UD_R_EDI: address = ctx.Edi; break;
48 default:
49 DbgIO.println("WARNING: yet unsupported register 0x%x used in jmp/call destination", ud_obj.operand[0].base);
50 break;
51 }
52 if ( ud_obj.operand[0].type == ud_type.UD_OP_MEM )
53 {
54 switch ( ud_obj.operand[0].offset )
55 {
56 case 8: address += ud_obj.operand[0].lval._ubyte; break;
57 case 16: address += ud_obj.operand[0].lval.uword; break;
58 case 32: address += ud_obj.operand[0].lval.udword; break;
59 default:
60 DbgIO.println("WARNING: yet unsupported offset size used in jmp/call destination");
61 break;
62 }
63 process.readProcessMemory(address, &destination, uint.sizeof);
64 }
65 else
66 destination = address;
67 }
68 else if ( ud_obj.operand[0].type == ud_type.UD_OP_JIMM )
69 {
70 is_imm = true;
71 address = cast(uint)ud_insn_off(ud_obj);
72 destination = address+ud_insn_len(ud_obj);
73 switch ( ud_obj.operand[0].size )
74 {
75 case 8:
76 destination += ud_obj.operand[0].lval.sbyte;
77 break;
78 case 16:
79 destination += ud_obj.operand[0].lval.sword;
80 break;
81 case 32:
82 destination += ud_obj.operand[0].lval.sdword;
83 break;
84 case 48:
85 DbgIO.println("WARNING: 48bit immediate jump destinations not implemented, yet");
86 break;
87 case 64:
88 DbgIO.println("WARNING: 64bit immediate jump destinations not implemented, yet");
89 break;
90 default:
91 assert(0);
92 }
93 }
94 else
95 DbgIO.println("yet unsupported jmp/call destination");
96 return destination;
97 }
98
99 /**********************************************************************************************
100 Test if given mnemonic a a conditional jump (i.e. jxx, not jmp).
101 **********************************************************************************************/
102 static bool isConditionalJump(ud_mnemonic_code opcode)
103 {
104 if ( ud_mnemonic_code.UD_Ijmp == opcode )
105 return false;
106 if ( ud_mnemonic_code.UD_Ijcxz <= opcode && ud_mnemonic_code.UD_Ijnle >= opcode )
107 return true;
108 if ( ud_mnemonic_code.UD_Ija <= opcode && ud_mnemonic_code.UD_Ijnc >= opcode )
109 return true;
110 if ( ud_mnemonic_code.UD_Iloop <= opcode && ud_mnemonic_code.UD_Iloopz >= opcode )
111 return true;
112 return false;
113 }
114
115 /**********************************************************************************************
116 Wrapper function for disassembly. Calls the delegate callback for each instruction.
117 **********************************************************************************************/
118 static void disasm(DbgProcess process, uint start, uint stop, bool delegate(ud_t*) callback)
119 {
120 ubyte[] code;
121
122 bool disasm(uint length, bool abort_at_ret)
123 {
124 ud_t ud_obj;
125 ud_init(&ud_obj);
126 ud_set_pc(&ud_obj, start);
127 ud_set_input_buffer(&ud_obj, code.ptr, length);
128 ud_set_mode(&ud_obj, 32);
129 ud_set_syntax(&ud_obj, &ud_translate_intel);
130
131 // init callback
132 callback(cast(ud_t*)null);
133
134 while ( ud_disassemble(&ud_obj) )
135 {
136 if ( !callback(&ud_obj) )
137 return false;
138 if ( abort_at_ret && (ud_obj.mnemonic == ud_mnemonic_code.UD_Iret || ud_obj.mnemonic == ud_mnemonic_code.UD_Iretf) )
139 return false;
140 }
141 return true;
142 }
143
144 if ( stop > 0 && stop <= start ) {
145 DbgIO.println("ERROR: invalid address range: Eip=0x%x >= 0x%x", start, stop);
146 return;
147 }
148
149 code.length = stop>0?stop-start:512;
150 bool more;
151 uint read;
152 do
153 {
154 read = process.readProcessMemory(start, code.ptr, code.length);
155 if ( read == 0 )
156 DbgIO.println("ERROR: Couldn't read from process' memory for disassembly: %s", lastError);
157 if ( read > 0 )
158 more = disasm(read, stop==0);
159 start += code.length;
160 } while ( stop == 0 && more && read > 0 );
161 }
162 }