Mercurial > projects > ddbg_continued
view 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 |
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. */ module expression.datahandler; import std.string; import std.utf; import codeview.codeview; import codeview.decl; import dbgprocess; import util; import minidump; import expression.evaluationcontext; import internal.aaA; T min(T)(T a, T b) { return a<b?a:b; } /************************************************************************************************** **************************************************************************************************/ class SymbolValue { string name, value; SymbolValue[] children; this() {} this(string v) { value = v; } this(string n, string v) { name = n; value = v; } } /************************************************************************************************** **************************************************************************************************/ class DataHandler { static DataHandler[string] s_dataHandlerRegistry; static uint max_elem_count = 32; static this() { s_dataHandlerRegistry["b"] = new DataHandler_bool; s_dataHandlerRegistry["a"] = new DataHandler_num; s_dataHandlerRegistry["w"] = new DataHandler_num; s_dataHandlerRegistry["u"] = new DataHandler_num; s_dataHandlerRegistry["g"] = new DataHandler_num; s_dataHandlerRegistry["h"] = new DataHandler_num; s_dataHandlerRegistry["i"] = new DataHandler_num; s_dataHandlerRegistry["l"] = new DataHandler_num; s_dataHandlerRegistry["k"] = new DataHandler_num; s_dataHandlerRegistry["m"] = new DataHandler_num; s_dataHandlerRegistry["s"] = new DataHandler_num; s_dataHandlerRegistry["t"] = new DataHandler_num; s_dataHandlerRegistry["v"] = new DataHandler_num; s_dataHandlerRegistry["f"] = new DataHandler_num; s_dataHandlerRegistry["d"] = new DataHandler_num; s_dataHandlerRegistry["e"] = new DataHandler_num; s_dataHandlerRegistry["x"] = new DataHandler_num; s_dataHandlerRegistry["Aa"] = new DataHandler_string; s_dataHandlerRegistry["Au"] = new DataHandler_string; s_dataHandlerRegistry["Aw"] = new DataHandler_string; s_dataHandlerRegistry["P*"] = new DataHandler_num; s_dataHandlerRegistry["A*"] = new DataHandler_A; s_dataHandlerRegistry["G*"] = new DataHandler_G; s_dataHandlerRegistry["S*"] = new DataHandler_SCU; s_dataHandlerRegistry["C*"] = new DataHandler_SCU; s_dataHandlerRegistry["PC*"] = new DataHandler_SCU; s_dataHandlerRegistry["E*"] = new DataHandler_E; s_dataHandlerRegistry["H*"] = new DataHandler_H; } static SymbolValue handle(EvaluationContext ctx, string type, ubyte[] data, int depth) { if ( type.length <= 0 ) return null; DataHandler* handler = type in s_dataHandlerRegistry; if ( type.length > 1 && handler is null ) handler = type[0..2]~"*" in s_dataHandlerRegistry; if ( handler is null ) handler = type[0]~"*" in s_dataHandlerRegistry; SymbolValue val; if ( handler !is null ) { debug(datahandler) DbgIO.println("%s is handling data", handler.classinfo.name); val = handler.toString(ctx, type, data, depth); } return val; } abstract SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth); } /************************************************************************************************** **************************************************************************************************/ class DataHandler_H : DataHandler { SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) { SymbolValue val = new SymbolValue; size_t ptr = (cast(size_t[])data)[0]; if ( ptr == 0 ) { val.value = "null"; return val; } if ( depth == 0 ) { val.value = "..."; return val; } int i; pragma(msg, TODO(__FILE__,__LINE__,"allow named types (C,S,D,F, etc.)")); for ( i = 1; i < mangled_type.length && find(lowercase, mangled_type[i]) < 0; ++i ) {} string key_type = mangled_type[1..i+1], val_type = mangled_type[i+1..$]; size_t val_tsize = ctx.codeView.sizeofMangled(val_type), key_tsize = ctx.codeView.sizeofMangled(key_type); if ( key_type.length == 0 ) { val.value = "invalid key type "~key_type; return val; } if ( val_type.length == 0 ) { val.value = "invalid val type "~val_type; return val; } bool evalaaA(void* ptr) { if ( ptr is null ) return true; ubyte[] data; size_t len = aaA.sizeof+key_tsize+val_tsize; data = ctx.readMemory(cast(size_t)ptr, len); if ( data is null ) return false; uint i=aaA.sizeof; SymbolValue k = handle(ctx, key_type, data[i..i+key_tsize], depth>0?depth-1:depth); i += key_tsize; SymbolValue v = handle(ctx, val_type, data[i..i+val_tsize], depth>0?depth-1:depth); v.name = k.value; val.children ~= v; return true; } bool evalBB(uint ptr) { ubyte[] data = ctx.readMemory(cast(size_t)ptr, BB.sizeof); if ( data is null ) return false; BB* bb = cast(BB*)data.ptr; size_t blen = bb.b.length*size_t.sizeof; debug DbgIO.println("%d nodes, bb.b.length=%d", bb.nodes, bb.b.length); data = ctx.readMemory(cast(size_t)bb.b.ptr, blen); if ( data is null ) return false; bb.b = cast(aaA*[])data; foreach ( a; bb.b ) { if ( !evalaaA(a) ) return false; } return true; } if ( !evalBB(ptr) ) val.value = format("invalid AA pointer 0x%x", ptr); return val; } } /************************************************************************************************** **************************************************************************************************/ class DataHandler_E : DataHandler { SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) { SymbolValue val = new SymbolValue; string mangled = mangled_type[1..$].dup, name; name = demangleNameSkip(mangled); if ( (name in ctx.codeView.UDTsByName) !is null ) { LeafEnum lf = cast(LeafEnum)ctx.codeView.UDTsByName[name]; if ( lf is null ) { val.value = "invalid codeview information for enum type "~name; return val; } uint index = lf.field-0x1000; if ( index >= ctx.codeView.type_strings.length ) { val.value = "invalid codeview information for enum type "~name; return val; } LeafFieldList fields = cast(LeafFieldList)ctx.codeView.type_strings[lf.field-0x1000][0]; if ( fields is null ) { val.value = "invalid codeview information for enum type "~name; return val; } assert(data.length >= 4); uint value = (cast(uint[])data)[0]; foreach ( f; fields.fields ) { LeafEnumNameValue ef = cast(LeafEnumNameValue)f; assert(ef !is null); if ( ef.value.getUint == value ) { val.value = ef.name; return val; } } val.value = "invalid enum value"; } else val.value = "unknown enum type "~name; return val; } } /************************************************************************************************** **************************************************************************************************/ class DataHandler_SCU : DataHandler { SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) { SymbolValue val = new SymbolValue; string scu_name_mangled, scu_name; if ( mangled_type[0] == 'P' ) { assert(data.length==size_t.sizeof); if ( *cast(size_t*)data.ptr == 0 ) { val.value = "null"; return val; } scu_name_mangled = mangled_type[2..$].dup; } else scu_name_mangled = mangled_type[1..$].dup; scu_name = demangleNameSkip(scu_name_mangled); if ( depth == 0 ) { val.value = "..."; return val; } if ( (scu_name in ctx.codeView.UDTsByName) is null ) { val.value = format("unknown type %s", scu_name); return val; } LeafClassStruc lcs; LeafUnion lu; LeafFieldList lfl; uint type_length; lcs = cast(LeafClassStruc)ctx.codeView.UDTsByName[scu_name]; debug DbgIO.println("%s %x", scu_name, lcs.field); if ( lcs !is null && lcs.field-0x1000 < ctx.codeView.type_strings.length ) { lfl = cast(LeafFieldList)ctx.codeView.type_strings[lcs.field-0x1000][0]; type_length = lcs.length.getUint(); } else { lu = cast(LeafUnion)ctx.codeView.UDTsByName[scu_name]; if ( lu !is null && lu.field-0x1000 < ctx.codeView.type_strings.length ) { lfl = cast(LeafFieldList)ctx.codeView.type_strings[lu.field-0x1000][0]; type_length = lu.length.getUint(); } } if ( lfl is null ) { val.value = "{no debug symbols available}"; return val; } ubyte[] tmpdata; if ( mangled_type[0] == 'P' || mangled_type[0] == 'C' ) { assert(data.length==size_t.sizeof); debug(datahandler) DbgIO.println("dereferencing class/struct reference at 0x%x", *cast(size_t*)data.ptr); tmpdata = ctx.readMemory(*cast(size_t*)data.ptr, type_length); if ( tmpdata is null ) { val.value = format("invalid class pointer 0x%08x", *cast(size_t*)data.ptr); return val; } } else tmpdata = data; void listMembers(LeafFieldList lfl, SymbolValue root) { foreach ( l; lfl.fields ) { if ( l.leaf_index == LF_BCLASS_16t ) { LeafBaseClass lbc = cast(LeafBaseClass)l; assert ( lbc !is null ); if ( lbc.type-0x1000 >= ctx.codeView.type_strings.length ) { root.children ~= new SymbolValue("unknown base class "~format("0x%04x", lbc.type)); continue; } LeafClassStruc lcs = cast(LeafClassStruc)ctx.codeView.type_strings[lbc.type-0x1000][0]; assert ( lcs !is null ); if ( lcs.field == 0 ) continue; if ( lcs.field-0x1000 >= ctx.codeView.type_strings.length ) { root.children ~= new SymbolValue("unknown field list "~format("0x%04x", lcs.field)); continue; } Leaf[] fields = ctx.codeView.type_strings[lcs.field-0x1000]; debug(datahandler) DbgIO.println("processing base class ", lcs.name); SymbolValue v = new SymbolValue; v.name = lcs.name; listMembers(cast(LeafFieldList)fields[0], v); root.children ~= v; } else if ( l.leaf_index == LF_MEMBER_16t ) { LeafMember lm = cast(LeafMember)l; assert ( lm !is null ); uint size = ctx.codeView.sizeofCV(lm.type), offset = lm.offset.getUint; LeafPointer lp; bool seen_type; if ( lm.type >= 0x1000 && lm.type-0x1000 < ctx.codeView.type_strings.length ) lp = cast(LeafPointer)ctx.codeView.type_strings[lm.type-0x1000][0]; if ( depth > 0 ) { debug(datahandler) DbgIO.println("processing member %s cvtype 0x%x mangled %s", lm.name, lm.type, ctx.codeView.mangleCVtype(lm.type)); if ( offset+size > tmpdata.length ) root.children ~= new SymbolValue(lm.name, format("invalid: offset=0x%x size=%d", offset, size)); else { SymbolValue v = handle(ctx, ctx.codeView.mangleCVtype(lm.type), tmpdata[offset..offset+size], depth>0?depth-1:depth); if ( v !is null ) { v.name = lm.name; root.children ~= v; } else root.children ~= new SymbolValue(lm.name, "null"); } } } } } listMembers(lfl, val); return val; } } /************************************************************************************************** **************************************************************************************************/ class DataHandler_A : DataHandler { SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) { SymbolValue val = new SymbolValue; size_t[] idata = cast(size_t[])data; if ( idata[1] == 0 ) { val.value = "null"; return val; } if ( depth == 0 ) { val.value = "..."; return val; } mangled_type = mangled_type[1..$]; uint elm_size = ctx.codeView.sizeofMangled(mangled_type); size_t alen = min(idata[0],max_elem_count)*elm_size; ubyte[] tmpdata = ctx.readMemory(idata[1], alen); if ( tmpdata is null ) val.value = format("invalid array: ptr=0x%08x $=%d", idata[1], idata[0]); else { uint off_end = tmpdata.length; for ( uint i = 0, off=0; off < off_end; ++i, off+=elm_size ) { SymbolValue v = handle(ctx, mangled_type, tmpdata[off..off+elm_size], depth>0?depth-1:depth); if ( v is null ) val.children ~= new SymbolValue("["~.toString(i)~"]", "null"); else { v.name = "["~.toString(i)~"]"; val.children ~= v; } } if ( idata[0] > max_elem_count ) val.children ~= new SymbolValue("... $", format("%d", idata[0])); } return val; } } /************************************************************************************************** **************************************************************************************************/ class DataHandler_G : DataHandler { SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) { SymbolValue val = new SymbolValue; if ( depth == 0 ) { val.value = "..."; return val; } mangled_type = mangled_type[1..$]; uint count = parseNumber(mangled_type), elm_size = ctx.codeView.sizeofMangled(mangled_type), off_end = min(count,max_elem_count)*elm_size; if ( count*elm_size != data.length ) throw new EvaluationException("unexpected data length: have "~.toString(data.length)~" should be "~.toString(count*elm_size)); for ( uint i = 0, off=0; off < off_end; ++i, off+=elm_size ) { SymbolValue v = handle(ctx, mangled_type, data[off..off+elm_size], depth>0?depth-1:depth); if ( v is null ) val.children ~= new SymbolValue("["~.toString(i)~"]", "null"); else { v.name = "["~.toString(i)~"]"; val.children ~= v; } } if ( count > max_elem_count ) val.children ~= new SymbolValue("... $", format("%d", count)); return val; } } /************************************************************************************************** **************************************************************************************************/ class DataHandler_string : DataHandler { SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) { SymbolValue val = new SymbolValue; string str; uint[] idata = cast(uint[])data; if ( idata[1] == 0 ) { val.value = "null"; return val; } assert(mangled_type[0] == 'A'); switch ( mangled_type[1] ) { case 'a': str = cast(string)ctx.readMemory(idata[1], idata[0]); if ( str is null ) { val.value = format("invalid string: ptr=0x%08x $=%d", idata[1], idata[0]); return val; } break; case 'u': wstring wstr; size_t len = idata[0]*wchar.sizeof; wstr = cast(wstring)ctx.readMemory(idata[1], len); if ( wstr is null ) { val.value = format("invalid string: ptr=0x%08x $=%d", idata[1], idata[0]); return val; } str = toUTF8(wstr); break; case 'w': dstring dstr; size_t len = idata[0]*dchar.sizeof; dstr = cast(dstring)ctx.readMemory(idata[1], len); if ( dstr is null ) { val.value = format("invalid string: ptr=0x%08x $=%d", idata[1], idata[0]); return val; } str = toUTF8(dstr); break; default: assert(0); } val.value = "\""~replace(replace(str, "\\", "\\\\"), "\"", "\\\"")~"\""; return val; } } /************************************************************************************************** **************************************************************************************************/ class DataHandler_num : DataHandler { SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) { SymbolValue val = new SymbolValue; switch ( mangled_type[0] ) { case 'a': val.value = (cast(char[])data)[0..1]; break; //~ case 'u': //~ val.value = toUTF8((cast(wchar[])data)[0..1]); //~ break; case 'w': val.value = toUTF8((cast(dchar[])data)[0..1]); break; case 'g': val.value = format("%d", (cast(byte[])data)[0]); break; case 'h': val.value = format("%d", (cast(ubyte[])data)[0]); break; case 's': val.value = format("%d", (cast(short[])data)[0]); break; case 't': case 'u': val.value = format("%d", (cast(ushort[])data)[0]); break; case 'i': val.value = format("%d", (cast(int[])data)[0]); break; case 'P': case 'v': case 'k': val.value = format("0x%08x", (cast(uint[])data)[0]); break; case 'l': val.value = format("%d", (cast(long[])data)[0]); break; case 'm': val.value = format("%d", (cast(ulong[])data)[0]); break; case 'f': val.value = format("% .6g", (cast(float[])data)[0]); break; case 'd': val.value = format("% .12g", (cast(double[])data)[0]); break; case 'e': val.value = format("% .16g", (cast(real[])data)[0]); break; case 'x': case 'b': val.value = format("%s", (cast(bool[])data)[0]?"true":"false"); break; default: assert(0, mangled_type); } return val; } } /************************************************************************************************** **************************************************************************************************/ class DataHandler_bool : DataHandler { SymbolValue toString(EvaluationContext ctx, string mangled_type, ubyte[] data, int depth) { SymbolValue val = new SymbolValue; assert(mangled_type[0]=='b'); val.value = format("%s", (cast(bool[])data)[0]); return val; } }