view src/expression/evaluationcontext.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.evaluationcontext;

import container;
import codeview.decl;
import codeview.codeview;
import minidump;
import dbgprocess;
import dbgthread;
import callstack;
import util;
import expression.datahandler;

import std.string;

import win32.winnt;

class EvaluationException : Exception
{
	this(string m) { super(m); }
}

/**************************************************************************************************

**************************************************************************************************/
class SymbolData
{
    string  type;
    bool    defered_load;

    union
    {
        ubyte[] data;
        struct {
            size_t  len,
                    ptr;
        }
    }

    /**********************************************************************************************

    **********************************************************************************************/
    ubyte[] getData(EvaluationContext ctx)
    {
		if ( defered_load )
		{
            debug(eval) DbgIO.println("defered load: ptr=%x len=%d", ptr, len);
			defered_load = false;
			data = ctx.readMemory(ptr, len);
		}
        return data;
    }

    /**********************************************************************************************

    **********************************************************************************************/
    bool loadElementSlice(size_t start, size_t end, CodeView cv)
    {
        assert(end>=start);
        size_t size = cv.sizeofMangled(type);
        start *= size;
        end *= size;
        if ( defered_load )
        {
            if ( end > len )
                return false;
            ptr += start;
            len = end-start;
        }
        else
        {
            if ( end > data.length )
                return false;
            data = data[start..end];
        }
        return true;
    }

    /**********************************************************************************************

    **********************************************************************************************/
    bool loadByteSlice(size_t start, size_t end)
    {
        assert(end>=start);
        if ( defered_load )
        {
            if ( end > len )
                return false;
            ptr += start;
            len = end-start;
        }
        else
        {
            if ( end > data.length )
                return false;
            data = data[start..end];
        }
        return true;
    }
}

/**************************************************************************************************

**************************************************************************************************/
class EvaluationContext
{
    CodeView    codeView;
	MiniDump    miniDump;
	DbgProcess  process;
	DbgThread   thread;

	uint        frameLevel;
	CallStack   stack;
	ScopeSymbol scopeSym;

    NamedSymbol[]   scopeSymbols;

    /**********************************************************************************************

    **********************************************************************************************/
    this(CodeView _cv,
		uint _current_address,
		MiniDump _miniDump,
		DbgProcess _process,
		DbgThread _thread,
		CallStack _stack,
		uint _frame_level=0
    )
    {
        miniDump = _miniDump;
        thread = _thread;
        codeView = _cv;
        process = _process;
        stack = _stack;
        frameLevel = _frame_level;

		uint segment;
		scopeSym = codeView.findProcedureSymbol(_current_address);
        for ( ; scopeSym !is null; scopeSym = scopeSym.parent_scope )
        {
            scopeSymbols ~= scopeSym.symbols.named_symbols;
            ProcedureSymbol psym = cast(ProcedureSymbol)scopeSym;
            if ( psym !is null )
                scopeSymbols ~= psym.arguments.named_symbols;
		}
    }

    bool getContext(out CONTEXT ctx, uint context_flags)
    {
        if ( process !is null )
            return thread.getContext(ctx, context_flags);
        else if ( miniDump !is null ) {
            CONTEXT* ptr = miniDump.getContext;
            if ( ptr !is null ) {
                ctx = *ptr;
                return true;
            }
        }
        return false;
    }

    /**********************************************************************************************

    **********************************************************************************************/
    NamedSymbol findSymbol(string name, inout NamedSymbol[] symbols)
    {
        if ( symbols is null )
        {
            StringWrap sw = new StringWrap(name);
            AVLNode!(NamedSymbol) res;
            if ( codeView.globalNamedSymbols.find(sw, res) )
            {
                NamedSymbol ns = res.value;
                ScopeSymbol scopesym = cast(ScopeSymbol)ns;
                if ( scopesym is null )
                    return ns;
                symbols = scopesym.symbols.named_symbols;
                return null;
            }
            foreach ( ns; scopeSymbols )
            {
                if ( name == ns.name_notype )
                {
                    debug(findSymbol) DbgIO.println("%s == %s", name, ns.name_notype);
                    ScopeSymbol scopesym = cast(ScopeSymbol)ns;
                    if ( scopesym is null )
                        return ns;
                    symbols = scopesym.symbols.named_symbols;
                    return null;
                }
            }
        }
        else
        {
            foreach ( ns; symbols )
            {
                if ( name == ns.name_notype )
                {
                    debug(findSymbol) DbgIO.println("%s == %s", name, ns.name_notype);
                    ScopeSymbol scopesym = cast(ScopeSymbol)ns;
                    if ( scopesym is null )
                        return ns;
                    symbols = scopesym.symbols.named_symbols;
                    return null;
                }
            }
        }
        return null;
    }

