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 }