Commits

spencercw  committed b254a1c

Create a document context class so stack frames can be linked to their source code.

  • Participants
  • Parent commits 226c7ee
  • Branches debugger

Comments (0)

Files changed (11)

File GbDebuggerMsvs/DocumentContext.rgs

+HKCR
+{
+	NoRemove CLSID
+	{
+		ForceRemove {1AB3E935-E5C9-47C0-8858-6B69F1DC978B} = s 'DocumentContext Class'
+		{
+			InprocServer32 = s '%MODULE%'
+			{
+				val ThreadingModel = s 'Apartment'
+			}
+			TypeLib = s '{13703F40-0D7C-4E56-B8A5-85DB92D6944E}'
+			Version = s '1.0'
+		}
+	}
+}

File GbDebuggerMsvs/GbDebuggerMsvs.idl

 	{
 		[default] interface IDebugModule2;
 	};
+	[
+		uuid(1AB3E935-E5C9-47C0-8858-6B69F1DC978B)		
+	]
+	coclass DocumentContext
+	{
+		[default] interface IDebugDocumentContext2;
+	};
 };

File GbDebuggerMsvs/GbDebuggerMsvs.rc

Binary file modified.

File GbDebuggerMsvs/GbDebuggerMsvs.vcxproj

   </ItemDefinitionGroup>
   <ItemGroup>
     <ClCompile Include="code_context.cpp" />
+    <ClCompile Include="document_context.cpp" />
     <ClCompile Include="Engine.cpp" />
     <ClCompile Include="events.cpp" />
     <ClCompile Include="expression.cpp" />
   <ItemGroup>
     <ClInclude Include="com_enum.h" />
     <ClInclude Include="code_context.h" />
+    <ClInclude Include="document_context.h" />
     <ClInclude Include="Engine.h" />
     <ClInclude Include="events.h" />
     <ClInclude Include="expression.h" />
     <ResourceCompile Include="GbDebuggerMsvs.rc" />
   </ItemGroup>
   <ItemGroup>
+    <None Include="DocumentContext.rgs" />
     <None Include="DebugContext.rgs" />
     <None Include="DebugProperty.rgs" />
     <None Include="Engine.rgs" />

File GbDebuggerMsvs/GbDebuggerMsvs.vcxproj.filters

     <ClCompile Include="code_context.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="document_context.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="stdafx.h">
     <ClInclude Include="code_context.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="document_context.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="GbDebuggerMsvs.rc">
     <None Include="GbVsModule.rgs">
       <Filter>Resource Files</Filter>
     </None>
+    <None Include="DocumentContext.rgs">
+      <Filter>Resource Files</Filter>
+    </None>
   </ItemGroup>
   <ItemGroup>
     <Midl Include="GbDebuggerMsvs.idl">

File GbDebuggerMsvs/Program.cpp

 	for (deque<GbStackFrame>::const_reverse_iterator frame = gbStackFrames.rbegin(),
 		end = gbStackFrames.rend(); frame != end; ++frame, ++i)
 	{
-		CComObject<CCodeContext> *context;
-		CComObject<CCodeContext>::CreateInstance(&context);
-		context->AddRef();
-		context->Init(frame->instructionAddr, frame->module);
+		CComObject<CCodeContext> *codeContext;
+		CComObject<CCodeContext>::CreateInstance(&codeContext);
+		codeContext->AddRef();
+		codeContext->Init(frame->instructionAddr, frame->module);
+
+		CComObject<CDocumentContext> *documentContext = NULL;
+		if (frame->hasDebugInfo && !frame->sourceLocation.sourceFile.empty())
+		{
+			CComObject<CDocumentContext>::CreateInstance(&documentContext);
+			documentContext->AddRef();
+			documentContext->Init(frame->sourceLocation.sourceFile, frame->sourceLocation.line);
+		}
 
 		CComObject<CGbVsStackFrame> *debugFrame;
 		CComObject<CGbVsStackFrame>::CreateInstance(&debugFrame);
 		debugFrame->AddRef();
-		debugFrame->Init(*frame, context);
+		debugFrame->Init(*frame, codeContext, documentContext);
 		debugFrame->PopulateFrameInfo(&stackFrames[i], dwFieldSpec, nRadix);
 
-		context->Release();
+		if (documentContext)
+		{
+			documentContext->Release();
+		}
+		codeContext->Release();
 		debugFrame->Release();
 	}
 

