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;
+	}
+}