Mercurial > projects > ddbg_continued
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/expression/datahandler.d Tue Apr 05 20:44:01 2011 +0200 @@ -0,0 +1,599 @@ +/* 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; + } +}