File GbDebuggerMsvs/document_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 "document_context.h"
+
+#include <fstream>
+
+using std::string;
+
+// IDebugDocumentContext2 methods
+
+HRESULT CDocumentContext::GetDocument(IDebugDocument2 **ppDocument)
+{
+	std::ofstream f("C:\\Users\\Chris\\gbem_debug.txt", std::ios_base::out | std::ios_base::binary | std::ios_base::app);
+	f << "CDocumentContext::GetDocument\n";
+	f.close();
+
+	(void) ppDocument;
+
+	return E_NOTIMPL;
+}
+
+HRESULT CDocumentContext::GetName(GETNAME_TYPE gnType, BSTR *pbstrFileName)
+{
+	std::ofstream f("C:\\Users\\Chris\\gbem_debug.txt", std::ios_base::out | std::ios_base::binary | std::ios_base::app);
+	f << "CDocumentContext::GetName\n";
+	f.close();
+
+	if (!pbstrFileName)
+	{
+		return E_POINTER;
+	}
+
+	switch (gnType)
+	{
+	case GN_NAME:
+	case GN_FILENAME:
+		*pbstrFileName = filename_.Copy();
+		break;
+
+	default:
+		return E_NOTIMPL;
+	}
+
+	return S_OK;
+}
+
+HRESULT CDocumentContext::EnumCodeContexts(IEnumDebugCodeContexts2 **ppEnumCodeCxts)
+{
+	std::ofstream f("C:\\Users\\Chris\\gbem_debug.txt", std::ios_base::out | std::ios_base::binary | std::ios_base::app);
+	f << "CDocumentContext::EnumCodeContexts\n";
+	f.close();
+
+	(void) ppEnumCodeCxts;
+
+	return E_NOTIMPL;
+}
+
+HRESULT CDocumentContext::GetLanguageInfo(BSTR *pbstrLanguage, GUID *pguidLanguage)
+{
+	std::ofstream f("C:\\Users\\Chris\\gbem_debug.txt", std::ios_base::out | std::ios_base::binary | std::ios_base::app);
+	f << "CDocumentContext::GetLanguageInfo\n";
+	f.close();
+
+	(void) pbstrLanguage;
+	(void) pguidLanguage;
+
+	return E_NOTIMPL;
+}
+
+HRESULT CDocumentContext::GetStatementRange(TEXT_POSITION *pBegPosition,
+	TEXT_POSITION *pEndPosition)
+{
+	std::ofstream f("C:\\Users\\Chris\\gbem_debug.txt", std::ios_base::out | std::ios_base::binary | std::ios_base::app);
+	f << "CDocumentContext::GetStatementRange\n";
+	f.close();
+	
+	if (pBegPosition)
+	{
+		pBegPosition->dwLine = line_;
+		pBegPosition->dwColumn = 0;
+	}
+	if (pEndPosition)
+	{
+		pEndPosition->dwLine = line_;
+		pEndPosition->dwColumn = 0;
+	}
+
+	return S_OK;
+}
+
+HRESULT CDocumentContext::GetSourceRange(TEXT_POSITION *pBegPosition, TEXT_POSITION *pEndPosition)
+{
+	std::ofstream f("C:\\Users\\Chris\\gbem_debug.txt", std::ios_base::out | std::ios_base::binary | std::ios_base::app);
+	f << "CDocumentContext::GetSourceRange\n";
+	f.close();
+
+	(void) pBegPosition;
+	(void) pEndPosition;
+
+	return E_NOTIMPL;
+}
+
+HRESULT CDocumentContext::Compare(
+	DOCCONTEXT_COMPARE compare,
+	IDebugDocumentContext2 **rgpDocContextSet,
+	DWORD dwDocContextSetLen,
+	DWORD *pdwDocContext)
+{
+	std::ofstream f("C:\\Users\\Chris\\gbem_debug.txt", std::ios_base::out | std::ios_base::binary | std::ios_base::app);
+	f << "CDocumentContext::Compare\n";
+	f.close();
+
+	(void) compare;
+	(void) rgpDocContextSet;
+	(void) dwDocContextSetLen;
+	(void) pdwDocContext;
+
+	return E_NOTIMPL;
+}
+
+HRESULT CDocumentContext::Seek(int nCount, IDebugDocumentContext2 **ppDocContext)
+{
+	std::ofstream f("C:\\Users\\Chris\\gbem_debug.txt", std::ios_base::out | std::ios_base::binary | std::ios_base::app);
+	f << "CDocumentContext::Seek\n";
+	f.close();
+
+	(void) nCount;
+	(void) ppDocContext;
+
+	return E_NOTIMPL;
+}
+
+// CDocumentContext methods
+
+void CDocumentContext::Init(const string &filename, unsigned line)
+{
+	filename_.Append(filename.c_str());
+	line_ = line;
+}

