gb_emulator / gb_debugger_msvs / code_context.cpp

/*  Copyright Š 2011 Chris Spencer <spencercw@gmail.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "stdafx.h"

#include "code_context.h"

#include <iomanip>
#include <sstream>

#include "disassembly_stream.h"

namespace fs = boost::filesystem;
using boost::optional;
using std::hex;
using std::pair;
using std::setfill;
using std::setw;
using std::uppercase;
using std::wostringstream;
using std::wstring;

// IDebugCodeContext2 methods

HRESULT CCodeContext::GetDocumentContext(IDebugDocumentContext2 **ppSrcCxt)
{
	if (!ppSrcCxt)
	{
		return E_POINTER;
	}
	if (!documentContext_)
	{
		return E_FAIL;
	}

	*ppSrcCxt = documentContext_;
	(*ppSrcCxt)->AddRef();
	return S_OK;
}

HRESULT CCodeContext::GetLanguageInfo(BSTR * /*pbstrLanguage*/, GUID * /*pguidLanguage*/)
{
	return E_NOTIMPL;
}

// IDebugMemoryContext2 methods

HRESULT CCodeContext::GetName(BSTR *pbstrName)
{
	(void) pbstrName;

	return E_NOTIMPL;
}

HRESULT CCodeContext::GetInfo(CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO *pInfo)
{
	memset(pInfo, 0, sizeof(*pInfo));

	if (dwFields & CIF_MODULEURL && module_)
	{
		pInfo->dwFields |= CIF_MODULEURL;
		pInfo->bstrModuleUrl = SysAllocString(module_->first.c_str());
	}
	if (dwFields & CIF_ADDRESS)
	{
		wostringstream oss;
		oss << hex << uppercase << setfill(L'0') << L"0x" << setw(8) << static_cast<unsigned>(address_);
		wstring address = oss.str();

		pInfo->dwFields |= CIF_ADDRESS;
		pInfo->bstrAddress = SysAllocString(address.c_str());
	}

	return S_OK;
}

HRESULT CCodeContext::Add(UINT64 dwCount, IDebugMemoryContext2 **ppMemCxt)
{
	(void) dwCount;
	(void) ppMemCxt;

	return E_NOTIMPL;
}

HRESULT CCodeContext::Subtract(UINT64 dwCount, IDebugMemoryContext2 **ppMemCxt)
{
	(void) dwCount;
	(void) ppMemCxt;

	return E_NOTIMPL;
}

HRESULT CCodeContext::Compare(
	CONTEXT_COMPARE compare,
	IDebugMemoryContext2 **rgpMemoryContextSet,
	DWORD dwMemoryContextSetLen,
	DWORD *pdwMemoryContext)
{
	if (!rgpMemoryContextSet || !pdwMemoryContext)
	{
		return E_POINTER;
	}

	for (DWORD i = 0; i != dwMemoryContextSetLen; ++i)
	{
		// Get the CCodeContext interface
		CCodeContext *context = NULL;
		HRESULT hr = rgpMemoryContextSet[i]->QueryInterface(IID_GbDebuggerMsvsCodeContext,
			reinterpret_cast<void **>(&context));
		if (!SUCCEEDED(hr))
		{
			return E_COMPARE_CANNOT_COMPARE;
		}

		// Do the comparison
		switch (compare)
		{
		case CONTEXT_EQUAL:
			// TODO: This should check the module is the same
			if (context->GetAddress() == address_)
			{
				*pdwMemoryContext = i;
				return S_OK;
			}
			break;

		default:
			return E_NOTIMPL;
		}
	}

	return S_FALSE;
}

// CCodeContext methods
 
void CCodeContext::Init(IDebugDocumentContext2 *documentContext, uint32_t address,
	const optional<pair<fs::path, uint32_t> > &module)
{
	documentContext_ = documentContext;
	address_ = address;
	module_ = module;
}

HRESULT CCodeContext::GetDisassemblyStream(DISASSEMBLY_STREAM_SCOPE scope,
	IDebugDisassemblyStream2 **disassemblyStream)
{
	(void) scope;

	if (!disassembly_)
	{
		CComObject<CDisassemblyStream> *disassembly;
		CComObject<CDisassemblyStream>::CreateInstance(&disassembly);
		disassembly_ = disassembly;
		disassembly->Init(this);
	}
	else
	{
		disassembly_->SetAddress(address_);
	}

	*disassemblyStream = disassembly_;
	(*disassemblyStream)->AddRef();
	return S_OK;
}

optional<pair<fs::path, uint32_t> > CCodeContext::GetModule() const
{
	return module_;
}

uint32_t CCodeContext::GetAddress() const
{
	return address_;
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.