view src/callstack.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.
 */

import util;
import codeview.codeview;
import expression.evaluationcontext;

import std.string;

/**************************************************************************************************
    Wraps the raw stack data with functions for unwinding it.
**************************************************************************************************/
class CallStack
{
	ubyte[]	data;
	uint	base_ptr,	// the "base" of the stack, i.e. the largest address
			top_ptr,	// the current top of the stack = Esp
			frame_ptr;	// the current frame pointer

	/**********************************************************************************************
        Initializes the object with pointers to base, top (esp) and frame (ebp)
        of the stack. Resizes the data array to the required size.
    **********************************************************************************************/
	this(uint base_ptr_, uint top_ptr_, uint frame_ptr_)
	{
		base_ptr = base_ptr_;
		top_ptr = top_ptr_;
		frame_ptr = frame_ptr_;
		data.length = base_ptr-top_ptr;
	}

	/**********************************************************************************************
        Calculates the first frame.
        Params: prev_index = first byte of previous frame pointer
        Returns: Array covering the frame.
    **********************************************************************************************/
	ubyte[] firstFrame(out uint prev_index)
	{
		prev_index = frame_ptr-top_ptr;
		if ( prev_index >= data.length )
            return data;
		return data[0..prev_index];
	}

	/**********************************************************************************************
        Calculates the previous frame.
        Params:
        frame_index	= start of desired frame in data array
        prev_index	= start of previous to desired frame in data array
        Returns: Array covering the previous frame.
    **********************************************************************************************/
	ubyte[] prevFrame(in uint frame_index, out uint prev_index)
	{
		if ( frame_index >= data.length-4 )
			return null;

		uint prev_frame_ptr = (cast(uint[])data)[frame_index>>2];
		if ( prev_frame_ptr < top_ptr || prev_frame_ptr > base_ptr )
			return null;

		prev_index = prev_frame_ptr-top_ptr;
		assert( prev_index > frame_index && prev_index <= data.length );
		return data[frame_index..prev_index];
	}

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

	**********************************************************************************************/
    ubyte[] getFrame(uint frame_level)
    {
		uint	prev_frame_idx;
		ubyte[]	frame = firstFrame(prev_frame_idx);
		for ( ; frame_level > 0; --frame_level )
			frame = prevFrame(prev_frame_idx, prev_frame_idx);
        return frame;
    }

	/**********************************************************************************************
        Loads data from the stack for a given symbol.
        Returns: Array of bytes continaing the data
    **********************************************************************************************/
	bool loadSymbolData(StackSymbol sym, SymbolData symdata, uint frame_level=0)
	{
		if ( sym is null )
			return false;
		uint	prev_frame_idx;
		ubyte[]	frame = firstFrame(prev_frame_idx);
		for ( ; frame_level > 0; --frame_level )
			frame = prevFrame(prev_frame_idx, prev_frame_idx);

        symdata.defered_load = true;

		bool loadSymbolData(uint offset)
		{
			// index is in this frame
			if ( offset <= frame.length-sym.size ) {
				symdata.len = sym.size;
				symdata.ptr = top_ptr + (frame.ptr - data.ptr) + offset;
				return true;
			}
			assert( offset >= frame.length );
			// consider previous frame
			offset -= frame.length;
			frame = prevFrame(prev_frame_idx, prev_frame_idx);
			if ( frame !is null )
				return loadSymbolData(offset);
			return false;
		}

		return loadSymbolData(frame.length+sym.cvdata.offset);
	}
}