File GbDebuggerMsvs/document_context.h

+/*  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/>.  */
+
+#pragma once
+
+#include <atlbase.h>
+#include <atlcom.h>
+
+#include "GbDebuggerMsvs_i.h"
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
+#endif
+
+using namespace ATL;
+
+class ATL_NO_VTABLE CDocumentContext :
+	public CComObjectRootEx<CComSingleThreadModel>,
+	public CComCoClass<CDocumentContext, &CLSID_DocumentContext>,
+	public IDebugDocumentContext2
+{
+public:
+	CDocumentContext()
+	{
+	}
+
+DECLARE_REGISTRY_RESOURCEID(IDR_CDOCUMENTCONTEXT1)
+
+BEGIN_COM_MAP(CDocumentContext)
+	COM_INTERFACE_ENTRY(IDebugDocumentContext2)
+END_COM_MAP()
+
+	// IDebugDocumentContext2 methods
+	STDMETHOD(GetDocument)(IDebugDocument2 **ppDocument);
+	STDMETHOD(GetName)(GETNAME_TYPE gnType, BSTR *pbstrFileName);
+	STDMETHOD(EnumCodeContexts)(IEnumDebugCodeContexts2 **ppEnumCodeCxts);
+	STDMETHOD(GetLanguageInfo)(BSTR *pbstrLanguage, GUID *pguidLanguage);
+	STDMETHOD(GetStatementRange)(TEXT_POSITION *pBegPosition, TEXT_POSITION *pEndPosition);
+	STDMETHOD(GetSourceRange)(TEXT_POSITION *pBegPosition, TEXT_POSITION *pEndPosition);
+	STDMETHOD(Compare)(
+		DOCCONTEXT_COMPARE compare,
+		IDebugDocumentContext2 **rgpDocContextSet,
+		DWORD dwDocContextSetLen,
+		DWORD *pdwDocContext);
+	STDMETHOD(Seek)(int nCount, IDebugDocumentContext2 **ppDocContext);
+
+	DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+	HRESULT FinalConstruct()
+	{
+		return S_OK;
+	}
+
+	void FinalRelease()
+	{
+	}
+
+public:
+	void Init(const std::string &filename, unsigned line);
+
+protected:
+	CComBSTR filename_;
+	unsigned line_;
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(DocumentContext), CDocumentContext)

File GbDebuggerMsvs/resource.h

Binary file modified.

File GbDebuggerMsvs/stack_frame.cpp

 	return S_OK;
 }
 
