Mercurial > projects > ddbg_continued
comparison src/expression/datahandler.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 module expression.datahandler; | |
6 | |
7 import std.string; | |
8 import std.utf; | |
9 | |
10 import codeview.codeview; | |
11 import codeview.decl; | |
12 import dbgprocess; | |
13 import util; | |
14 import minidump; | |
15 import expression.evaluationcontext; | |
16 | |
17 import internal.aaA; | |
18 | |
19 T min(T)(T a, T b) | |
20 { | |
21 return a<b?a:b; | |
22 } | |
23 | |
24 /************************************************************************************************** | |
25 | |
26 **************************************************************************************************/ | |
27 class SymbolValue | |
28 { | |
29 string name, | |
30 value; | |
31 SymbolValue[] children; | |
32 | |
33 this() {} | |
34 | |
35 this(string v) | |
36 { | |
37 value = v; | |
38 } | |
39 | |
40 this(string n, string v) | |
41 { | |
42 name = n; | |
43 value = v; | |
44 } | |
45 } | |
46 | |
47 | |
48 /************************************************************************************************** | |
49 | |
50 **************************************************************************************************/ | |
51 class DataHandler | |
52 { | |
53 static DataHandler[string] s_dataHandlerRegistry; | |
54 static uint max_elem_count = 32; | |
55 | |
56 static this() | |
57 { | |
58 s_dataHandlerRegistry["b"] = new DataHandler_bool; | |
59 s_dataHandlerRegistry["a"] = new DataHandler_num; | |
60 s_dataHandlerRegistry["w"] = new DataHandler_num; | |
61 s_dataHandlerRegistry["u"] = new DataHandler_num; | |
62 s_dataHandlerRegistry["g"] = new DataHandler_num; | |
63 s_dataHandlerRegistry["h"] = new DataHandler_num; | |
64 s_dataHandlerRegistry["i"] = new DataHandler_num; | |
65 s_dataHandlerRegistry["l"] = new DataHandler_num; | |
66 s_dataHandlerRegistry["k"] = new DataHandler_num; | |
67 s_dataHandlerRegistry["m"] = new DataHandler_num; | |
68 s_dataHandlerRegistry["s"] = new DataHandler_num; | |
69 s_dataHandlerRegistry["t"] = new DataHandler_num; | |
70 s_dataHandlerRegistry["v"] = new DataHandler_num; | |
71 s_dataHandlerRegistry["f"] = new DataHandler_num; | |
72 s_dataHandlerRegistry["d"] = new DataHandler_num; | |
73 s_dataHandlerRegistry["e"] = new DataHandler_num; | |
74 s_dataHandlerRegistry["x"] = new DataHandler_num; | |
75 s_dataHandlerRegistry["Aa"] = new DataHandler_string; | |
76 s_dataHandlerRegistry["Au"] = new DataHandler_string; | |
77 s_dataHandlerRegistry["Aw"] = new DataHandler_string; | |
78 s_dataHandlerRegistry["P*"] = new DataHandler_num; | |
79 s_dataHandlerRegistry["A*"] = new DataHandler_A; | |
80 s_dataHandlerRegistry["G*"] = new DataHandler_G; | |
81 s_dataHandlerRegistry["S*"] = new DataHandler_SCU; | |
82 s_dataHandlerRegistry["C*"] = new DataHandler_SCU; | |
83 s_dataHandlerRegistry["PC*"] = new DataHandler_SCU; | |
84 s_dataHandlerRegistry["E*"] = new DataHandler_E; | |
85 s_dataHandlerRegistry["H*"] = new DataHandler_H; | |
86 } | |
87 | |
88 static SymbolValue handle(EvaluationContext ctx, string type, ubyte[] data, int depth) | |
89 { | |
90 if ( type.length <= 0 ) | |
91 return null; | |
92 | |
93 DataHandler* handler = type in s_dataHandlerRegistry; | |
94 if ( type.length > 1 && handler is null ) | |
95 handler = type[0..2]~"*" in s_dataHandlerRegistry; | |
96 if ( handler is null ) | |
97 handler = type[0]~"*" in s_dataHandlerRegistry; | |
98 | |
99 SymbolValue val; | |
100 if ( handler !is null ) { | |
101 debug(datahandler) DbgIO.println("%s is handling data", handler.classinfo.name); | |
102 val = handler.toString(ctx, type, data, depth); | |
103 } | |
104 return val; | |
105 } | |
106 | |
107 abstract SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth); | |
108 } | |
109 | |
110 /************************************************************************************************** | |
111 | |
112 **************************************************************************************************/ | |
113 class DataHandler_H : DataHandler | |
114 { | |
115 SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) | |
116 { | |
117 SymbolValue val = new SymbolValue; | |
118 | |
119 size_t ptr = (cast(size_t[])data)[0]; | |
120 if ( ptr == 0 ) { | |
121 val.value = "null"; | |
122 return val; | |
123 } | |
124 | |
125 if ( depth == 0 ) { | |
126 val.value = "..."; | |
127 return val; | |
128 } | |
129 | |
130 int i; | |
131 pragma(msg, TODO(__FILE__,__LINE__,"allow named types (C,S,D,F, etc.)")); | |
132 for ( i = 1; i < mangled_type.length && find(lowercase, mangled_type[i]) < 0; ++i ) {} | |
133 | |
134 string key_type = mangled_type[1..i+1], | |
135 val_type = mangled_type[i+1..$]; | |
136 size_t val_tsize = ctx.codeView.sizeofMangled(val_type), | |
137 key_tsize = ctx.codeView.sizeofMangled(key_type); | |
138 | |
139 if ( key_type.length == 0 ) { | |
140 val.value = "invalid key type "~key_type; | |
141 return val; | |
142 } | |
143 if ( val_type.length == 0 ) { | |
144 val.value = "invalid val type "~val_type; | |
145 return val; | |
146 } | |
147 | |
148 bool evalaaA(void* ptr) | |
149 { | |
150 if ( ptr is null ) | |
151 return true; | |
152 ubyte[] data; | |
153 size_t len = aaA.sizeof+key_tsize+val_tsize; | |
154 data = ctx.readMemory(cast(size_t)ptr, len); | |
155 if ( data is null ) | |
156 return false; | |
157 | |
158 uint i=aaA.sizeof; | |
159 SymbolValue k = handle(ctx, key_type, data[i..i+key_tsize], depth>0?depth-1:depth); | |
160 i += key_tsize; | |
161 SymbolValue v = handle(ctx, val_type, data[i..i+val_tsize], depth>0?depth-1:depth); | |
162 v.name = k.value; | |
163 val.children ~= v; | |
164 return true; | |
165 } | |
166 | |
167 bool evalBB(uint ptr) | |
168 { | |
169 ubyte[] data = ctx.readMemory(cast(size_t)ptr, BB.sizeof); | |
170 if ( data is null ) | |
171 return false; | |
172 | |
173 BB* bb = cast(BB*)data.ptr; | |
174 size_t blen = bb.b.length*size_t.sizeof; | |
175 debug DbgIO.println("%d nodes, bb.b.length=%d", bb.nodes, bb.b.length); | |
176 | |
177 data = ctx.readMemory(cast(size_t)bb.b.ptr, blen); | |
178 if ( data is null ) | |
179 return false; | |
180 bb.b = cast(aaA*[])data; | |
181 | |
182 foreach ( a; bb.b ) | |
183 { | |
184 if ( !evalaaA(a) ) | |
185 return false; | |
186 } | |
187 return true; | |
188 } | |
189 | |
190 if ( !evalBB(ptr) ) | |
191 val.value = format("invalid AA pointer 0x%x", ptr); | |
192 | |
193 return val; | |
194 } | |
195 } | |
196 | |
197 /************************************************************************************************** | |
198 | |
199 **************************************************************************************************/ | |
200 class DataHandler_E : DataHandler | |
201 { | |
202 SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) | |
203 { | |
204 SymbolValue val = new SymbolValue; | |
205 string mangled = mangled_type[1..$].dup, | |
206 name; | |
207 name = demangleNameSkip(mangled); | |
208 if ( (name in ctx.codeView.UDTsByName) !is null ) | |
209 { | |
210 LeafEnum lf = cast(LeafEnum)ctx.codeView.UDTsByName[name]; | |
211 if ( lf is null ) { | |
212 val.value = "invalid codeview information for enum type "~name; | |
213 return val; | |
214 } | |
215 uint index = lf.field-0x1000; | |
216 if ( index >= ctx.codeView.type_strings.length ) { | |
217 val.value = "invalid codeview information for enum type "~name; | |
218 return val; | |
219 } | |
220 LeafFieldList fields = cast(LeafFieldList)ctx.codeView.type_strings[lf.field-0x1000][0]; | |
221 if ( fields is null ) { | |
222 val.value = "invalid codeview information for enum type "~name; | |
223 return val; | |
224 } | |
225 assert(data.length >= 4); | |
226 uint value = (cast(uint[])data)[0]; | |
227 foreach ( f; fields.fields ) | |
228 { | |
229 LeafEnumNameValue ef = cast(LeafEnumNameValue)f; | |
230 assert(ef !is null); | |
231 if ( ef.value.getUint == value ) { | |
232 val.value = ef.name; | |
233 return val; | |
234 } | |
235 } | |
236 val.value = "invalid enum value"; | |
237 } | |
238 else | |
239 val.value = "unknown enum type "~name; | |
240 return val; | |
241 } | |
242 } | |
243 | |
244 /************************************************************************************************** | |
245 | |
246 **************************************************************************************************/ | |
247 class DataHandler_SCU : DataHandler | |
248 { | |
249 SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) | |
250 { | |
251 SymbolValue val = new SymbolValue; | |
252 | |
253 string scu_name_mangled, | |
254 scu_name; | |
255 if ( mangled_type[0] == 'P' ) | |
256 { | |
257 assert(data.length==size_t.sizeof); | |
258 if ( *cast(size_t*)data.ptr == 0 ) { | |
259 val.value = "null"; | |
260 return val; | |
261 } | |
262 scu_name_mangled = mangled_type[2..$].dup; | |
263 } | |
264 else | |
265 scu_name_mangled = mangled_type[1..$].dup; | |
266 scu_name = demangleNameSkip(scu_name_mangled); | |
267 | |
268 if ( depth == 0 ) { | |
269 val.value = "..."; | |
270 return val; | |
271 } | |
272 | |
273 if ( (scu_name in ctx.codeView.UDTsByName) is null ) { | |
274 val.value = format("unknown type %s", scu_name); | |
275 return val; | |
276 } | |
277 | |
278 LeafClassStruc lcs; | |
279 LeafUnion lu; | |
280 | |
281 LeafFieldList lfl; | |
282 uint type_length; | |
283 | |
284 lcs = cast(LeafClassStruc)ctx.codeView.UDTsByName[scu_name]; | |
285 debug DbgIO.println("%s %x", scu_name, lcs.field); | |
286 if ( lcs !is null && lcs.field-0x1000 < ctx.codeView.type_strings.length ) { | |
287 lfl = cast(LeafFieldList)ctx.codeView.type_strings[lcs.field-0x1000][0]; | |
288 type_length = lcs.length.getUint(); | |
289 } | |
290 else | |
291 { | |
292 lu = cast(LeafUnion)ctx.codeView.UDTsByName[scu_name]; | |
293 if ( lu !is null && lu.field-0x1000 < ctx.codeView.type_strings.length ) { | |
294 lfl = cast(LeafFieldList)ctx.codeView.type_strings[lu.field-0x1000][0]; | |
295 type_length = lu.length.getUint(); | |
296 } | |
297 } | |
298 | |
299 if ( lfl is null ) { | |
300 val.value = "{no debug symbols available}"; | |
301 return val; | |
302 } | |
303 | |
304 ubyte[] tmpdata; | |
305 if ( mangled_type[0] == 'P' || mangled_type[0] == 'C' ) | |
306 { | |
307 assert(data.length==size_t.sizeof); | |
308 debug(datahandler) DbgIO.println("dereferencing class/struct reference at 0x%x", *cast(size_t*)data.ptr); | |
309 tmpdata = ctx.readMemory(*cast(size_t*)data.ptr, type_length); | |
310 if ( tmpdata is null ) { | |
311 val.value = format("invalid class pointer 0x%08x", *cast(size_t*)data.ptr); | |
312 return val; | |
313 } | |
314 } | |
315 else | |
316 tmpdata = data; | |
317 | |
318 void listMembers(LeafFieldList lfl, SymbolValue root) | |
319 { | |
320 foreach ( l; lfl.fields ) | |
321 { | |
322 if ( l.leaf_index == LF_BCLASS_16t ) | |
323 { | |
324 LeafBaseClass lbc = cast(LeafBaseClass)l; | |
325 assert ( lbc !is null ); | |
326 if ( lbc.type-0x1000 >= ctx.codeView.type_strings.length ) { | |
327 root.children ~= new SymbolValue("unknown base class "~format("0x%04x", lbc.type)); | |
328 continue; | |
329 } | |
330 LeafClassStruc lcs = cast(LeafClassStruc)ctx.codeView.type_strings[lbc.type-0x1000][0]; | |
331 assert ( lcs !is null ); | |
332 if ( lcs.field == 0 ) | |
333 continue; | |
334 if ( lcs.field-0x1000 >= ctx.codeView.type_strings.length ) { | |
335 root.children ~= new SymbolValue("unknown field list "~format("0x%04x", lcs.field)); | |
336 continue; | |
337 } | |
338 Leaf[] fields = ctx.codeView.type_strings[lcs.field-0x1000]; | |
339 debug(datahandler) DbgIO.println("processing base class ", lcs.name); | |
340 | |
341 SymbolValue v = new SymbolValue; | |
342 v.name = lcs.name; | |
343 listMembers(cast(LeafFieldList)fields[0], v); | |
344 root.children ~= v; | |
345 } | |
346 else if ( l.leaf_index == LF_MEMBER_16t ) | |
347 { | |
348 LeafMember lm = cast(LeafMember)l; | |
349 assert ( lm !is null ); | |
350 uint size = ctx.codeView.sizeofCV(lm.type), | |
351 offset = lm.offset.getUint; | |
352 | |
353 LeafPointer lp; | |
354 bool seen_type; | |
355 if ( lm.type >= 0x1000 && lm.type-0x1000 < ctx.codeView.type_strings.length ) | |
356 lp = cast(LeafPointer)ctx.codeView.type_strings[lm.type-0x1000][0]; | |
357 if ( depth > 0 ) | |
358 { | |
359 debug(datahandler) DbgIO.println("processing member %s cvtype 0x%x mangled %s", lm.name, lm.type, ctx.codeView.mangleCVtype(lm.type)); | |
360 if ( offset+size > tmpdata.length ) | |
361 root.children ~= new SymbolValue(lm.name, format("invalid: offset=0x%x size=%d", offset, size)); | |
362 else | |
363 { | |
364 SymbolValue v = handle(ctx, ctx.codeView.mangleCVtype(lm.type), tmpdata[offset..offset+size], depth>0?depth-1:depth); | |
365 if ( v !is null ) { | |
366 v.name = lm.name; | |
367 root.children ~= v; | |
368 } | |
369 else | |
370 root.children ~= new SymbolValue(lm.name, "null"); | |
371 } | |
372 } | |
373 } | |
374 } | |
375 } | |
376 | |
377 listMembers(lfl, val); | |
378 return val; | |
379 } | |
380 } | |
381 | |
382 /************************************************************************************************** | |
383 | |
384 **************************************************************************************************/ | |
385 class DataHandler_A : DataHandler | |
386 { | |
387 SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) | |
388 { | |
389 SymbolValue val = new SymbolValue; | |
390 size_t[] idata = cast(size_t[])data; | |
391 | |
392 if ( idata[1] == 0 ) { | |
393 val.value = "null"; | |
394 return val; | |
395 } | |
396 | |
397 if ( depth == 0 ) { | |
398 val.value = "..."; | |
399 return val; | |
400 } | |
401 | |
402 mangled_type = mangled_type[1..$]; | |
403 uint elm_size = ctx.codeView.sizeofMangled(mangled_type); | |
404 size_t alen = min(idata[0],max_elem_count)*elm_size; | |
405 | |
406 ubyte[] tmpdata = ctx.readMemory(idata[1], alen); | |
407 if ( tmpdata is null ) | |
408 val.value = format("invalid array: ptr=0x%08x $=%d", idata[1], idata[0]); | |
409 else | |
410 { | |
411 uint off_end = tmpdata.length; | |
412 for ( uint i = 0, off=0; off < off_end; ++i, off+=elm_size ) { | |
413 SymbolValue v = handle(ctx, mangled_type, tmpdata[off..off+elm_size], depth>0?depth-1:depth); | |
414 if ( v is null ) | |
415 val.children ~= new SymbolValue("["~.toString(i)~"]", "null"); | |
416 else { | |
417 v.name = "["~.toString(i)~"]"; | |
418 val.children ~= v; | |
419 } | |
420 } | |
421 if ( idata[0] > max_elem_count ) | |
422 val.children ~= new SymbolValue("... $", format("%d", idata[0])); | |
423 } | |
424 return val; | |
425 } | |
426 } | |
427 | |
428 /************************************************************************************************** | |
429 | |
430 **************************************************************************************************/ | |
431 class DataHandler_G : DataHandler | |
432 { | |
433 SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) | |
434 { | |
435 SymbolValue val = new SymbolValue; | |
436 | |
437 if ( depth == 0 ) { | |
438 val.value = "..."; | |
439 return val; | |
440 } | |
441 | |
442 mangled_type = mangled_type[1..$]; | |
443 uint count = parseNumber(mangled_type), | |
444 elm_size = ctx.codeView.sizeofMangled(mangled_type), | |
445 off_end = min(count,max_elem_count)*elm_size; | |
446 if ( count*elm_size != data.length ) | |
447 throw new EvaluationException("unexpected data length: have "~.toString(data.length)~" should be "~.toString(count*elm_size)); | |
448 for ( uint i = 0, off=0; off < off_end; ++i, off+=elm_size ) { | |
449 SymbolValue v = handle(ctx, mangled_type, data[off..off+elm_size], depth>0?depth-1:depth); | |
450 if ( v is null ) | |
451 val.children ~= new SymbolValue("["~.toString(i)~"]", "null"); | |
452 else { | |
453 v.name = "["~.toString(i)~"]"; | |
454 val.children ~= v; | |
455 } | |
456 } | |
457 if ( count > max_elem_count ) | |
458 val.children ~= new SymbolValue("... $", format("%d", count)); | |
459 return val; | |
460 } | |
461 } | |
462 | |
463 /************************************************************************************************** | |
464 | |
465 **************************************************************************************************/ | |
466 class DataHandler_string : DataHandler | |
467 { | |
468 SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) | |
469 { | |
470 SymbolValue val = new SymbolValue; | |
471 | |
472 string str; | |
473 uint[] idata = cast(uint[])data; | |
474 if ( idata[1] == 0 ) { | |
475 val.value = "null"; | |
476 return val; | |
477 } | |
478 | |
479 assert(mangled_type[0] == 'A'); | |
480 | |
481 switch ( mangled_type[1] ) | |
482 { | |
483 case 'a': | |
484 str = cast(string)ctx.readMemory(idata[1], idata[0]); | |
485 if ( str is null ) { | |
486 val.value = format("invalid string: ptr=0x%08x $=%d", idata[1], idata[0]); | |
487 return val; | |
488 } | |
489 break; | |
490 case 'u': | |
491 wstring wstr; | |
492 size_t len = idata[0]*wchar.sizeof; | |
493 | |
494 wstr = cast(wstring)ctx.readMemory(idata[1], len); | |
495 if ( wstr is null ) { | |
496 val.value = format("invalid string: ptr=0x%08x $=%d", idata[1], idata[0]); | |
497 return val; | |
498 } | |
499 str = toUTF8(wstr); | |
500 break; | |
501 case 'w': | |
502 dstring dstr; | |
503 size_t len = idata[0]*dchar.sizeof; | |
504 | |
505 dstr = cast(dstring)ctx.readMemory(idata[1], len); | |
506 if ( dstr is null ) { | |
507 val.value = format("invalid string: ptr=0x%08x $=%d", idata[1], idata[0]); | |
508 return val; | |
509 } | |
510 str = toUTF8(dstr); | |
511 break; | |
512 default: | |
513 assert(0); | |
514 } | |
515 val.value = "\""~replace(replace(str, "\\", "\\\\"), "\"", "\\\"")~"\""; | |
516 return val; | |
517 } | |
518 } | |
519 | |
520 /************************************************************************************************** | |
521 | |
522 **************************************************************************************************/ | |
523 class DataHandler_num : DataHandler | |
524 { | |
525 SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) | |
526 { | |
527 SymbolValue val = new SymbolValue; | |
528 switch ( mangled_type[0] ) | |
529 { | |
530 case 'a': | |
531 val.value = (cast(char[])data)[0..1]; | |
532 break; | |
533 //~ case 'u': | |
534 //~ val.value = toUTF8((cast(wchar[])data)[0..1]); | |
535 //~ break; | |
536 case 'w': | |
537 val.value = toUTF8((cast(dchar[])data)[0..1]); | |
538 break; | |
539 case 'g': | |
540 val.value = format("%d", (cast(byte[])data)[0]); | |
541 break; | |
542 case 'h': | |
543 val.value = format("%d", (cast(ubyte[])data)[0]); | |
544 break; | |
545 case 's': | |
546 val.value = format("%d", (cast(short[])data)[0]); | |
547 break; | |
548 case 't': | |
549 case 'u': | |
550 val.value = format("%d", (cast(ushort[])data)[0]); | |
551 break; | |
552 case 'i': | |
553 val.value = format("%d", (cast(int[])data)[0]); | |
554 break; | |
555 case 'P': | |
556 case 'v': | |
557 case 'k': | |
558 val.value = format("0x%08x", (cast(uint[])data)[0]); | |
559 break; | |
560 case 'l': | |
561 val.value = format("%d", (cast(long[])data)[0]); | |
562 break; | |
563 case 'm': | |
564 val.value = format("%d", (cast(ulong[])data)[0]); | |
565 break; | |
566 case 'f': | |
567 val.value = format("% .6g", (cast(float[])data)[0]); | |
568 break; | |
569 case 'd': | |
570 val.value = format("% .12g", (cast(double[])data)[0]); | |
571 break; | |
572 case 'e': | |
573 val.value = format("% .16g", (cast(real[])data)[0]); | |
574 break; | |
575 case 'x': | |
576 case 'b': | |
577 val.value = format("%s", (cast(bool[])data)[0]?"true":"false"); | |
578 break; | |
579 default: | |
580 assert(0, mangled_type); | |
581 } | |
582 return val; | |
583 } | |
584 } | |
585 | |
586 | |
587 /************************************************************************************************** | |
588 | |
589 **************************************************************************************************/ | |
590 class DataHandler_bool : DataHandler | |
591 { | |
592 SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) | |
593 { | |
594 SymbolValue val = new SymbolValue; | |
595 assert(mangled_type[0]=='b'); | |
596 val.value = format("%s", (cast(bool[])data)[0]); | |
597 return val; | |
598 } | |
599 } |