    /**********************************************************************************************

    **********************************************************************************************/
    SymbolData loadSymbolData(NamedSymbol symbol)
    {
        StackSymbol stacksym = cast(StackSymbol)symbol;
        SymbolData symdata = new SymbolData;
        if ( stacksym !is null )
        {
            if ( stacksym.size == 0 )
                stacksym.size = codeView.sizeofCV(stacksym.cvdata.type);
            debug(eval) DbgIO.println("reading stack symbol size=%d cv type 0x%x", stacksym.size, stacksym.cvdata.type);
            if ( !stack.loadSymbolData(stacksym, symdata, frameLevel) )
                throw new EvaluationException("Couldn't load stack symbol "~symbol.name_notype);
        }
        else
        {
            DataSymbol datasym = cast(DataSymbol)symbol;
            if ( datasym !is null )
            {
                if ( datasym.size == 0 )
                    datasym.size = codeView.sizeofCV(datasym.cvdata.type);
                debug(eval) DbgIO.println("reading global symbol size=%d cv type 0x%x", datasym.size, datasym.cvdata.type);

                symdata.ptr = codeView.image.getSectionBase(datasym.cvdata.segment)+datasym.cvdata.offset;
                symdata.len = datasym.size;
                symdata.defered_load = true;
            }
            else
                throw new EvaluationException("Can only evaluate Data and Stack Data Symbols, yet");
        }

        symdata.type = codeView.mangleType(symbol);
        if ( symdata.type is null )
            throw new EvaluationException("Symbol "~symbol.name_notype~" has unknown CV type");
        return symdata;
    }

    /**********************************************************************************************

    **********************************************************************************************/
    bool findMember(string ident, LeafFieldList lfl, inout size_t size, inout size_t offset, inout string type)
    {
        if ( lfl is null )
            return false;
        foreach ( l; lfl.fields )
        {
            if ( l.leaf_index == LF_BCLASS_16t )
            {
                LeafBaseClass lbc = cast(LeafBaseClass)l;
                assert ( lbc !is null );
                if ( lbc.type-0x1000 >= codeView.type_strings.length )
                {
                    throw new EvaluationException(
                        "unknown base class "~format("0x%04x", lbc.type)~" in type information for expression"
                    );
                }
                LeafClassStruc lcs = cast(LeafClassStruc)codeView.type_strings[lbc.type-0x1000][0];
                assert ( lcs !is null );
                if ( lcs.field == 0 )
                    continue;
                if ( lcs.field-0x1000 >= codeView.type_strings.length )
                {
                    throw new EvaluationException(
                        "unknown field list "~format("0x%04x", lcs.field)~" in type information for expression"
                    );
                }
                Leaf[] fields = codeView.type_strings[lcs.field-0x1000];
                if ( findMember(ident, cast(LeafFieldList)fields[0], size, offset, type) )
                    return true;
            }
            else if ( l.leaf_index == LF_MEMBER_16t )
            {
                LeafMember lm = cast(LeafMember)l;
                assert ( lm !is null );
                if ( lm.name != ident )
                    continue;
                type	= codeView.mangleCVtype(lm.type);
                size	= codeView.sizeofCV(lm.type);
                offset	= lm.offset.getUint;
                return true;
            }
        }

        return false;
    }

    /**********************************************************************************************

    **********************************************************************************************/
    ubyte[] readMemory(size_t ptr, size_t len)
    {
        if ( miniDump !is null )
            return miniDump.readMemory(ptr, len);

        if ( process is null )
            return null;

        if ( len > process.MEMCHECK_MIN && process.isInvalidMem(ptr, len) )
            return null;
        ubyte data[] = new ubyte[len];
        if ( len != process.readProcessMemory(ptr, data.ptr, data.length) )
            return null;
        return data;
    }
}