1
|
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 }
|