-HRESULT CGbVsStackFrame::GetDocumentContext(IDebugDocumentContext2 ** /*ppCxt*/)
+HRESULT CGbVsStackFrame::GetDocumentContext(IDebugDocumentContext2 **ppCxt)
 {
 	std::ofstream f("C:\\Users\\Chris\\gbem_debug.txt", std::ios_base::out | std::ios_base::binary | std::ios_base::app);
 	f << "CGbVsStackFrame::GetDocumentContext\n";
 	f.close();
 
-	return E_NOTIMPL;
+	if (documentContext_)
+	{
+		*ppCxt = documentContext_;
+		(*ppCxt)->AddRef();
+		return S_OK;
+	}
+	else
+	{
+		return E_FAIL;
+	}
 }
 
 HRESULT CGbVsStackFrame::GetName(BSTR * /*pbstrName*/)
 	return S_OK;
 }
 
-HRESULT CGbVsStackFrame::GetLanguageInfo(BSTR * /*pbstrLanguage*/, GUID * /*pguidLanguage*/)
+HRESULT CGbVsStackFrame::GetLanguageInfo(BSTR *pbstrLanguage, GUID *pguidLanguage)
 {
 	std::ofstream f("C:\\Users\\Chris\\gbem_debug.txt", std::ios_base::out | std::ios_base::binary | std::ios_base::app);
 	f << "CGbVsStackFrame::GetLanguageInfo\n";
 	f.close();
 
-	return E_NOTIMPL;
+	// {4BC19A8F-8423-4A8B-89CC-EE95FE9FBBB2}
+	static const GUID assemblyGuid =
+		{ 0x4bc19a8f, 0x8423, 0x4a8b, { 0x89, 0xcc, 0xee, 0x95, 0xfe, 0x9f, 0xbb, 0xb2 } };
+
+	if (!frame_.hasDebugInfo || frame_.sourceLocation.sourceFile.empty())
+	{
+		return E_FAIL;
+	}
+
+	switch (frame_.sourceLocation.language)
+	{
+	case CdbFile::SourceLocation::ASSEMBLY:
+		*pbstrLanguage = SysAllocString(L"Assembly");
+		*pguidLanguage = guidCLang;
+		break;
+	case CdbFile::SourceLocation::C:
+		*pbstrLanguage = SysAllocString(L"C");
+		*pguidLanguage = assemblyGuid;
+		break;
+	default:
+		assert(!"all languages should have been handled");
+	}
+
+	return S_OK;
 }
 
 HRESULT CGbVsStackFrame::GetDebugProperty(IDebugProperty2 ** /*ppDebugProp*/)
 
 // CGbVsStackFrame methods
 
-void CGbVsStackFrame::Init(const GbStackFrame &frame, CCodeContext *codeContext)
+void CGbVsStackFrame::Init(const GbStackFrame &frame, CCodeContext *codeContext, CDocumentContext *documentContext)
 {
 	frame_ = frame;
 	codeContext_ = codeContext;
 	codeContext_->AddRef();
+	documentContext_ = documentContext;
 
 	CComObject<CGbVsModule> *module;
 	CComObject<CGbVsModule>::CreateInstance(&module);

File GbDebuggerMsvs/stack_frame.h

 #include <atlcom.h>
 
 #include "code_context.h"
+#include "document_context.h"
 #include "GbDebuggerMsvs_i.h"
 #include "module.h"
 
 	}
 
 public:
-	void Init(const GbStackFrame &frame, CCodeContext *codeContext);
+	void Init(const GbStackFrame &frame, CCodeContext *codeContext,
+		CDocumentContext *documentContext);
 	void PopulateFrameInfo(FRAMEINFO *frameInfo, FRAMEINFO_FLAGS fields, UINT radix);
 
 protected:
 	GbStackFrame frame_;
 	CCodeContext *codeContext_;
+	CComPtr<CDocumentContext> documentContext_;
 	CComPtr<CGbVsModule> module_;
 };