internal const int InitialSize = 16;
internal LocalSymInfo?[] m_localSymInfos = null!; // keep track debugging local information
}
-
- /// <summary>
- /// This class tracks the line number info
- /// </summary>
- internal sealed class REDocument
- {
- internal REDocument(ISymbolDocumentWriter document)
- {
- // initialize data variables
- m_iLineNumberCount = 0;
- m_document = document;
- }
-
- internal void AddLineNumberInfo(
- ISymbolDocumentWriter? document,
- int iOffset,
- int iStartLine,
- int iStartColumn,
- int iEndLine,
- int iEndColumn)
- {
- Debug.Assert(document == m_document, "Bad document look up!");
-
- // make sure that arrays are large enough to hold addition info
- EnsureCapacity();
-
- m_iOffsets[m_iLineNumberCount] = iOffset;
- m_iLines[m_iLineNumberCount] = iStartLine;
- m_iColumns[m_iLineNumberCount] = iStartColumn;
- m_iEndLines[m_iLineNumberCount] = iEndLine;
- m_iEndColumns[m_iLineNumberCount] = iEndColumn;
- checked { m_iLineNumberCount++; }
- }
-
- /// <summary>
- /// Helper to ensure arrays are large enough
- /// </summary>
- private void EnsureCapacity()
- {
- if (m_iLineNumberCount == 0)
- {
- // First time. Allocate the arrays.
- m_iOffsets = new int[InitialSize];
- m_iLines = new int[InitialSize];
- m_iColumns = new int[InitialSize];
- m_iEndLines = new int[InitialSize];
- m_iEndColumns = new int[InitialSize];
- }
- else if (m_iLineNumberCount == m_iOffsets.Length)
- {
- // the arrays are full. Enlarge the arrays
- // It would probably be simpler to just use Lists here
- int newSize = checked(m_iLineNumberCount * 2);
- int[] temp = new int[newSize];
- Array.Copy(m_iOffsets, temp, m_iLineNumberCount);
- m_iOffsets = temp;
-
- temp = new int[newSize];
- Array.Copy(m_iLines, temp, m_iLineNumberCount);
- m_iLines = temp;
-
- temp = new int[newSize];
- Array.Copy(m_iColumns, temp, m_iLineNumberCount);
- m_iColumns = temp;
-
- temp = new int[newSize];
- Array.Copy(m_iEndLines, temp, m_iLineNumberCount);
- m_iEndLines = temp;
-
- temp = new int[newSize];
- Array.Copy(m_iEndColumns, temp, m_iLineNumberCount);
- m_iEndColumns = temp;
- }
- }
-
- private int[] m_iOffsets = null!; // array of offsets
- private int[] m_iLines = null!; // array of offsets
- private int[] m_iColumns = null!; // array of offsets
- private int[] m_iEndLines = null!; // array of offsets
- private int[] m_iEndColumns = null!; // array of offsets
- internal ISymbolDocumentWriter m_document; // The ISymbolDocumentWriter that this REDocument is tracking.
- private int m_iLineNumberCount; // how many entries in the arrays are occupied
- private const int InitialSize = 16;
- } // end of REDocument
}
add_subdirectory(daccess)
-add_subdirectory(ildbsymlib)
add_subdirectory(ee)
add_subdirectory(di)
add_subdirectory(shim)
}
InitTargetBufferFromMemoryRange(m, pTargetBuffer);
- // Set the symbol format appropriately
- ESymbolFormat symFormat = pModule->GetInMemorySymbolStreamFormat();
- switch (symFormat)
- {
- case eSymbolFormatPDB:
- *pSymbolFormat = kSymbolFormatPDB;
- break;
-
- case eSymbolFormatILDB:
- *pSymbolFormat = kSymbolFormatILDB;
- break;
-
- default:
- CONSISTENCY_CHECK_MSGF(false, "Unexpected symbol format");
- pTargetBuffer->Clear();
- ThrowHR(E_UNEXPECTED);
- }
+ *pSymbolFormat = kSymbolFormatPDB;
}
#include "winbase.h"
#include "corpriv.h"
#include "corsym.h"
-#include "ildbsymlib.h"
#include "pedecoder.h"
#include "stgpool.h"
(void**)&pBinder));
#endif
}
- else if (symFormat == IDacDbiInterface::kSymbolFormatILDB)
- {
- // ILDB format - use statically linked-in ildbsymlib
- IfFailThrow(IldbSymbolsCreateInstance(CLSID_CorSymBinder_SxS,
- IID_ISymUnmanagedBinder,
- (void**)&pBinder));
- }
else
{
// No in-memory symbols, return the appropriate error
// callback. That callback is defined to pass a PDB stream, and so we still use this
// only for legacy compatibility reasons when we've actually got PDB symbols.
// New clients know they must request a new symbol reader after ClassLoad events.
- if (pRuntimeModule->GetInMemorySymbolStreamFormat() != eSymbolFormatPDB)
+ if (pRuntimeModule->GetInMemorySymbolStream() == NULL)
return; // Non-PDB symbols
DebuggerModule* module = LookupOrCreateModule(pRuntimeModule, pAppDomain);
+++ /dev/null
-if(CLR_CMAKE_HOST_WIN32)
- #use static crt
- set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
-endif(CLR_CMAKE_HOST_WIN32)
-
-set( ILDBSYMLIB_SOURCES
- symread.cpp
- symbinder.cpp
- ildbsymbols.cpp
- symwrite.cpp
-)
-
-add_library_clr(ildbsymlib_obj OBJECT ${ILDBSYMLIB_SOURCES})
-add_library(ildbsymlib INTERFACE)
-target_sources(ildbsymlib INTERFACE $<TARGET_OBJECTS:ildbsymlib_obj>)
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ===========================================================================
-// File: ClassFactory.h
-//
-
-// ===========================================================================
-
-//*****************************************************************************
-// ClassFactory.h
-//
-// Class factories are used by the pluming in COM to activate new objects.
-// This module contains the class factory code to instantiate the
-// ISymUnmanaged Reader,Writer and Binder
-//*****************************************************************************
-#ifndef __ILDBClassFactory__h__
-#define __ILDBClassFactory__h__
-
-// This typedef is for a function which will create a new instance of an object.
-typedef HRESULT (* PFN_CREATE_OBJ)(REFIID riid, void**ppvObject);
-
-//*****************************************************************************
-// This structure is used to declare a global list of coclasses. The class
-// factory object is created with a pointer to the correct one of these, so
-// that when create instance is called, it can be created.
-//*****************************************************************************
-struct COCLASS_REGISTER
-{
- const GUID *pClsid; // Class ID of the coclass.
- LPCWSTR szProgID; // Prog ID of the class.
- PFN_CREATE_OBJ pfnCreateObject; // Creation function for an instance.
-};
-
-
-
-//*****************************************************************************
-// One class factory object satifies all of our clsid's, to reduce overall
-// code bloat.
-//*****************************************************************************
-class CIldbClassFactory :
- public IClassFactory
-{
- CIldbClassFactory() { } // Can't use without data.
-
-public:
- CIldbClassFactory(const COCLASS_REGISTER *pCoClass)
- : m_cRef(1), m_pCoClass(pCoClass)
- { }
-
- virtual ~CIldbClassFactory() {}
-
- //
- // IUnknown methods.
- //
-
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(
- REFIID riid,
- void **ppvObject);
-
- virtual ULONG STDMETHODCALLTYPE AddRef()
- {
- return InterlockedIncrement(&m_cRef);
- }
-
- virtual ULONG STDMETHODCALLTYPE Release()
- {
- LONG cRef = InterlockedDecrement(&m_cRef);
- if (cRef <= 0)
- DELETE(this);
- return (cRef);
- }
-
-
- //
- // IClassFactory methods.
- //
-
- virtual HRESULT STDMETHODCALLTYPE CreateInstance(
- IUnknown *pUnkOuter,
- REFIID riid,
- void **ppvObject);
-
- virtual HRESULT STDMETHODCALLTYPE LockServer(
- BOOL fLock);
-
-
-private:
- LONG m_cRef; // Reference count.
- const COCLASS_REGISTER *m_pCoClass; // The class we belong to.
-};
-
-
-
-#endif // __ClassFactory__h__
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ===========================================================================
-// File: ildbsymbols.cpp
-//
-
-// ===========================================================================
-
-#include "pch.h"
-
-#include "classfactory.h"
-
-// GUID identifying the ILDB format version.
-extern "C" const GUID ILDB_VERSION_GUID = {0x9e02e5b6, 0x8aef, 0x4d06, { 0x82, 0xe8, 0xe, 0x9b, 0x45, 0x49, 0x97, 0x16} };
-
-// Version used for the "first source release", no longer supported.
-extern "C" const GUID ILDB_VERSION_GUID_FSR = {0xCB2F6723, 0xAB3A, 0x11d, { 0x9C, 0x40, 0x00, 0xC0, 0x4F, 0xA3, 0x0A, 0x3E} };
-
-// This map contains the list of coclasses which are exported from this module.
-const COCLASS_REGISTER g_CoClasses[] =
-{
-// pClsid szProgID pfnCreateObject
- { &CLSID_CorSymReader_SxS, W("CorSymReader"), SymReader::NewSymReader},
- { &CLSID_CorSymWriter_SxS, W("CorSymWriter"), SymWriter::NewSymWriter},
- { &CLSID_CorSymBinder_SxS, W("CorSymBinder"), SymBinder::NewSymBinder},
- { NULL, NULL, NULL }
-};
-
-STDAPI IldbSymbolsGetClassObject(REFCLSID rclsid, REFIID riid, void** ppvObject)
-{
- CIldbClassFactory *pClassFactory; // To create class factory object.
- const COCLASS_REGISTER *pCoClass; // Loop control.
- HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
-
- _ASSERTE(IsValidCLSID(rclsid));
- _ASSERTE(IsValidIID(riid));
- _ASSERTE(IsValidWritePtr(ppvObject, void*));
-
- if (ppvObject)
- {
- *ppvObject = NULL;
-
- // Scan for the right one.
- for (pCoClass=g_CoClasses; pCoClass->pClsid; pCoClass++)
- {
- if (*pCoClass->pClsid == rclsid)
- {
- // Allocate the new factory object.
- pClassFactory = NEW(CIldbClassFactory(pCoClass));
- if (!pClassFactory)
- return (E_OUTOFMEMORY);
-
- // Pick the v-table based on the caller's request.
- hr = pClassFactory->QueryInterface(riid, ppvObject);
-
- // Always release the local reference, if QI failed it will be
- // the only one and the object gets freed.
- pClassFactory->Release();
- break;
- }
- }
- }
- else
- {
- hr = E_INVALIDARG;
- }
-
- return hr;
-}
-
-/* ------------------------------------------------------------------------- *
- * CIldbClassFactory class
- * ------------------------------------------------------------------------- */
-
-//*****************************************************************************
-// QueryInterface is called to pick a v-table on the co-class.
-//*****************************************************************************
-HRESULT STDMETHODCALLTYPE CIldbClassFactory::QueryInterface(
- REFIID riid,
- void **ppvObject)
-{
- HRESULT hr;
-
- if (ppvObject == NULL)
- {
- return E_INVALIDARG;
- }
-
- // Avoid confusion.
- *ppvObject = NULL;
-
- // Pick the right v-table based on the IID passed in.
- if (riid == IID_IUnknown)
- *ppvObject = (IUnknown *) this;
- else if (riid == IID_IClassFactory)
- *ppvObject = (IClassFactory *) this;
-
- // If successful, add a reference for out pointer and return.
- if (*ppvObject)
- {
- hr = S_OK;
- AddRef();
- }
- else
- hr = E_NOINTERFACE;
- return (hr);
-}
-
-
-//*****************************************************************************
-// CreateInstance is called to create a new instance of the coclass for which
-// this class was created in the first place. The returned pointer is the
-// v-table matching the IID if there.
-//*****************************************************************************
-HRESULT STDMETHODCALLTYPE CIldbClassFactory::CreateInstance(
- IUnknown *pUnkOuter,
- REFIID riid,
- void **ppvObject)
-{
- HRESULT hr;
-
- _ASSERTE(IsValidIID(riid));
- _ASSERTE(IsValidWritePtr(ppvObject, void*));
-
- // Avoid confusion.
- *ppvObject = NULL;
- _ASSERTE(m_pCoClass);
-
- // Aggregation is not supported by these objects.
- if (pUnkOuter)
- return (CLASS_E_NOAGGREGATION);
-
- // Ask the object to create an instance of itself, and check the iid.
- hr = (*m_pCoClass->pfnCreateObject)(riid, ppvObject);
- return (hr);
-}
-
-// Version of CreateInstance called directly from clients
-STDAPI IldbSymbolsCreateInstance(REFCLSID rclsid, REFIID riid, void** ppvIUnknown)
-{
- IClassFactory *pClassFactory = NULL;
- HRESULT hr = IldbSymbolsGetClassObject(rclsid, IID_IClassFactory, (void**)&pClassFactory);
- if (SUCCEEDED(hr))
- hr = pClassFactory->CreateInstance(NULL, riid, ppvIUnknown);
- if (pClassFactory)
- pClassFactory->Release();
- return hr;
-}
-
-HRESULT STDMETHODCALLTYPE CIldbClassFactory::LockServer(
- BOOL fLock)
-{
- return (S_OK);
-}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ===========================================================================
-// File: pch.h
-//
-
-// ===========================================================================
-
-#ifndef _ILDBSYMLIB_PCH_H_
-#define _ILDBSYMLIB_PCH_H_
-
-#include "ole2.h"
-
-#include "winwrap.h"
-#include "umisc.h"
-
-#include "corhdr.h"
-#include "corsym.h"
-#include "palclr.h"
-#include "cor.h"
-
-// I'm not sure why this code uses these macros for memory management (they should at least be
-// in-line functions). DELETE is a symbol defined in WinNt.h as an access-type. We're probably
-// not going to try and use that, so we'll just override it for now.
-#ifdef DELETE
-#undef DELETE
-#endif
-
-
-#define NEW( x ) ( ::new (nothrow) x )
-#define DELETE( x ) ( ::delete(x) )
-#define DELETEARRAY( x ) (::delete[] (x))
-
-#include "ildbsymlib.h"
-#include "symwrite.h"
-#include "symread.h"
-#include "symbinder.h"
-
-#endif
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ===========================================================================
-// File: pdbdata.h
-//
-
-// ===========================================================================
-
-#ifndef PDBDATA_H_
-#define PDBDATA_H_
-
-#include "umisc.h"
-#include "palclr.h"
-
-struct SymMethodInfo;
-struct SymLexicalScope;
-struct SymVariable;
-struct SymUsingNamespace;
-struct SymConstant;
-struct SequencePoint;
-struct DocumentInfo;
-struct MethodInfo;
-
-extern "C" const GUID ILDB_VERSION_GUID_FSR;
-extern "C" const GUID ILDB_VERSION_GUID;
-
-#define ILDB_MINOR_VERSION_NUMBER 0
-#define ILDB_SIGNATURE "_ildb_signature"
-#define ILDB_SIGNATURE_SIZE (16)
-
-typedef struct PDBInfo {
-
- // Entry point of the PE
- mdMethodDef m_userEntryPoint;
-
- UINT32 m_CountOfMethods;
- UINT32 m_CountOfScopes;
- UINT32 m_CountOfVars;
- UINT32 m_CountOfUsing;
- UINT32 m_CountOfConstants;
- UINT32 m_CountOfDocuments;
- UINT32 m_CountOfSequencePoints;
- UINT32 m_CountOfBytes;
- UINT32 m_CountOfStringBytes;
-
-public:
- PDBInfo()
- {
- memset(this, 0, sizeof(PDBInfo));
- // Make sure m_userEntryPoint initialized correctly
- _ASSERTE(mdTokenNil == 0);
- }
-
-#if BIGENDIAN
- void ConvertEndianness() {
- m_userEntryPoint = VAL32(m_userEntryPoint);
- m_CountOfMethods = VAL32(m_CountOfMethods);
- m_CountOfScopes = VAL32(m_CountOfScopes);
- m_CountOfVars = VAL32(m_CountOfVars);
- m_CountOfUsing = VAL32(m_CountOfUsing);
- m_CountOfConstants = VAL32(m_CountOfConstants);
- m_CountOfSequencePoints = VAL32(m_CountOfSequencePoints);
- m_CountOfDocuments = VAL32(m_CountOfDocuments);
- m_CountOfBytes = VAL32(m_CountOfBytes);
- m_CountOfStringBytes = VAL32(m_CountOfStringBytes);
- }
-#else
- void ConvertEndianness() {}
-#endif
-
-} PDBInfo;
-
-// The signature, Guid version + PDBInfo data
-#define ILDB_HEADER_SIZE (ILDB_SIGNATURE_SIZE + sizeof(GUID) + sizeof(PDBInfo) )
-
-typedef struct PDBDataPointers
-{
- SymMethodInfo * m_pMethods; // Method information
- SymLexicalScope *m_pScopes; // Scopes
- SymVariable *m_pVars; // Local Variables
- SymUsingNamespace *m_pUsings; // list of using/imports
- SymConstant *m_pConstants; // Constants
- DocumentInfo *m_pDocuments; // Documents
- SequencePoint *m_pSequencePoints; // Sequence Points
- // Array of various bytes (variable signature, etc)
- BYTE *m_pBytes;
- // Strings
- BYTE *m_pStringsBytes;
-} PDBDataPointers;
-
-#endif /* PDBDATA_H_ */
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ===========================================================================
-// File: symbinder.cpp
-//
-
-// ===========================================================================
-
-#include "pch.h"
-#include "symbinder.h"
-
-/* ------------------------------------------------------------------------- *
- * SymBinder class
- * ------------------------------------------------------------------------- */
-
-HRESULT
-SymBinder::QueryInterface(
- REFIID riid,
- void **ppvObject
- )
-{
- HRESULT hr = S_OK;
-
- _ASSERTE(IsValidIID(riid));
- _ASSERTE(IsValidWritePtr(ppvObject, void*));
-
- IfFalseGo( ppvObject, E_INVALIDARG );
-
- if (riid == IID_ISymUnmanagedBinder)
- {
- *ppvObject = (ISymUnmanagedBinder*) this;
- }
- else if (riid == IID_ISymUnmanagedBinder2)
- {
- *ppvObject = (ISymUnmanagedBinder2*) this;
- }
- else if (riid == IID_IUnknown)
- {
- *ppvObject = (IUnknown*)this;
- }
- else
- {
- *ppvObject = NULL;
- hr = E_NOINTERFACE;
- }
-
- if (*ppvObject)
- {
- AddRef();
- }
-
-ErrExit:
-
- return hr;
-}
-
-HRESULT
-SymBinder::NewSymBinder(
- REFCLSID clsid,
- void** ppObj
- )
-{
- HRESULT hr = S_OK;
- SymBinder* pSymBinder = NULL;
-
- _ASSERTE(IsValidCLSID(clsid));
- _ASSERTE(IsValidWritePtr(ppObj, IUnknown*));
-
- if (clsid != IID_ISymUnmanagedBinder)
- return (E_UNEXPECTED);
-
- IfFalseGo( ppObj, E_INVALIDARG );
-
- *ppObj = NULL;
-
- IfNullGo( pSymBinder = NEW(SymBinder()) );
- *ppObj = pSymBinder;
- pSymBinder->AddRef();
- pSymBinder = NULL;
-
-ErrExit:
-
- RELEASE( pSymBinder );
-
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetReaderForFile
-//-----------------------------------------------------------
-HRESULT
-SymBinder::GetReaderForFile(
- IUnknown *importer, // IMetaDataImporter
- const WCHAR *fileName, // File we're looking symbols for
- const WCHAR *searchPath, // Search path for file
- ISymUnmanagedReader **ppRetVal) // Out: SymReader for file
-{
- HRESULT hr = S_OK;
- ISymUnmanagedReader *pSymReader = NULL;
- IfFalseGo( ppRetVal && fileName && fileName[0] != '\0', E_INVALIDARG );
-
- // Init Out parameter
- *ppRetVal = NULL;
-
- // Call the class factory directly.
- IfFailGo(IldbSymbolsCreateInstance(CLSID_CorSymReader_SxS,
- IID_ISymUnmanagedReader,
- (void**)&pSymReader));
-
- IfFailGo(pSymReader->Initialize(importer, fileName, searchPath, NULL));
-
- // Transfer ownership to the out parameter
- *ppRetVal = pSymReader;
- pSymReader = NULL;
-
-ErrExit:
- RELEASE(pSymReader);
- return hr;
-}
-
-HRESULT
-SymBinder::GetReaderFromStream(
- IUnknown *importer,
- IStream *pStream,
- ISymUnmanagedReader **ppRetVal
- )
-{
- HRESULT hr = S_OK;
- ISymUnmanagedReader *pSymReader = NULL;
- IfFalseGo( ppRetVal && importer && pStream, E_INVALIDARG );
-
- // Init Out parameter
- *ppRetVal = NULL;
-
- // Call the class factory directly
- IfFailGo(IldbSymbolsCreateInstance(CLSID_CorSymReader_SxS,
- IID_ISymUnmanagedReader,
- (void**)&pSymReader));
-
- IfFailGo(pSymReader->Initialize(importer, NULL, NULL, pStream));
-
- // Transfer ownership to the out parameter
- *ppRetVal = pSymReader;
- pSymReader = NULL;
-
-ErrExit:
- RELEASE(pSymReader);
- return hr;
-}
-
-HRESULT SymBinder::GetReaderForFile2(
- IUnknown *importer,
- const WCHAR *fileName,
- const WCHAR *searchPath,
- ULONG32 searchPolicy,
- ISymUnmanagedReader **pRetVal)
-{
- // This API exists just to allow VS to function properly.
- // ILDB doesn't support any search policy or search path - we only look
- // next to the image file.
- return GetReaderForFile(importer, fileName, searchPath, pRetVal);
-}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ===========================================================================
-// File: SymBinder.h
-//
-
-// ===========================================================================
-
-#ifndef SYMBINDER_H_
-#define SYMBINDER_H_
-
-/* ------------------------------------------------------------------------- *
- * SymBinder class
- * ------------------------------------------------------------------------- */
-
-class SymBinder : ISymUnmanagedBinder2
-{
-// ctor/dtor
-public:
- SymBinder()
- {
- m_refCount = 0;
- }
-
- virtual ~SymBinder() {}
-
- static HRESULT NewSymBinder( REFCLSID clsid, void** ppObj );
-
-// IUnknown methods
-public:
-
- //-----------------------------------------------------------
- // IUnknown support
- //-----------------------------------------------------------
- ULONG STDMETHODCALLTYPE AddRef()
- {
- return (InterlockedIncrement((LONG *) &m_refCount));
- }
-
- ULONG STDMETHODCALLTYPE Release()
- {
- LONG refCount = InterlockedDecrement((LONG *) &m_refCount);
- if (refCount == 0)
- DELETE(this);
-
- return (refCount);
- }
- STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
-
- // ISymUnmanagedBinder
-public:
-
- STDMETHOD(GetReaderForFile)( IUnknown *importer,
- const WCHAR *fileName,
- const WCHAR *searchPath,
- ISymUnmanagedReader **pRetVal);
- STDMETHOD(GetReaderFromStream)(IUnknown *importer,
- IStream *pstream,
- ISymUnmanagedReader **pRetVal);
-
- // ISymUnmanagedBinder2
- STDMETHOD(GetReaderForFile2)( IUnknown *importer,
- const WCHAR *fileName,
- const WCHAR *searchPath,
- ULONG32 searchPolicy,
- ISymUnmanagedReader **pRetVal);
-
-private:
- SIZE_T m_refCount;
-
-};
-#endif
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ===========================================================================
-// File: symread.cpp
-//
-
-// ===========================================================================
-#include "pch.h"
-#include "symread.h"
-#include "corimage.h"
-
-#define CODE_WITH_NO_SOURCE 0xfeefee
-// -------------------------------------------------------------------------
-// SymReader class
-// -------------------------------------------------------------------------
-
-//-----------------------------------------------------------
-// NewSymReader
-// Static function used to create a new instance of SymReader
-//-----------------------------------------------------------
-HRESULT
-SymReader::NewSymReader(
- REFCLSID clsid,
- void** ppObj
- )
-{
- HRESULT hr = S_OK;
- SymReader* pSymReader = NULL;
-
- _ASSERTE(IsValidCLSID(clsid));
- _ASSERTE(IsValidWritePtr(ppObj, IUnknown*));
-
- if (clsid != IID_ISymUnmanagedReader)
- return (E_UNEXPECTED);
-
- IfFalseGo(ppObj, E_INVALIDARG);
-
- *ppObj = NULL;
- IfNullGo( pSymReader = NEW(SymReader()));
-
- *ppObj = pSymReader;
- pSymReader->AddRef();
- pSymReader = NULL;
-
-ErrExit:
-
- RELEASE( pSymReader );
-
- return hr;
-}
-
-
-//-----------------------------------------------------------
-// ~SymReader
-//-----------------------------------------------------------
-SymReader::~SymReader()
-{
- Cleanup();
-}
-
-//-----------------------------------------------------------
-// Cleanup
-// Release all memory and clear initialized data structures
-// (eg. as a result of a failed Initialization attempt)
-//-----------------------------------------------------------
-void SymReader::Cleanup()
-{
- if (m_pDocs)
- {
- unsigned i;
- for(i = 0; i < m_pPDBInfo->m_CountOfDocuments; i++)
- {
- RELEASE(m_pDocs[i]);
- }
- }
-
- DELETE(m_pPDBInfo);
- m_pPDBInfo = NULL;
-
- // If we loaded from stream, then free the memory we allocated
- if (m_fInitializeFromStream)
- {
- DELETEARRAY(m_DataPointers.m_pBytes);
- DELETEARRAY(m_DataPointers.m_pConstants);
- DELETEARRAY(m_DataPointers.m_pDocuments);
- DELETEARRAY(m_DataPointers.m_pMethods);
- DELETEARRAY(m_DataPointers.m_pScopes);
- DELETEARRAY(m_DataPointers.m_pSequencePoints);
- DELETEARRAY(m_DataPointers.m_pStringsBytes);
- DELETEARRAY(m_DataPointers.m_pUsings);
- DELETEARRAY(m_DataPointers.m_pVars);
- }
-
- DELETEARRAY(m_pDocs);
- m_pDocs = NULL;
-
- RELEASE(m_pImporter);
- m_pImporter = NULL;
-
- memset(&m_DataPointers, 0, sizeof(PDBDataPointers));
- m_szPath[0] = '\0';
-}
-
-//-----------------------------------------------------------
-// ~QueryInterface
-//-----------------------------------------------------------
-HRESULT
-SymReader::QueryInterface(
- REFIID riid,
- void **ppvObject
- )
-{
- HRESULT hr = S_OK;
-
- _ASSERTE(IsValidIID(riid));
- _ASSERTE(IsValidWritePtr(ppvObject, void*));
-
- IfFalseGo(ppvObject, E_INVALIDARG);
- if (riid == IID_ISymUnmanagedReader)
- {
- *ppvObject = (ISymUnmanagedReader*) this;
- }
- else
- if (riid == IID_IUnknown)
- {
- *ppvObject = (IUnknown*)this;
- }
- else
- {
- *ppvObject = NULL;
- hr = E_NOINTERFACE;
- }
-
- if (*ppvObject)
- {
- AddRef();
- }
-
-ErrExit:
-
- return hr;
-}
-
-static HRESULT ReadFromStream(IStream *pIStream, void *pv, ULONG cb)
-{
- HRESULT hr = NOERROR;
- ULONG ulBytesRead;
-
- IfFailGo(pIStream->Read(pv, cb, &ulBytesRead));
- if (ulBytesRead != cb)
- IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// Initialize
-// Pass in the required information to read in the debug info
-// If a stream is passed in, it is used, otherwise a filename
-// must be passed in
-//-----------------------------------------------------------
-HRESULT SymReader::Initialize(
- IUnknown *importer, // Cash it to be consistent with CLR
- const WCHAR* szFileName, // File name of the ildb
- const WCHAR* szsearchPath, // Search Path
- IStream *pIStream // IStream
- )
-{
- HRESULT hr = NOERROR;
- _ASSERTE(szFileName || pIStream);
- IfFalseGo(szFileName || pIStream, E_INVALIDARG );
-
- _ASSERTE(!m_fInitialized);
- IfFalseGo(!m_fInitialized, E_UNEXPECTED);
-
- // If it's passed in, we need to AddRef to be consistent the
- // desktop version since ReleaseImporterFromISymUnmanagedReader (ceeload.cpp)
- // assumes there's an addref
- if (importer)
- {
- m_pImporter = importer;
- m_pImporter->AddRef();
- }
-
- // See if we're reading from a file or stream
- if (pIStream == NULL)
- {
- // We're initializing from a file
- m_fInitializeFromStream = false;
- IfFailGo(InitializeFromFile(szFileName, szsearchPath));
- }
- else
- {
- // We're reading in from a stream
- m_fInitializeFromStream = true;
- IfFailGo(InitializeFromStream(pIStream));
- }
-
- // Note that up to this point, the data we've read in has not been validated. Since we don't trust
- // our input, it's important that we don't proceed with using this data until validation has been
- // successful.
- IfFailGo(ValidateData());
-
-
-ErrExit:
- // If we have not succeeded, then we need to clean up our data structures. This would allow a client to call
- // Initialize again, but also ensures we can't possibly use partial or otherwise invalid (possibly
- // malicious) data.
- if (FAILED(hr))
- {
- Cleanup();
- }
- else
- {
- // Otherwise we are not properly initialized
- m_fInitialized = true;
- }
-
- return hr;
-}
-
-//-----------------------------------------------------------
-// Initialize the data structures by reading from the supplied stream
-// Note that upon completion the data has not yet been validated for safety.
-//-----------------------------------------------------------
-HRESULT SymReader::InitializeFromStream(
- IStream *pIStream // IStream
- )
-{
- GUID GuidVersion;
- BYTE *pSignature;
- HRESULT hr = S_OK;
-
- // Reset the stream to the beginning
- LARGE_INTEGER li;
- li.u.HighPart = 0;
- li.u.LowPart = 0;
-
- // Make sure we're at the beginning of the stream
- IfFailGo(pIStream->Seek(li, STREAM_SEEK_SET, NULL));
-
- IfNullGo(pSignature = (BYTE *)_alloca(ILDB_SIGNATURE_SIZE));
- IfFailGo(ReadFromStream(pIStream, pSignature, ILDB_SIGNATURE_SIZE));
-
- // Verify that we're looking at an ILDB File
- if (memcmp(pSignature, ILDB_SIGNATURE, ILDB_SIGNATURE_SIZE))
- {
- IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
- }
-
- IfFailGo(ReadFromStream(pIStream, &GuidVersion, sizeof(GUID)));
-
- SwapGuid(&GuidVersion);
-
- if (memcmp(&GuidVersion, &ILDB_VERSION_GUID, sizeof(GUID)))
- {
- IfFailGo(HrFromWin32(ERROR_INVALID_DATA));
- }
-
- IfNullGo(m_pPDBInfo = NEW(PDBInfo));
-
- memset(m_pPDBInfo, 0 , sizeof(PDBInfo));
- IfFailGo(ReadFromStream(pIStream, m_pPDBInfo, sizeof(PDBInfo)));
-
- // Swap the counts
- m_pPDBInfo->ConvertEndianness();
-
- if (m_pPDBInfo->m_CountOfConstants)
- {
- IfNullGo(m_DataPointers.m_pConstants = NEW(SymConstant[m_pPDBInfo->m_CountOfConstants]));
- IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pConstants, m_pPDBInfo->m_CountOfConstants*sizeof(SymConstant)));
- }
-
- if (m_pPDBInfo->m_CountOfMethods)
- {
- IfNullGo(m_DataPointers.m_pMethods = NEW(SymMethodInfo[m_pPDBInfo->m_CountOfMethods]));
- IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pMethods, m_pPDBInfo->m_CountOfMethods*sizeof(SymMethodInfo)));
- }
-
- if (m_pPDBInfo->m_CountOfScopes)
- {
- IfNullGo(m_DataPointers.m_pScopes = NEW(SymLexicalScope[m_pPDBInfo->m_CountOfScopes]));
- IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pScopes, m_pPDBInfo->m_CountOfScopes*sizeof(SymLexicalScope)));
- }
-
- if (m_pPDBInfo->m_CountOfVars)
- {
- IfNullGo(m_DataPointers.m_pVars = NEW(SymVariable[m_pPDBInfo->m_CountOfVars]));
- IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pVars, m_pPDBInfo->m_CountOfVars*sizeof(SymVariable)));
- }
-
- if (m_pPDBInfo->m_CountOfUsing)
- {
- IfNullGo(m_DataPointers.m_pUsings = NEW(SymUsingNamespace[m_pPDBInfo->m_CountOfUsing]));
- IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pUsings, m_pPDBInfo->m_CountOfUsing*sizeof(SymUsingNamespace)));
- }
-
- if (m_pPDBInfo->m_CountOfSequencePoints)
- {
- IfNullGo(m_DataPointers.m_pSequencePoints = NEW(SequencePoint[m_pPDBInfo->m_CountOfSequencePoints]));
- IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pSequencePoints, m_pPDBInfo->m_CountOfSequencePoints*sizeof(SequencePoint)));
- }
-
- if (m_pPDBInfo->m_CountOfDocuments)
- {
- IfNullGo(m_DataPointers.m_pDocuments = NEW(DocumentInfo[m_pPDBInfo->m_CountOfDocuments]));
- IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pDocuments, m_pPDBInfo->m_CountOfDocuments*sizeof(DocumentInfo)));
- }
-
- if (m_pPDBInfo->m_CountOfBytes)
- {
- IfNullGo(m_DataPointers.m_pBytes = NEW(BYTE[m_pPDBInfo->m_CountOfBytes]));
- IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pBytes, m_pPDBInfo->m_CountOfBytes*sizeof(BYTE)));
- }
-
-
- if (m_pPDBInfo->m_CountOfStringBytes)
- {
- IfNullGo(m_DataPointers.m_pStringsBytes = NEW(BYTE[m_pPDBInfo->m_CountOfStringBytes]));
- IfFailGo(ReadFromStream(pIStream, m_DataPointers.m_pStringsBytes, m_pPDBInfo->m_CountOfStringBytes));
- }
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// ValidateData
-// Checks the contents of everything in m_DataPointers (i.e. all the structures read from the file)
-// to make sure it is valid. Specifically, validates that all indexes are within bounds for the
-// sizes allocated.
-//-----------------------------------------------------------
-HRESULT SymReader::ValidateData()
-{
- HRESULT hr = S_OK;
-
- for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfConstants; i++)
- {
- SymConstant & c = m_DataPointers.m_pConstants[i];
- IfFalseGo(c.ParentScope() < m_pPDBInfo->m_CountOfScopes, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(c.Name() < m_pPDBInfo->m_CountOfStringBytes, HrFromWin32(ERROR_BAD_FORMAT));
- IfFailGo(ValidateBytes(c.Signature(), c.SignatureSize()));
- }
-
- for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfMethods; i++)
- {
- // Note that start/end values may equal the count (i.e. point one past the end) because
- // the end is the extent, and start can equal end to indicate no entries.
- SymMethodInfo & m = m_DataPointers.m_pMethods[i];
- IfFalseGo(m.StartScopes() <= m_pPDBInfo->m_CountOfScopes, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.EndScopes() <= m_pPDBInfo->m_CountOfScopes, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.StartScopes() <= m.EndScopes(), HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.StartVars() <= m_pPDBInfo->m_CountOfVars, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.EndVars() <= m_pPDBInfo->m_CountOfVars, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.StartVars() <= m.EndVars(), HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.StartUsing() <= m_pPDBInfo->m_CountOfUsing, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.EndUsing() <= m_pPDBInfo->m_CountOfUsing, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.StartUsing() <= m.EndUsing(), HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.StartConstant() <= m_pPDBInfo->m_CountOfConstants, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.EndConstant() <= m_pPDBInfo->m_CountOfConstants, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.StartConstant() <= m.EndConstant(), HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.StartDocuments() <= m_pPDBInfo->m_CountOfDocuments, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.EndDocuments() <= m_pPDBInfo->m_CountOfDocuments, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.StartDocuments() <= m.EndDocuments(), HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.StartSequencePoints() <= m_pPDBInfo->m_CountOfSequencePoints, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.EndSequencePoints() <= m_pPDBInfo->m_CountOfSequencePoints, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(m.StartSequencePoints() <= m.EndSequencePoints(), HrFromWin32(ERROR_BAD_FORMAT));
- }
-
- for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfScopes; i++)
- {
- SymLexicalScope & s = m_DataPointers.m_pScopes[i];
- IfFalseGo((s.ParentScope() == (UINT32)-1) || (s.ParentScope() < m_pPDBInfo->m_CountOfScopes), HrFromWin32(ERROR_BAD_FORMAT));
- }
-
- for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfVars; i++)
- {
- SymVariable & v = m_DataPointers.m_pVars[i];
- IfFalseGo(v.Scope() < m_pPDBInfo->m_CountOfScopes, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(v.Name() < m_pPDBInfo->m_CountOfStringBytes, HrFromWin32(ERROR_BAD_FORMAT));
- IfFailGo(ValidateBytes(v.Signature(), v.SignatureSize()));
- }
-
- for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfUsing; i++)
- {
- SymUsingNamespace & u = m_DataPointers.m_pUsings[i];
- IfFalseGo(u.ParentScope() < m_pPDBInfo->m_CountOfScopes, HrFromWin32(ERROR_BAD_FORMAT));
- IfFalseGo(u.Name() < m_pPDBInfo->m_CountOfStringBytes, HrFromWin32(ERROR_BAD_FORMAT));
- }
-
- for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfSequencePoints; i++)
- {
- SequencePoint & s = m_DataPointers.m_pSequencePoints[i];
- IfFalseGo(s.Document() < m_pPDBInfo->m_CountOfDocuments, HrFromWin32(ERROR_BAD_FORMAT));
- }
-
- for (UINT32 i = 0; i < m_pPDBInfo->m_CountOfDocuments; i++)
- {
- DocumentInfo & d = m_DataPointers.m_pDocuments[i];
- IfFailGo(ValidateBytes(d.CheckSumEntry(), d.CheckSumSize()));
- IfFailGo(ValidateBytes(d.SourceEntry(), d.SourceSize()));
- IfFalseGo(d.UrlEntry() < m_pPDBInfo->m_CountOfStringBytes, HrFromWin32(ERROR_BAD_FORMAT));
- }
-
- // Nothing to validate for the m_pBytes array - each reference must validate above that it's
- // length doesn't exceed the array
-
- // We expect all strings to be null terminated. To ensure no string operation overruns the buffer
- // it sufficies to check that the buffer ends in a null character
- if (m_pPDBInfo->m_CountOfStringBytes > 0)
- {
- IfFalseGo(m_DataPointers.m_pStringsBytes[m_pPDBInfo->m_CountOfStringBytes-1] == '\0', HrFromWin32(ERROR_BAD_FORMAT));
- }
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// Validate a reference to the bytes array
-//-----------------------------------------------------------
-HRESULT SymReader::ValidateBytes(UINT32 bytesIndex, UINT32 bytesLen)
-{
- S_UINT32 extent = S_UINT32(bytesIndex) + S_UINT32(bytesLen);
- if (!extent.IsOverflow() &&
- (extent.Value() <= m_pPDBInfo->m_CountOfBytes))
- {
- return S_OK;
- }
-
- return HrFromWin32(ERROR_BAD_FORMAT);
-}
-
-//-----------------------------------------------------------
-// VerifyPEDebugInfo
-// Verify that the debug info in the PE is the one we want
-//-----------------------------------------------------------
-HRESULT SymReader::VerifyPEDebugInfo(const WCHAR* szFileName)
-{
- HRESULT hr = E_FAIL;
- HANDLE hFile = INVALID_HANDLE_VALUE;
- HANDLE hMapFile = INVALID_HANDLE_VALUE;
- BYTE *pMod = NULL;
- DWORD dwFileSize;
- IMAGE_DEBUG_DIRECTORY *pDebugDir;
- RSDSI *pDebugInfo;
- DWORD dwUtf8Length;
- DWORD dwUnicodeLength;
-
- // We need to change the .pdb extension to .ildb
- // compatible with VS7
- WCHAR fullpath[_MAX_PATH];
- WCHAR drive[_MAX_DRIVE];
- WCHAR dir[_MAX_DIR];
- WCHAR fname[_MAX_FNAME];
-
- IMAGE_NT_HEADERS*pNT;
-
- hFile = WszCreateFile(szFileName,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- if (hFile == INVALID_HANDLE_VALUE)
- {
- // Get the last error if we can
- return HrFromWin32(GetLastError());
- }
-
- dwFileSize = GetFileSize(hFile, NULL);
- if (dwFileSize < ILDB_HEADER_SIZE)
- {
- IfFailGo(HrFromWin32(ERROR_INVALID_DATA));
- }
-
- hMapFile = WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
- if (hMapFile == NULL)
- IfFailGo(HrFromWin32(GetLastError()));
-
- pMod = (BYTE *) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
- if (pMod == NULL)
- IfFailGo(HrFromWin32(GetLastError()));
-
- pNT = Cor_RtlImageNtHeader(pMod, dwFileSize);
-
- // If there is no DebugEntry, then just error out
- if (VAL32(pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) == 0)
- IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
-
- // NOTE: This code is not secure against malformed PE files - any of the pointer additions below
- // may be outside the range of memory mapped for the file. If we ever want to use this code
- // on untrusted PE files, we should properly validate everything (probably by using PEDecoder).
-
- DWORD offset;
- offset = Cor_RtlImageRvaToOffset(pNT, VAL32(pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress), dwFileSize);
- if (offset == NULL)
- IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
- pDebugDir = (IMAGE_DEBUG_DIRECTORY *)(pMod + offset);
- pDebugInfo = (RSDSI *)(pMod + VAL32(pDebugDir->PointerToRawData));
-
- if (pDebugInfo->dwSig != VAL32(0x53445352)) // "SDSR"
- {
- IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
- }
-
-
- // Try the returned Stored Name since it might be a fully qualified path
- dwUtf8Length = VAL32(pDebugDir->SizeOfData) - sizeof(RSDSI);
- dwUnicodeLength = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) pDebugInfo->szPDB, dwUtf8Length, fullpath, COUNTOF(fullpath) - 1);
-
- // Make sure it's NULL terminated
- _ASSERTE(dwUnicodeLength < COUNTOF(fullpath));
- fullpath[dwUnicodeLength]='\0';
-
- // Replace the extension with ildb
- if (_wsplitpath_s( fullpath, drive, COUNTOF(drive), dir, COUNTOF(dir), fname, COUNTOF(fname), NULL, 0 ))
- IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
- if (_wmakepath_s(m_szStoredSymbolName, MAX_LONGPATH, drive, dir, fname, W("ildb") ))
- IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
-
- // It looks valid, make sure to set the return code
- hr = S_OK;
-ErrExit:
- if (pMod)
- UnmapViewOfFile(pMod);
- if (hMapFile != INVALID_HANDLE_VALUE)
- CloseHandle(hMapFile);
- if (hFile != INVALID_HANDLE_VALUE)
- CloseHandle(hFile);
- return hr;
-
-}
-
-//-----------------------------------------------------------
-// InitializeFromFile
-// Initialize the reader using the passed in file name
-// Note that upon completion the data hasn't yet been validated for safety.
-//-----------------------------------------------------------
-HRESULT
-SymReader::InitializeFromFile(
- const WCHAR* szFileName,
- const WCHAR* szsearchPath)
-{
- HRESULT hr = S_OK;
- WCHAR fullpath[_MAX_PATH];
- WCHAR drive[_MAX_DRIVE];
- WCHAR dir[_MAX_DIR];
- WCHAR fname[_MAX_FNAME];
- HANDLE hFile = INVALID_HANDLE_VALUE;
- HANDLE hMapFile = INVALID_HANDLE_VALUE;
- HMODULE hMod = NULL;
- BYTE *CurrentOffset;
- DWORD dwFileSize;
- S_UINT32 dwDataSize;
- GUID VersionInfo;
-
- _ASSERTE(szFileName);
- IfFalseGo(szFileName, E_INVALIDARG );
-
- IfFailGo(VerifyPEDebugInfo(szFileName));
- // We need to open the exe and check to see if the DebugInfo matches
-
- if (_wsplitpath_s( szFileName, drive, COUNTOF(drive), dir, COUNTOF(dir), fname, COUNTOF(fname), NULL, 0 ))
- IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
- if (_wmakepath_s( fullpath, _MAX_PATH, drive, dir, fname, W("ildb") ))
- IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
- if (wcsncpy_s( m_szPath, COUNTOF(m_szPath), fullpath, _TRUNCATE) == STRUNCATE)
- IfFailGo(HrFromWin32(ERROR_INSUFFICIENT_BUFFER));
-
- hFile = WszCreateFile(m_szPath,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- if (hFile == INVALID_HANDLE_VALUE)
- {
-
- // If the stored string is empty, don't do anything
- if (m_szStoredSymbolName[0] == '\0')
- {
- return HrFromWin32(GetLastError());
- }
-
- if (_wsplitpath_s( m_szStoredSymbolName, drive, COUNTOF(drive), dir, COUNTOF(dir), fname, COUNTOF(fname), NULL, 0 ))
- IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
- if (_wmakepath_s( fullpath, _MAX_PATH, drive, dir, fname, W("ildb") ))
- IfFailGo(HrFromWin32(ERROR_BAD_FORMAT));
- if (wcsncpy_s( m_szPath, COUNTOF(m_szPath), fullpath, _TRUNCATE) == STRUNCATE)
- IfFailGo(HrFromWin32(ERROR_INSUFFICIENT_BUFFER));
-
- hFile = WszCreateFile(m_szPath,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- if (hFile == INVALID_HANDLE_VALUE)
- {
- return HrFromWin32(GetLastError());
- }
- }
-
- dwFileSize = GetFileSize(hFile, NULL);
- if (dwFileSize < ILDB_HEADER_SIZE)
- {
- IfFailGo(HrFromWin32(ERROR_INVALID_DATA));
- }
-
- hMapFile = WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
- if (hMapFile == NULL)
- IfFailGo(HrFromWin32(GetLastError()));
-
- hMod = (HMODULE) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
- if (hMod == NULL)
- IfFailGo(HrFromWin32(GetLastError()));
-
- // We've opened the file, now let's get the pertinent info
- CurrentOffset = (BYTE *)hMod;
-
- // Verify that we're looking at an ILDB File
- if (memcmp(CurrentOffset, ILDB_SIGNATURE, ILDB_SIGNATURE_SIZE))
- {
- IfFailGo(E_FAIL);
- }
- CurrentOffset += ILDB_SIGNATURE_SIZE;
-
- memcpy( &VersionInfo, CurrentOffset, sizeof(GUID));
- SwapGuid( &VersionInfo );
- CurrentOffset += sizeof(GUID);
-
- if (memcmp(&VersionInfo, &ILDB_VERSION_GUID, sizeof(GUID)))
- {
- IfFailGo(HrFromWin32(ERROR_INVALID_DATA));
- }
-
- IfNullGo(m_pPDBInfo = NEW(PDBInfo));
-
- memcpy(m_pPDBInfo, CurrentOffset, sizeof(PDBInfo));
-
- // Swap the counts
- m_pPDBInfo->ConvertEndianness();
-
- // Check to make sure we have enough data to be read in.
- dwDataSize = S_UINT32(ILDB_HEADER_SIZE);
- dwDataSize += m_pPDBInfo->m_CountOfConstants*sizeof(SymConstant);
- dwDataSize += m_pPDBInfo->m_CountOfMethods * sizeof(SymMethodInfo);
- dwDataSize += m_pPDBInfo->m_CountOfScopes*sizeof(SymLexicalScope);
- dwDataSize += m_pPDBInfo->m_CountOfVars*sizeof(SymVariable);
- dwDataSize += m_pPDBInfo->m_CountOfUsing*sizeof(SymUsingNamespace);
- dwDataSize += m_pPDBInfo->m_CountOfSequencePoints*sizeof(SequencePoint);
- dwDataSize += m_pPDBInfo->m_CountOfDocuments*sizeof(DocumentInfo);
- dwDataSize += m_pPDBInfo->m_CountOfBytes*sizeof(BYTE);
- dwDataSize += m_pPDBInfo->m_CountOfStringBytes*sizeof(BYTE);
-
- if (dwDataSize.IsOverflow() || dwDataSize.Value() > dwFileSize)
- {
- IfFailGo(HrFromWin32(ERROR_INVALID_DATA));
- }
-
- CurrentOffset += sizeof(PDBInfo);
-
- if (m_pPDBInfo->m_CountOfConstants)
- {
- m_DataPointers.m_pConstants = (SymConstant*)CurrentOffset;
- CurrentOffset += (m_pPDBInfo->m_CountOfConstants*sizeof(SymConstant));
- }
-
- if (m_pPDBInfo->m_CountOfMethods)
- {
- m_DataPointers.m_pMethods = (SymMethodInfo *)CurrentOffset;
- CurrentOffset += (m_pPDBInfo->m_CountOfMethods*sizeof(SymMethodInfo));
- }
-
- if (m_pPDBInfo->m_CountOfScopes)
- {
- m_DataPointers.m_pScopes = (SymLexicalScope *)CurrentOffset;
- CurrentOffset += (m_pPDBInfo->m_CountOfScopes*sizeof(SymLexicalScope));
- }
-
- if (m_pPDBInfo->m_CountOfVars)
- {
- m_DataPointers.m_pVars = (SymVariable *)CurrentOffset;
- CurrentOffset += (m_pPDBInfo->m_CountOfVars*sizeof(SymVariable));
- }
-
- if (m_pPDBInfo->m_CountOfUsing)
- {
- m_DataPointers.m_pUsings = (SymUsingNamespace *)CurrentOffset;
- CurrentOffset += (m_pPDBInfo->m_CountOfUsing*sizeof(SymUsingNamespace));
- }
-
- if (m_pPDBInfo->m_CountOfSequencePoints)
- {
- m_DataPointers.m_pSequencePoints = (SequencePoint*)CurrentOffset;
- CurrentOffset += (m_pPDBInfo->m_CountOfSequencePoints*sizeof(SequencePoint));
- }
-
- if (m_pPDBInfo->m_CountOfDocuments)
- {
- m_DataPointers.m_pDocuments = (DocumentInfo*)CurrentOffset;
- CurrentOffset += (m_pPDBInfo->m_CountOfDocuments*sizeof(DocumentInfo));
- }
-
- if (m_pPDBInfo->m_CountOfBytes)
- {
- m_DataPointers.m_pBytes = (BYTE*)CurrentOffset;
- CurrentOffset += (m_pPDBInfo->m_CountOfBytes*sizeof(BYTE));
- }
-
- if (m_pPDBInfo->m_CountOfStringBytes)
- {
- m_DataPointers.m_pStringsBytes = (BYTE*)CurrentOffset;
- }
-
-ErrExit:
- if (hMod)
- UnmapViewOfFile(hMod);
- if (hMapFile != INVALID_HANDLE_VALUE)
- CloseHandle(hMapFile);
- if (hFile != INVALID_HANDLE_VALUE)
- CloseHandle(hFile);
-
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetDocument
-// Get the document for the passed in information
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetDocument(
- __in LPWSTR wcsUrl, // URL of the document
- GUID language, // Language for the file
- GUID languageVendor, // Language vendor
- GUID documentType, // Type of document
- ISymUnmanagedDocument **ppRetVal // [out] Document
- )
-{
- HRESULT hr = S_OK;
- unsigned i;
- SymDocument* pDoc = NULL;
- WCHAR *wcsDocumentUrl = NULL;
- WCHAR *wcsDocumentUrlAlloc = NULL;
-
- _ASSERTE(m_fInitialized);
- IfFalseGo(m_fInitialized, E_UNEXPECTED);
-
- _ASSERTE(ppRetVal && wcsUrl);
- IfFalseGo(ppRetVal, E_INVALIDARG);
- IfFalseGo(wcsUrl, E_INVALIDARG);
-
- // Init Out Parameter
- *ppRetVal = NULL;
-
- for (i = 0; i < m_pPDBInfo->m_CountOfDocuments; i++)
- {
- int cchName;
-
- // Convert the UTF8 string to Wide
- cchName = (ULONG32) MultiByteToWideChar(CP_UTF8,
- 0,
- (LPCSTR)&(m_DataPointers.m_pStringsBytes[m_DataPointers.m_pDocuments[i].UrlEntry()]),
- -1,
- 0,
- NULL);
- IfNullGo( wcsDocumentUrlAlloc = NEW(WCHAR[cchName]) );
-
- cchName = (ULONG32) MultiByteToWideChar(CP_UTF8,
- 0,
- (LPCSTR)&(m_DataPointers.m_pStringsBytes[m_DataPointers.m_pDocuments[i].UrlEntry()]),
- -1,
- wcsDocumentUrlAlloc,
- cchName);
- wcsDocumentUrl = wcsDocumentUrlAlloc;
-
- // Compare the url
- if (wcscmp(wcsUrl, wcsDocumentUrl) == 0)
- {
- IfFailGo(GetDocument(i, &pDoc));
- break;
- }
- DELETEARRAY(wcsDocumentUrlAlloc);
- wcsDocumentUrlAlloc = NULL;
- }
-
- if (pDoc)
- {
- IfFailGo( pDoc->QueryInterface( IID_ISymUnmanagedDocument,
- (void**) ppRetVal ) );
- }
-
-ErrExit:
- DELETEARRAY(wcsDocumentUrlAlloc);
-
- RELEASE( pDoc );
-
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetDocuments
-// Get the documents for this reader
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetDocuments(
- ULONG32 cDocs,
- ULONG32 *pcDocs,
- ISymUnmanagedDocument *pDocs[]
- )
-{
- HRESULT hr = S_OK;
- unsigned cDocCount = 0;
-
- _ASSERTE(m_fInitialized);
- IfFalseGo(m_fInitialized, E_UNEXPECTED);
-
- _ASSERTE(pDocs || pcDocs);
- IfFalseGo(pDocs || pcDocs, E_INVALIDARG);
-
- cDocs = min(cDocs, m_pPDBInfo->m_CountOfDocuments);
-
- for (cDocCount = 0; cDocCount < cDocs; cDocCount++)
- {
- if (pDocs)
- {
- SymDocument *pDoc;
- IfFailGo(GetDocument(cDocCount, &pDoc));
- pDocs[cDocCount] = pDoc;
- }
- }
- if (pcDocs)
- {
- *pcDocs = (ULONG32)m_pPDBInfo->m_CountOfDocuments;
- }
-
-ErrExit:
- if (FAILED(hr))
- {
- unsigned i;
- for (i = 0; i < cDocCount; i++)
- {
- RELEASE(pDocs[cDocCount]);
- }
- }
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetUserEntryPoint
-// Get the entry point for the pe
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetUserEntryPoint(
- mdMethodDef *pRetVal
- )
-{
- HRESULT hr = S_OK;
-
- _ASSERTE(m_fInitialized);
- IfFalseGo(m_fInitialized, E_UNEXPECTED);
-
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
-
- // If it wasn't set then return E_FAIL
- if (m_pPDBInfo->m_userEntryPoint == mdTokenNil)
- {
- hr = E_FAIL;
- }
- else
- {
- *pRetVal = m_pPDBInfo->m_userEntryPoint;
- }
-ErrExit:
- return hr;
-}
-
-// Compare the method token with the SymMethodInfo Entry and return the
-// value expected by bsearch
-int __cdecl CompareMethodToToken(const void *pMethodToken, const void *pMethodInfoEntry)
-{
- mdMethodDef MethodDef = *(mdMethodDef *)pMethodToken;
- SymMethodInfo *pMethodInfo = (SymMethodInfo *)pMethodInfoEntry;
-
- return MethodDef - pMethodInfo->MethodToken();
-}
-
-//-----------------------------------------------------------
-// GetMethod
-// Get the method for the methoddef
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetMethod(
- mdMethodDef method, // MethodDef
- ISymUnmanagedMethod **ppRetVal // [out] Method
- )
-{
- HRESULT hr = S_OK;
- UINT32 MethodEntry = 0;
- SymMethodInfo *pMethodInfo;
- SymMethod * pMethod = NULL;
-
- _ASSERTE(m_fInitialized);
- IfFalseGo(m_fInitialized, E_UNEXPECTED);
-
- _ASSERTE(ppRetVal);
- IfFalseGo(ppRetVal, E_INVALIDARG);
-
- pMethodInfo = (SymMethodInfo *)bsearch(&method, m_DataPointers.m_pMethods, m_pPDBInfo->m_CountOfMethods, sizeof(SymMethodInfo), CompareMethodToToken);
- IfFalseGo(pMethodInfo, E_FAIL); // no matching method found
-
- // Found a match
- MethodEntry = UINT32 (pMethodInfo - m_DataPointers.m_pMethods);
- _ASSERTE(m_DataPointers.m_pMethods[MethodEntry].MethodToken() == method);
- IfNullGo( pMethod = NEW(SymMethod(this, &m_DataPointers, MethodEntry)) );
- *ppRetVal = pMethod;
- pMethod->AddRef();
- hr = S_OK;
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetMethodByVersion
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetMethodByVersion(
- mdMethodDef method,
- int version,
- ISymUnmanagedMethod **ppRetVal
- )
-{
- // Don't support multiple version of the same Method so just
- // call GetMethod
- return GetMethod(method, ppRetVal);
-}
-
-
-//-----------------------------------------------------------
-// GetMethodFromDocumentPosition
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetMethodFromDocumentPosition(
- ISymUnmanagedDocument *document,
- ULONG32 line,
- ULONG32 column,
- ISymUnmanagedMethod **ppRetVal
-)
-{
- HRESULT hr = S_OK;
- UINT32 DocumentEntry;
- UINT32 Method;
- UINT32 point;
- SequencePoint *pSequencePointBefore;
- SequencePoint *pSequencePointAfter;
- bool found = false;
-
- _ASSERTE(m_fInitialized);
- IfFalseGo(m_fInitialized, E_UNEXPECTED);
-
- _ASSERTE(document && ppRetVal);
- IfFalseGo(document, E_INVALIDARG);
- IfFalseGo(ppRetVal, E_INVALIDARG);
-
- DocumentEntry = ((SymDocument *)document)->GetDocumentEntry();
-
- // Init out parameter
- *ppRetVal = NULL;
-
- // Walk all Methods, check their Document and SequencePoints to see if it's in this doc
- // and the line/column
-
- // This function returns the first match if more than one methods cover the specified position.
- for (Method = 0; Method < m_pPDBInfo->m_CountOfMethods; Method++)
- {
- pSequencePointBefore = NULL;
- pSequencePointAfter = NULL;
-
- // Walk the sequence points
- for (point = m_DataPointers.m_pMethods[Method].StartSequencePoints();
- point < m_DataPointers.m_pMethods[Method].EndSequencePoints();
- point++)
- {
- // Check to see if this sequence point is in this doc
- if (m_DataPointers.m_pSequencePoints[point].Document() == DocumentEntry)
- {
- // If the point is position is within the sequence point then
- // we're done.
- if (m_DataPointers.m_pSequencePoints[point].IsWithin(line, column))
- {
- IfFailGo(GetMethod(m_DataPointers.m_pMethods[Method].MethodToken(), ppRetVal));
- found = true;
- break;
- }
-
- // If the sequence is before the point then just remember the point
- if (m_DataPointers.m_pSequencePoints[point].IsUserLine() &&
- m_DataPointers.m_pSequencePoints[point].IsLessThan(line, column))
- {
- pSequencePointBefore = &m_DataPointers.m_pSequencePoints[point];
- }
-
- // If the sequence is before the point then just remember the point
- if (m_DataPointers.m_pSequencePoints[point].IsUserLine() &&
- m_DataPointers.m_pSequencePoints[point].IsGreaterThan(line, column))
- {
- pSequencePointAfter = &m_DataPointers.m_pSequencePoints[point];
- }
- }
- }
-
- // If we found an exact match, we're done.
- if (found)
- {
- break;
- }
-
- // If we found sequence points within the method before and after
- // the line/column then we may have found the method. Record the return value, but keep looking
- // to see if we find an exact match. This may not actually be the right method. Iron Python, for instance,
- // issues a "method" containing sequence points for all the method headers in a class. Sequence points
- // in this "method" would then span the sequence points in the bodies of all but the last method.
- if (pSequencePointBefore && pSequencePointAfter)
- {
- IfFailGo(GetMethod(m_DataPointers.m_pMethods[Method].MethodToken(), ppRetVal));
- }
- }
-
- // This function returns E_FAIL if no match is found.
- // Note that this is different from the behaviour of GetMethodsFromDocumentPosition() (see below).
- if (*ppRetVal == NULL)
- {
- hr = E_FAIL;
- }
-
-ErrExit:
- return hr;
-}
-
-//---------------------------------------------------------------------------------------
-//
-// Return all methods with sequence points covering the specified source location. This
-// is actually not as straighforward as it sounds, since we need to mimic the behaviour of
-// diasymreader and PDBs here. For PDBs, diasymreader actually does two passes over the
-// sequence points. It tries to find an exact match in the first pass, and if that fails,
-// it'll do a second pass looking for an approximate match. An approximate match is a sequence
-// point which doesn't start on the specified line but covers it. If there's an exact match,
-// then it ignores all the approximate matches. In both cases, diasymreader only checks the
-// start line number of the sequence point and it ignores the column number.
-//
-// For backward compatibility, I'm leaving GetMethodFromDocumentPosition() unchanged.
-//
-
-HRESULT
-SymReader::GetMethodsFromDocumentPosition(
- ISymUnmanagedDocument *document,
- ULONG32 line,
- ULONG32 column,
- ULONG32 cMethod,
- ULONG32* pcMethod, //[Optional]: How many method actually returned
- ISymUnmanagedMethod** ppRetVal
- )
-{
- HRESULT hr = S_OK;
- UINT32 DocumentEntry;
- UINT32 Method;
- UINT32 point;
-
- UINT CurMethod = 0;
- bool found = false;
- bool fExactMatch = true;
-
- ULONG32 maxPreLine = 0;
-
- _ASSERTE(m_fInitialized);
- IfFalseGo(m_fInitialized, E_UNEXPECTED);
-
- _ASSERTE(document);
- IfFalseGo(document, E_INVALIDARG);
-
- _ASSERTE((cMethod == 0) || (ppRetVal != NULL));
- IfFalseGo(cMethod == 0 || ppRetVal != NULL, E_INVALIDARG);
-
- // Initialize the out parameter if it has been provided.
- if (pcMethod != NULL)
- {
- *pcMethod = 0;
- }
-
- DocumentEntry = ((SymDocument *)document)->GetDocumentEntry();
-
- // Enumerate the sequence points in two passes.
- while (true)
- {
- // Walk all Methods, check their Document and SequencePoints to see if it's in this doc
- // and the line/column
-
- for (Method = 0; Method < m_pPDBInfo->m_CountOfMethods; Method++)
- {
- found = false;
-
- // Walk the sequence points
- for (point = m_DataPointers.m_pMethods[Method].StartSequencePoints();
- point < m_DataPointers.m_pMethods[Method].EndSequencePoints();
- point++)
- {
- // Check to see if this sequence point is in this doc
- if (m_DataPointers.m_pSequencePoints[point].Document() == DocumentEntry)
- {
- // PDBs (more specifically the DIA APIs) only check the start line number and not the end line number when
- // trying to determine whether a sequence point covers the specified line number. We need to match this
- // behaviour here. For backward compatibility reasons, GetMethodFromDocumentPosition() is still checking
- // against the entire range of a sequence point, but we should revisit that in the next release.
- ULONG32 curLine = m_DataPointers.m_pSequencePoints[point].StartLine();
-
- if (fExactMatch)
- {
- if (curLine == line)
- {
- found = true;
- }
- else if ((maxPreLine < curLine) && (curLine < line))
- {
- // This is not an exact match, but let's keep track of the sequence point closest to the specified
- // line. We'll use this info if we have to do a second pass.
- maxPreLine = curLine;
- }
- }
- else
- {
- // We are in the second pass, looking for approximate matches.
- if ((maxPreLine != 0) && (maxPreLine == curLine))
- {
- // Make sure the sequence point covers the specified line.
- if (m_DataPointers.m_pSequencePoints[point].IsWithinLineOnly(line))
- {
- found = true;
- }
- }
- }
-
- // If we have found a match (whether it's exact or approximate), then save this method unless the caller is
- // only interested in the number of matching methods or the array provided by the caller isn't big enough.
- if (found)
- {
- if (CurMethod < cMethod)
- {
- IfFailGo(GetMethod(m_DataPointers.m_pMethods[Method].MethodToken(), &(ppRetVal[CurMethod])));
- }
- CurMethod++;
- break;
- }
- }
- }
-
- if (found)
- {
- // If we have already filled out the entire array provided by the caller, then we are done.
- if ((cMethod > 0) && (cMethod == CurMethod))
- {
- break;
- }
- else
- {
- // Otherwise move on to the next method.
- continue;
- }
- }
- }
-
- // If we haven't found an exact match, then try it again looking for a sequence point covering the specified line.
- if (fExactMatch && (CurMethod == 0))
- {
- fExactMatch = false;
- continue;
- }
- else
- {
- // If we have found an exact match, or if we have done two passes already, then bail.
- break;
- }
- }
-
- // Note that unlike GetMethodFromDocumentPosition(), this function returns S_OK even if a match is not found.
- if (SUCCEEDED(hr))
- {
- if (pcMethod != NULL)
- {
- *pcMethod = CurMethod;
- }
- }
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetSymbolStoreFileName
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetSymbolStoreFileName(
- ULONG32 cchName, // Length of szName
- ULONG32 *pcchName, // [Optional]
- __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[] // [Optional]
- )
-{
- _ASSERTE(m_fInitialized);
- if (!m_fInitialized)
- return E_UNEXPECTED;
-
- if (pcchName)
- {
- *pcchName = (ULONG32)(wcslen(m_szPath)+1);
- }
-
- if( szName )
- {
- if (wcsncpy_s( szName, cchName, m_szPath, _TRUNCATE) == STRUNCATE)
- return HrFromWin32(ERROR_INSUFFICIENT_BUFFER);
- }
-
- return NOERROR;
-}
-
-//-----------------------------------------------------------
-// GetMethodVersion
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetMethodVersion(
- ISymUnmanagedMethod * pMethod,
- int* pVersion
- )
-{
- HRESULT hr = S_OK;
-
- _ASSERTE(m_fInitialized);
- IfFalseGo(m_fInitialized, E_UNEXPECTED);
-
- _ASSERTE(pMethod && pVersion);
- IfFalseGo( pMethod && pVersion, E_INVALIDARG);
- // This symbol store only supports one version of a method
- *pVersion = 0;
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetDocumentVersion
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetDocumentVersion(
- ISymUnmanagedDocument* pDoc,
- int* pVersion,
- BOOL* pbCurrent // [Optional]
- )
-{
- HRESULT hr = S_OK;
-
- _ASSERTE(m_fInitialized);
- IfFalseGo(m_fInitialized, E_UNEXPECTED);
-
- _ASSERTE(pVersion && pDoc);
- IfFalseGo(pVersion, E_INVALIDARG);
- IfFalseGo(pDoc, E_INVALIDARG);
-
- // This symbol store only supports one version of a document
- *pVersion = 0;
- if (pbCurrent)
- {
- *pbCurrent = TRUE;
- }
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetDocument
-// Return the document for the given entry
-//-----------------------------------------------------------
-HRESULT SymReader::GetDocument(
- UINT32 DocumentEntry,
- SymDocument **ppDocument)
-{
- HRESULT hr = NOERROR;
-
- _ASSERTE(m_fInitialized);
- IfFalseGo(m_fInitialized, E_UNEXPECTED);
-
- _ASSERTE(ppDocument);
- IfFalseGo(ppDocument, E_INVALIDARG);
-
- _ASSERTE(DocumentEntry < m_pPDBInfo->m_CountOfDocuments);
- IfFalseGo(DocumentEntry < m_pPDBInfo->m_CountOfDocuments, E_INVALIDARG);
-
- if (m_pDocs == NULL)
- {
- IfNullGo(m_pDocs = NEW(SymDocument *[m_pPDBInfo->m_CountOfDocuments]));
- memset(m_pDocs, 0, m_pPDBInfo->m_CountOfDocuments * sizeof(void *));
- }
-
- if (m_pDocs[DocumentEntry] == NULL)
- {
- m_pDocs[DocumentEntry] = NEW(SymDocument(this, &m_DataPointers, m_pPDBInfo->m_CountOfMethods, DocumentEntry));
- IfNullGo(m_pDocs[DocumentEntry]);
- // AddRef the table version
- m_pDocs[DocumentEntry]->AddRef();
-
- }
-
- //Set and AddRef the Out Parameter
- *ppDocument = m_pDocs[DocumentEntry];
- (*ppDocument)->AddRef();
-
-ErrExit:
- return hr;
-}
-
-HRESULT
-SymReader::UpdateSymbolStore(
- const WCHAR *filename,
- IStream *pIStream
- )
-{
- // This symbol store doesn't support updating the symbol store.
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-HRESULT
-SymReader::ReplaceSymbolStore(
- const WCHAR *filename,
- IStream *pIStream
- )
-{
- // This symbol store doesn't support updating the symbol store.
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// GetVariables
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetVariables(
- mdToken parent,
- ULONG32 cVars,
- ULONG32 *pcVars,
- ISymUnmanagedVariable *pVars[]
- )
-{
- //
- // This symbol reader doesn't support non-local variables.
- //
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// GetGlobalVariables
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetGlobalVariables(
- ULONG32 cVars,
- ULONG32 *pcVars,
- ISymUnmanagedVariable *pVars[]
- )
-{
- //
- // This symbol reader doesn't support non-local variables.
- //
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// GetSymAttribute
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetSymAttribute(
- mdToken parent,
- __in LPWSTR name,
- ULONG32 cBuffer,
- ULONG32 *pcBuffer,
- __out_bcount_part_opt(cBuffer, *pcBuffer) BYTE buffer[]
- )
-{
- // This symbol store doesn't support attributes
- // VS may query for certain attributes, but will survive without them,
- // so don't ASSERT here.
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// GetNamespaces
-//-----------------------------------------------------------
-HRESULT
-SymReader::GetNamespaces(
- ULONG32 cNameSpaces,
- ULONG32 *pcNameSpaces,
- ISymUnmanagedNamespace *namespaces[]
- )
-{
- // This symbol store doesn't support this
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-/* ------------------------------------------------------------------------- *
- * SymDocument class
- * ------------------------------------------------------------------------- */
-
-HRESULT
-SymDocument::QueryInterface(
- REFIID riid,
- void **ppInterface
- )
-{
- if (ppInterface == NULL)
- return E_INVALIDARG;
-
- if (riid == IID_ISymUnmanagedDocument)
- *ppInterface = (ISymUnmanagedDocument*)this;
- else if (riid == IID_IUnknown)
- *ppInterface = (IUnknown*)(ISymUnmanagedDocument*)this;
- else
- {
- *ppInterface = NULL;
- return E_NOINTERFACE;
- }
-
- AddRef();
- return S_OK;
-}
-
-
-//-----------------------------------------------------------
-// GetURL
-//-----------------------------------------------------------
-HRESULT
-SymDocument::GetURL(
- ULONG32 cchUrl, // The allocated size of the buffer
- ULONG32 *pcchUrl, // [optional,out] The number of characters available for return
- __out_ecount_part_opt(cchUrl, *pcchUrl) WCHAR szUrl[] // [optional,out] The string buffer.
- )
-{
- if (pcchUrl)
- {
- // Convert the UTF8 string to Wide
- *pcchUrl = (ULONG32) MultiByteToWideChar(CP_UTF8,
- 0,
- (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pDocuments[m_DocumentEntry].UrlEntry()]),
- -1,
- 0,
- NULL);
- }
-
- if( szUrl )
- {
- // Convert the UTF8 string to Wide
- MultiByteToWideChar(CP_UTF8,
- 0,
- (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pDocuments[m_DocumentEntry].UrlEntry()]),
- -1,
- szUrl,
- cchUrl);
- }
- return NOERROR;
-}
-
-//-----------------------------------------------------------
-// GetDocumentType
-//-----------------------------------------------------------
-HRESULT
-SymDocument::GetDocumentType(
- GUID *pRetVal
- )
-{
- HRESULT hr = NOERROR;
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
- *pRetVal = m_pData->m_pDocuments[m_DocumentEntry].DocumentType();
- SwapGuid(pRetVal);
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetLanguage
-//-----------------------------------------------------------
-HRESULT
-SymDocument::GetLanguage(
- GUID *pRetVal
- )
-{
- HRESULT hr = NOERROR;
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
-
- *pRetVal = m_pData->m_pDocuments[m_DocumentEntry].Language();
- SwapGuid(pRetVal);
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetLanguageVendor
-//-----------------------------------------------------------
-HRESULT
-SymDocument::GetLanguageVendor(
- GUID *pRetVal
- )
-{
- HRESULT hr = NOERROR;
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
- *pRetVal = m_pData->m_pDocuments[m_DocumentEntry].LanguageVendor();
- SwapGuid(pRetVal);
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetCheckSumAlgorithmId
-//-----------------------------------------------------------
-HRESULT
-SymDocument::GetCheckSumAlgorithmId(
- GUID *pRetVal
- )
-{
- HRESULT hr = NOERROR;
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
- *pRetVal = m_pData->m_pDocuments[m_DocumentEntry].AlgorithmId();
- SwapGuid(pRetVal);
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetCheckSum
-//-----------------------------------------------------------
-HRESULT
-SymDocument::GetCheckSum(
- ULONG32 cData, // The allocated size of the buffer.
- ULONG32 *pcData, // [optional] The number of bytes available for return
- BYTE data[]) // [optional] The buffer to receive the checksum.
-{
- BYTE *pCheckSum = &m_pData->m_pBytes[m_pData->m_pDocuments[m_DocumentEntry].CheckSumEntry()];
- ULONG32 CheckSumSize = m_pData->m_pDocuments[m_DocumentEntry].CheckSumSize();
- if (pcData)
- {
- *pcData = CheckSumSize;
- }
- if(data)
- {
- memcpy(data, pCheckSum, min(CheckSumSize, cData));
- }
- return NOERROR;
-}
-
-//-----------------------------------------------------------
-// FindClosestLine
-// Search the sequence points looking a line that is closest
-// line following this one that is a sequence point
-//-----------------------------------------------------------
-HRESULT
-SymDocument::FindClosestLine(
- ULONG32 line,
- ULONG32 *pRetVal
- )
-{
- HRESULT hr = NOERROR;
- UINT32 Method;
- UINT32 point;
- ULONG32 closestLine = 0; // GCC can't tell this isn't used before initialization
- bool found = false;
-
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
-
- // Walk all Methods, check their Document and SequencePoints to see if it's in this doc
- // and the line/column
- for (Method = 0; Method < m_CountOfMethods; Method++)
- {
- // Walk the sequence points
- for (point = m_pData->m_pMethods[Method].StartSequencePoints();
- point < m_pData->m_pMethods[Method].EndSequencePoints();
- point++)
- {
- SequencePoint & sp = m_pData->m_pSequencePoints[point];
- // Check to see if this sequence point is in this doc, and is at or
- // after the requested line
- if ((sp.Document() == m_DocumentEntry) && sp.IsUserLine())
- {
- if (sp.IsWithin(line, 0) || sp.IsGreaterThan(line, 0))
- {
- // This sequence point is at or after the requested line. If we haven't
- // already found a "closest", or this is even closer than the one we have,
- // then mark this as the best line so far.
- if (!found || m_pData->m_pSequencePoints[point].StartLine() < closestLine)
- {
- found = true;
- closestLine = m_pData->m_pSequencePoints[point].StartLine();
- }
- }
- }
- }
- }
-
- if (found)
- {
- *pRetVal = closestLine;
- }
- else
- {
- // Didn't find any lines at or after the one requested.
- hr = E_FAIL;
- }
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymDocument HasEmbeddedSource
-//-----------------------------------------------------------
-HRESULT
-SymDocument::HasEmbeddedSource(
- BOOL *pRetVal
- )
-{
- //
- // This symbol reader doesn't support embedded source.
- //
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// SymDocument GetSourceLength
-//-----------------------------------------------------------
-HRESULT
-SymDocument::GetSourceLength(
- ULONG32 *pRetVal
- )
-{
- //
- // This symbol reader doesn't support embedded source.
- //
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// SymDocument GetSourceRange
-//-----------------------------------------------------------
-HRESULT
-SymDocument::GetSourceRange(
- ULONG32 startLine,
- ULONG32 startColumn,
- ULONG32 endLine,
- ULONG32 endColumn,
- ULONG32 cSourceBytes,
- ULONG32 *pcSourceBytes,
- BYTE source[]
- )
-{
- //
- // This symbol reader doesn't support embedded source.
- //
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-/* ------------------------------------------------------------------------- *
- * SymMethod class
- * ------------------------------------------------------------------------- */
-HRESULT
-SymMethod::QueryInterface(
- REFIID riid,
- void **ppInterface
- )
-{
- if (ppInterface == NULL)
- return E_INVALIDARG;
-
- if (riid == IID_ISymUnmanagedMethod)
- *ppInterface = (ISymUnmanagedMethod*)this;
- else if (riid == IID_IUnknown)
- *ppInterface = (IUnknown*)(ISymUnmanagedMethod*)this;
- else
- {
- *ppInterface = NULL;
- return E_NOINTERFACE;
- }
-
- AddRef();
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// GetToken
-//-----------------------------------------------------------
-HRESULT
-SymMethod::GetToken(
- mdMethodDef *pRetVal
-)
-{
- HRESULT hr = S_OK;
-
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
- *pRetVal = m_pData->m_pMethods[m_MethodEntry].MethodToken();
-ErrExit:
- return hr;
-}
-
-
-//-----------------------------------------------------------
-// GetSequencePointCount
-//-----------------------------------------------------------
-HRESULT
-SymMethod::GetSequencePointCount(
- ULONG32* pRetVal
- )
-{
-
- HRESULT hr = S_OK;
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
-
- *pRetVal = (ULONG32)(m_pData->m_pMethods[m_MethodEntry].EndSequencePoints() -
- m_pData->m_pMethods[m_MethodEntry].StartSequencePoints());
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetSequencePoints
-//-----------------------------------------------------------
-HRESULT
-SymMethod::GetSequencePoints(
- ULONG32 cPoints, // The size of the allocated arrays.
- ULONG32* pcPoints, // [optional] The number of sequence points available for return.
- ULONG32 offsets[], // [optional]
- ISymUnmanagedDocument *documents[], // [Optional]
- ULONG32 lines[], // [Optional]
- ULONG32 columns[], // [Optional]
- ULONG32 endLines[], // [Optional]
- ULONG32 endColumns[] // [Optional]
- )
-{
- HRESULT hr = NOERROR;
- UINT32 i = 0;
- ULONG32 Points = 0;
-
- for (i = m_pData->m_pMethods[m_MethodEntry].StartSequencePoints();
- (i < m_pData->m_pMethods[m_MethodEntry].EndSequencePoints());
- i++, Points++)
- {
- if (Points < cPoints)
- {
- if (documents)
- {
- SymDocument *pDoc;
- IfFailGo(m_pReader->GetDocument(m_pData->m_pSequencePoints[i].Document(), &pDoc));
- documents[Points] = pDoc;
- }
-
- if (offsets)
- {
- offsets[Points] = m_pData->m_pSequencePoints[i].Offset();
- }
-
- if (lines)
- {
- lines[Points] = m_pData->m_pSequencePoints[i].StartLine();
- }
- if (columns)
- {
- columns[Points] = m_pData->m_pSequencePoints[i].StartColumn();
- }
- if (endLines)
- {
- endLines[Points] = m_pData->m_pSequencePoints[i].EndLine();
- }
- if (endColumns)
- {
- endColumns[Points] = m_pData->m_pSequencePoints[i].EndColumn();
- }
- }
- }
-
- if (pcPoints)
- {
- *pcPoints = Points;
- }
-
-ErrExit:
- if (FAILED(hr))
- {
- if (documents)
- {
- unsigned j;
- for (j = 0; j < i; j++)
- {
- RELEASE(documents[i]);
- }
- }
- }
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetRootScope
-//-----------------------------------------------------------
-HRESULT
-SymMethod::GetRootScope(
- ISymUnmanagedScope **ppRetVal
- )
-{
- HRESULT hr = S_OK;
- SymScope *pScope = NULL;
- _ASSERTE(ppRetVal);
- IfFalseGo(ppRetVal, E_INVALIDARG);
-
- // Init Out Param
- *ppRetVal = NULL;
- if (m_pData->m_pMethods[m_MethodEntry].EndScopes() - m_pData->m_pMethods[m_MethodEntry].StartScopes())
- {
- IfNullGo(pScope = NEW(SymScope(this, m_pData, m_MethodEntry, m_pData->m_pMethods[m_MethodEntry].StartScopes())));
- pScope->AddRef();
- *ppRetVal = pScope;
- }
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetOffset
-// Given a position in a document, gets the offset within the
-// method that corresponds to the position.
-//-----------------------------------------------------------
-HRESULT
-SymMethod::GetOffset(
- ISymUnmanagedDocument *document,
- ULONG32 line,
- ULONG32 column,
- ULONG32 *pRetVal
- )
-{
- HRESULT hr = S_OK;
- bool fFound = false;
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
-
- UINT32 point;
- UINT32 DocumentEntry;
-
- DocumentEntry = ((SymDocument *)document)->GetDocumentEntry();
-
- // Walk the sequence points
- for (point = m_pData->m_pMethods[m_MethodEntry].StartSequencePoints();
- point < m_pData->m_pMethods[m_MethodEntry].EndSequencePoints();
- point++)
- {
- // Check to see if this sequence point is in this doc
- if (m_pData->m_pSequencePoints[point].Document() == DocumentEntry)
- {
- // Check to see if it's within the sequence point
- if (m_pData->m_pSequencePoints[point].IsWithin(line, column))
- {
- *pRetVal = m_pData->m_pSequencePoints[point].Offset();
- fFound = true;
- break;
- }
- }
- }
- if (!fFound)
- {
- hr = E_FAIL;
- }
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetRanges
-//-----------------------------------------------------------
-HRESULT
-SymMethod::GetRanges(
- ISymUnmanagedDocument *pDocument, // [in] Document we're working on
- ULONG32 line, // [in] The document line corresponding to the ranges.
- ULONG32 column, // [in] Ignored
- ULONG32 cRanges, // [in] The size of the allocated ranges[] array.
- ULONG32 *pcRanges, // [out] The number of ranges available for return
- ULONG32 ranges[] // [out] The range array.
- )
-{
- HRESULT hr = NOERROR;
- DWORD iRange = 0;
- UINT32 DocumentEntry;
- UINT32 point;
- bool fFound = false;
-
- // Validate some of the parameters
- _ASSERTE(pDocument && (cRanges % 2) == 0);
- IfFalseGo(pDocument, E_INVALIDARG);
- IfFalseGo((cRanges % 2) == 0, E_INVALIDARG);
-
- // Init out parameter
- if (pcRanges)
- {
- *pcRanges=0;
- }
-
- DocumentEntry = ((SymDocument *)pDocument)->GetDocumentEntry();
-
- // Walk the sequence points
- for (point = m_pData->m_pMethods[m_MethodEntry].StartSequencePoints();
- point < m_pData->m_pMethods[m_MethodEntry].EndSequencePoints();
- point++)
- {
- // Check to see if this sequence point is in this doc
- if (m_pData->m_pSequencePoints[point].Document() == DocumentEntry)
- {
- // Check to see if the line is within this sequence
- // Note, to be compatible with VS7, ignore the column information
- if (line >= m_pData->m_pSequencePoints[point].StartLine() &&
- line <= m_pData->m_pSequencePoints[point].EndLine())
- {
- fFound = true;
- break;
- }
- }
- }
-
- if (fFound)
- {
- for (;point < m_pData->m_pMethods[m_MethodEntry].EndSequencePoints(); point++)
- {
-
- // Search through all the sequence points since line might have there
- // IL spread across multiple ranges (for loops for example)
- if (m_pData->m_pSequencePoints[point].Document() == DocumentEntry &&
- line >= m_pData->m_pSequencePoints[point].StartLine() &&
- line <= m_pData->m_pSequencePoints[point].EndLine())
- {
- if (iRange < cRanges)
- {
- ranges[iRange] = m_pData->m_pSequencePoints[point].Offset();
- }
- iRange++;
- if (iRange < cRanges)
- {
- if (point+1 < m_pData->m_pMethods[m_MethodEntry].EndSequencePoints())
- {
- ranges[iRange] = m_pData->m_pSequencePoints[point+1].Offset();
- }
- else
- {
- // Then it must be till the end of the function which is the root scope's endoffset
- ranges[iRange] = m_pData->m_pScopes[m_pData->m_pMethods[m_MethodEntry].StartScopes()].EndOffset()+1;
- }
- }
- iRange++;
- }
- }
- if (pcRanges)
- {
- // If cRanges passed in, return the number
- // of elements actually filled in
- if (cRanges)
- {
- *pcRanges = min(iRange, cRanges);
- }
- else
- {
- // Otherwise return the max number
- *pcRanges = iRange;
- }
- }
- }
- else
- {
- return E_FAIL;
- }
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetScopeFromOffset
-//-----------------------------------------------------------
-HRESULT
-SymMethod::GetScopeFromOffset(
- ULONG32 offset,
- ISymUnmanagedScope **pRetVal
- )
-{
- //
- // This symbol reader doesn't support this functionality
- //
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// GetParameters
-//-----------------------------------------------------------
-HRESULT
-SymMethod::GetParameters(
- ULONG32 cParams,
- ULONG32 *pcParams,
- ISymUnmanagedVariable *params[]
- )
-{
- //
- // This symbol reader doesn't support parameter access. Parameters
- // can be found in the normal metadata.
- //
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// GetNamespace
-//-----------------------------------------------------------
-HRESULT
-SymMethod::GetNamespace(
- ISymUnmanagedNamespace **ppRetVal
- )
-{
- //
- // This symbol reader doesn't support namespaces
- //
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// GetSourceStartEnd
-//-----------------------------------------------------------
-HRESULT
-SymMethod::GetSourceStartEnd(
- ISymUnmanagedDocument *docs[2],
- ULONG32 lines[2],
- ULONG32 columns[2],
- BOOL *pRetVal
- )
-{
- //
- // This symbol reader doesn't support source start/end for methods.
- //
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-/* ------------------------------------------------------------------------- *
- * SymScope class
- * ------------------------------------------------------------------------- */
-
-//-----------------------------------------------------------
-// QueryInterface
-//-----------------------------------------------------------
-HRESULT
-SymScope::QueryInterface(
- REFIID riid,
- void **ppInterface
- )
-{
- if (ppInterface == NULL)
- return E_INVALIDARG;
-
- if (riid == IID_ISymUnmanagedScope)
- *ppInterface = (ISymUnmanagedScope*)this;
- else if (riid == IID_IUnknown)
- *ppInterface = (IUnknown*)(ISymUnmanagedScope*)this;
- else
- {
- *ppInterface = NULL;
- return E_NOINTERFACE;
- }
-
- AddRef();
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// GetMethod
-//-----------------------------------------------------------
-HRESULT
-SymScope::GetMethod(
- ISymUnmanagedMethod **ppRetVal
- )
-{
- HRESULT hr = S_OK;
-
- _ASSERTE(ppRetVal);
- IfFalseGo(ppRetVal, E_INVALIDARG);
-
- *ppRetVal = m_pSymMethod;
- m_pSymMethod->AddRef();
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetParent
-//-----------------------------------------------------------
-HRESULT
-SymScope::GetParent(
- ISymUnmanagedScope **ppRetVal
- )
-{
- HRESULT hr = S_OK;
- _ASSERTE(ppRetVal);
- IfFalseGo(ppRetVal, E_INVALIDARG);
- if (m_pData->m_pScopes[m_ScopeEntry].ParentScope() != (UINT32)-1)
- {
- IfNullGo(*ppRetVal = static_cast<ISymUnmanagedScope *>(NEW(SymScope(m_pSymMethod, m_pData, m_MethodEntry,
- m_pData->m_pScopes[m_ScopeEntry].ParentScope()))));
- (*ppRetVal)->AddRef();
- }
- else
- {
- *ppRetVal = NULL;
- }
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetChildren
-//-----------------------------------------------------------
-HRESULT
-SymScope::GetChildren(
- ULONG32 cChildren, // [optional] Number of entries in children
- ULONG32 *pcChildren, // [optional, out] Number of Children available for retur
- ISymUnmanagedScope *children[] // [optional] array to store children into
- )
-{
- HRESULT hr = S_OK;
- ULONG32 ChildrenCount = 0;
- _ASSERTE(pcChildren || (children && cChildren));
- IfFalseGo((pcChildren || (children && cChildren)), E_INVALIDARG);
-
- if (m_pData->m_pScopes[m_ScopeEntry].HasChildren())
- {
- UINT32 ScopeEntry;
- for(ScopeEntry = m_pData->m_pMethods[m_MethodEntry].StartScopes();
- (ScopeEntry < m_pData->m_pMethods[m_MethodEntry].EndScopes());
- ScopeEntry++)
- {
- if (m_pData->m_pScopes[ScopeEntry].ParentScope() == m_ScopeEntry)
- {
- if (children && ChildrenCount < cChildren)
- {
- SymScope *pScope;
- // Found a child
- IfNullGo(pScope = NEW(SymScope(m_pSymMethod, m_pData, m_MethodEntry, ScopeEntry)));
- children[ChildrenCount] = pScope;
- pScope->AddRef();
- }
- ChildrenCount++;
- }
- }
- }
-
- if (pcChildren)
- {
- *pcChildren = ChildrenCount;
- }
-
-ErrExit:
- if (FAILED(hr) && ChildrenCount)
- {
- unsigned i;
- for (i =0; i< ChildrenCount; i++)
- {
- RELEASE(children[i]);
- }
- }
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetStartOffset
-//-----------------------------------------------------------
-HRESULT
-SymScope::GetStartOffset(
- ULONG32* pRetVal
- )
-{
- HRESULT hr = S_OK;
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
- *pRetVal = m_pData->m_pScopes[m_ScopeEntry].StartOffset();
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetEndOffset
-//-----------------------------------------------------------
-HRESULT
-SymScope::GetEndOffset(
- ULONG32* pRetVal
- )
-{
- HRESULT hr = S_OK;
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
- *pRetVal = m_pData->m_pScopes[m_ScopeEntry].EndOffset();
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetLocalCount
-//-----------------------------------------------------------
-HRESULT
-SymScope::GetLocalCount(
- ULONG32 *pRetVal
- )
-{
- HRESULT hr = S_OK;
- ULONG32 LocalCount = 0;
- _ASSERTE(pRetVal);
- IfFalseGo(pRetVal, E_INVALIDARG);
-
- // Init out parameter
- *pRetVal = 0;
- if (m_pData->m_pScopes[m_ScopeEntry].HasVars())
- {
- UINT32 var;
- // Walk and get the locals for this Scope
- for (var = m_pData->m_pMethods[m_MethodEntry].StartVars();
- var < m_pData->m_pMethods[m_MethodEntry].EndVars();
- var++)
- {
- if (m_pData->m_pVars[var].Scope() == m_ScopeEntry &&
- m_pData->m_pVars[var].IsParam() == false)
- {
- LocalCount++;
- }
- }
- }
-
- *pRetVal = LocalCount;
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetLocals
-// Input: either pcLocals or
-// cLocals and pLocals
-//-----------------------------------------------------------
-HRESULT
-SymScope::GetLocals(
- ULONG32 cLocals, // [optional] available entries in pLocals
- ULONG32 *pcLocals, // [optional, out] Number of locals returned
- ISymUnmanagedVariable *pLocals[] // [optional] array to store locals into
- )
-{
- HRESULT hr = S_OK;
-
- ULONG32 LocalCount = 0;
- _ASSERTE(pcLocals || pLocals);
- IfFalseGo(pcLocals || pLocals, E_INVALIDARG);
-
- if (m_pData->m_pScopes[m_ScopeEntry].HasVars())
- {
- UINT32 var;
- // Walk and get the locals for this Scope
- for (var = m_pData->m_pMethods[m_MethodEntry].StartVars();
- var < m_pData->m_pMethods[m_MethodEntry].EndVars();
- var++)
- {
- if (m_pData->m_pVars[var].Scope() == m_ScopeEntry &&
- m_pData->m_pVars[var].IsParam() == false)
- {
- if (pLocals && LocalCount < cLocals)
- {
- SymReaderVar *pVar;
- IfNullGo( pVar = NEW(SymReaderVar(this, m_pData, var)));
- pLocals[LocalCount] = pVar;
- pVar->AddRef();
- }
- LocalCount++;
- }
- }
- }
- if (pcLocals)
- {
- *pcLocals = LocalCount;
- }
-ErrExit:
- if (FAILED(hr) && LocalCount != 0)
- {
- unsigned i;
- for (i =0; i < LocalCount; i++)
- {
- RELEASE(pLocals[i]);
- }
- }
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetNamespaces
-// Input: either pcNameSpaces or
-// cNameSpaces and pNameSpaces
-//-----------------------------------------------------------
-HRESULT
-SymScope::GetNamespaces(
- ULONG32 cNameSpaces, // [optional] number of entries pNameSpaces
- ULONG32 *pcNameSpaces, // [optional, out] Maximum number of Namespace
- ISymUnmanagedNamespace *pNameSpaces[] // [optional] array to store namespaces into
- )
-{
- HRESULT hr = NOERROR;
- unsigned i;
- UINT32 NameSpace;
- unsigned NameSpaceCount = 0;
-
- _ASSERTE(pcNameSpaces || (pNameSpaces && cNameSpaces));
- IfFalseGo(pcNameSpaces || (pNameSpaces && cNameSpaces), E_INVALIDARG);
-
- for (NameSpace = m_pData->m_pMethods[m_MethodEntry].StartUsing();
- NameSpace < m_pData->m_pMethods[m_MethodEntry].EndUsing();
- NameSpace++)
- {
- if (m_pData->m_pUsings[NameSpace].ParentScope() == m_ScopeEntry)
- {
- if (pNameSpaces && (NameSpaceCount < cNameSpaces) )
- {
- IfNullGo(pNameSpaces[NameSpaceCount] = NEW(SymReaderNamespace(this, m_pData, NameSpace)));
- pNameSpaces[NameSpaceCount]->AddRef();
- }
- NameSpaceCount++;
- }
- }
- if (pcNameSpaces)
- {
- *pcNameSpaces = NameSpaceCount;
- }
-ErrExit:
- if (FAILED(hr) && pNameSpaces)
- {
- for (i = 0; (i < cNameSpaces) && (i < NameSpaceCount); i++)
- {
- RELEASE(pNameSpaces[i]);
- }
- }
- return hr;
-}
-
-/* ------------------------------------------------------------------------- *
- * SymReaderVar class
- * ------------------------------------------------------------------------- */
-
-//-----------------------------------------------------------
-// QueryInterface
-//-----------------------------------------------------------
-HRESULT
-SymReaderVar::QueryInterface(
- REFIID riid,
- void **ppInterface
- )
-{
- if (ppInterface == NULL)
- return E_INVALIDARG;
-
- if (riid == IID_ISymUnmanagedVariable)
- *ppInterface = (ISymUnmanagedVariable*)this;
- else if (riid == IID_IUnknown)
- *ppInterface = (IUnknown*)(ISymUnmanagedVariable*)this;
- else
- {
- *ppInterface = NULL;
- return E_NOINTERFACE;
- }
-
- AddRef();
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// GetName
-//-----------------------------------------------------------
-HRESULT
-SymReaderVar::GetName(
- ULONG32 cchName, // [optional] Length of szName buffer
- ULONG32 *pcchName, // [optional, out] Total size needed to return the name
- __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[] // [optional] Buffer to store the name into.
- )
-{
- HRESULT hr = S_OK;
-
- // We must have at least one combination
- _ASSERTE(pcchName || (szName && cchName));
- IfFalseGo( (pcchName || (szName && cchName)), E_INVALIDARG );
-
- if (pcchName)
- {
- // Convert the UTF8 string to Wide
- *pcchName = (ULONG32) MultiByteToWideChar(CP_UTF8,
- 0,
- (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pVars[m_VarEntry].Name()]),
- -1,
- 0,
- NULL);
-
- }
- if (szName)
- {
- // Convert the UTF8 string to Wide
- MultiByteToWideChar(CP_UTF8,
- 0,
- (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pVars[m_VarEntry].Name()]),
- -1,
- szName,
- cchName);
- }
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetAttributes
-//-----------------------------------------------------------
-HRESULT
-SymReaderVar::GetAttributes(
- ULONG32 *pRetVal // [out]
- )
-{
- if (pRetVal == NULL)
- return E_INVALIDARG;
-
- *pRetVal = m_pData->m_pVars[m_VarEntry].Attributes();
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// GetSignature
-//-----------------------------------------------------------
-HRESULT
-SymReaderVar::GetSignature(
- ULONG32 cSig, // Size of allocated buffer passed in (sig)
- ULONG32 *pcSig, // [optional, out] Total size needed to return the signature
- BYTE sig[] // [Optional] Signature
- )
-{
- HRESULT hr = S_OK;
-
- _ASSERTE(pcSig || sig);
- IfFalseGo( pcSig || sig, E_INVALIDARG );
- if (pcSig)
- {
- *pcSig = m_pData->m_pVars[m_VarEntry].SignatureSize();
- }
- if (sig)
- {
- cSig = min(m_pData->m_pVars[m_VarEntry].SignatureSize(), cSig);
- memcpy(sig, &m_pData->m_pBytes[m_pData->m_pVars[m_VarEntry].Signature()],cSig);
- }
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetAddressKind
-//-----------------------------------------------------------
-HRESULT
-SymReaderVar::GetAddressKind(
- ULONG32 *pRetVal // [out]
- )
-{
- HRESULT hr = S_OK;
- _ASSERTE(pRetVal);
- IfFalseGo( pRetVal, E_INVALIDARG );
- *pRetVal = m_pData->m_pVars[m_VarEntry].AddrKind();
-ErrExit:
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// GetAddressField1
-//-----------------------------------------------------------
-HRESULT
-SymReaderVar::GetAddressField1(
- ULONG32 *pRetVal // [out]
- )
-{
- HRESULT hr = S_OK;
-
- _ASSERTE(pRetVal);
- IfFalseGo( pRetVal, E_INVALIDARG );
-
- *pRetVal = m_pData->m_pVars[m_VarEntry].Addr1();
-
-ErrExit:
-
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetAddressField2
-//-----------------------------------------------------------
-HRESULT
-SymReaderVar::GetAddressField2(
- ULONG32 *pRetVal // [out]
- )
-{
- HRESULT hr = S_OK;
-
- _ASSERTE(pRetVal);
- IfFalseGo( pRetVal, E_INVALIDARG );
-
- *pRetVal = m_pData->m_pVars[m_VarEntry].Addr2();
-
-ErrExit:
-
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetAddressField3
-//-----------------------------------------------------------
-HRESULT
-SymReaderVar::GetAddressField3(
- ULONG32 *pRetVal // [out]
- )
-{
- HRESULT hr = S_OK;
-
- _ASSERTE(pRetVal);
- IfFalseGo( pRetVal, E_INVALIDARG );
-
- *pRetVal = m_pData->m_pVars[m_VarEntry].Addr3();
-
-ErrExit:
-
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetStartOffset
-//-----------------------------------------------------------
-HRESULT
-SymReaderVar::GetStartOffset(
- ULONG32 *pRetVal
- )
-{
- //
- // This symbol reader doesn't support variable sub-offsets.
- //
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// GetEndOffset
-//-----------------------------------------------------------
-HRESULT
-SymReaderVar::GetEndOffset(
- ULONG32 *pRetVal
- )
-{
- //
- // This symbol reader doesn't support variable sub-offsets.
- //
- return E_NOTIMPL;
-}
-
-
-/* ------------------------------------------------------------------------- *
- * SymReaderNamespace class
- * ------------------------------------------------------------------------- */
-
-//-----------------------------------------------------------
-// QueryInterface
-//-----------------------------------------------------------
-HRESULT
-SymReaderNamespace::QueryInterface(
- REFIID riid,
- void** ppInterface
- )
-{
- if (ppInterface == NULL)
- return E_INVALIDARG;
-
- if (riid == IID_ISymUnmanagedNamespace)
- *ppInterface = (ISymUnmanagedNamespace*)this;
- else if (riid == IID_IUnknown)
- *ppInterface = (IUnknown*)(ISymUnmanagedNamespace*)this;
- else
- {
- *ppInterface = NULL;
- return E_NOINTERFACE;
- }
-
- AddRef();
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// GetName
-//-----------------------------------------------------------
-HRESULT
-SymReaderNamespace::GetName(
- ULONG32 cchName, // [optional] Chars available in szName
- ULONG32 *pcchName, // [optional] Total size needed to return the name
- __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[] // [optional] Location to store the name into.
- )
-{
- HRESULT hr = S_OK;
- _ASSERTE(pcchName || (szName && cchName));
- IfFalseGo( (pcchName || (szName && cchName)), E_INVALIDARG );
-
- if (pcchName)
- {
- *pcchName = (ULONG32) MultiByteToWideChar(CP_UTF8,
- 0,
- (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pUsings[m_NamespaceEntry].Name()]),
- -1,
- 0,
- NULL);
- }
- if (szName)
- {
- MultiByteToWideChar(CP_UTF8,
- 0,
- (LPCSTR)&(m_pData->m_pStringsBytes[m_pData->m_pUsings[m_NamespaceEntry].Name()]),
- -1,
- szName,
- cchName);
- }
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// GetNamespaces
-//-----------------------------------------------------------
-HRESULT
-SymReaderNamespace::GetNamespaces(
- ULONG32 cNamespaces,
- ULONG32 *pcNamespaces,
- ISymUnmanagedNamespace* namespaces[]
- )
-{
- // This symbol store doesn't support namespaces.
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// GetVariables
-//-----------------------------------------------------------
-HRESULT
-SymReaderNamespace::GetVariables(
- ULONG32 cVariables,
- ULONG32 *pcVariables,
- ISymUnmanagedVariable *pVars[])
-{
- // This symbol store doesn't support namespaces.
- _ASSERTE(!"NYI");
- return E_NOTIMPL;
-}
-
-
-/* ------------------------------------------------------------------------- *
- * SequencePoint struct functions
- * ------------------------------------------------------------------------- */
-
-//-----------------------------------------------------------
-// IsWithin - Is the point given within this sequence point
-//-----------------------------------------------------------
-bool SequencePoint::IsWithin(
- ULONG32 line,
- ULONG32 column)
-{
- // If the sequence point starts on the same line
- // Check the start column (if present)
- if (StartLine() == line)
- {
- if (0 < column && StartColumn() > column)
- {
- return false;
- }
- }
-
- // If the sequence point ends on the same line
- // Check the end column
- if (EndLine() == line)
- {
- if (EndColumn() < column)
- {
- return false;
- }
- }
-
- // Make sure the line is within this sequence point
- if (!((StartLine() <= line) && (EndLine() >= line)))
- {
- return false;
- }
-
- // Yep it's within this sequence point
- return true;
-
-}
-
-//-----------------------------------------------------------
-// IsWithinLineOnly - Is the given line within this sequence point
-//-----------------------------------------------------------
-bool SequencePoint::IsWithinLineOnly(
- ULONG32 line)
-{
- return ((StartLine() <= line) && (line <= EndLine()));
-}
-
-//-----------------------------------------------------------
-// IsGreaterThan - Is the sequence point greater than the position
-//-----------------------------------------------------------
-bool SequencePoint::IsGreaterThan(
- ULONG32 line,
- ULONG32 column)
-{
- return (StartLine() > line) ||
- (StartLine() == line && StartColumn() > column);
-}
-
-//-----------------------------------------------------------
-// IsLessThan - Is the sequence point less than the position
-//-----------------------------------------------------------
-bool SequencePoint::IsLessThan
-(
- ULONG32 line,
- ULONG32 column
-)
-{
- return (StartLine() < line) ||
- (StartLine() == line && StartColumn() < column);
-}
-
-//-----------------------------------------------------------
-// IsUserLine - Is the sequence part of user code
-//-----------------------------------------------------------
-bool SequencePoint::IsUserLine()
-{
- return StartLine() != CODE_WITH_NO_SOURCE;
-}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ===========================================================================
-// File: SymRead.h
-//
-
-// ===========================================================================
-
-#ifndef SYMREAD_H_
-#define SYMREAD_H_
-
-class SymScope;
-class SymReaderVar;
-class SymDocument;
-
-// -------------------------------------------------------------------------
-// SymReader class
-// -------------------------------------------------------------------------
-
-class SymReader : public ISymUnmanagedReader
-{
-// ctor/dtor
-public:
- SymReader()
- {
- m_refCount = 0;
- m_pPDBInfo = NULL;
- m_pDocs = NULL;
- m_pImporter = NULL;
- m_fInitialized = false;
- m_fInitializeFromStream = false;
- memset(&m_DataPointers, 0, sizeof(PDBDataPointers));
- m_szPath[0] = '\0';
- }
- virtual ~SymReader();
- static HRESULT NewSymReader( REFCLSID clsid, void** ppObj );
-
-public:
- //-----------------------------------------------------------
- // IUnknown support
- //-----------------------------------------------------------
- ULONG STDMETHODCALLTYPE AddRef()
- {
- return (InterlockedIncrement((LONG *) &m_refCount));
- }
-
- ULONG STDMETHODCALLTYPE Release()
- {
- LONG refCount = InterlockedDecrement((LONG *) &m_refCount);
- if (refCount == 0)
- DELETE(this);
-
- return (refCount);
- }
- STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
-
-// ISymUnmanagedReader
-public:
- STDMETHOD(GetDocument)(__in LPWSTR url,
- GUID language,
- GUID languageVendor,
- GUID documentType,
- ISymUnmanagedDocument **pRetVal);
- STDMETHOD(GetDocuments)(ULONG32 cDocs,
- ULONG32 *pcDocs,
- ISymUnmanagedDocument *pDocs[]);
- STDMETHOD(GetUserEntryPoint)(mdMethodDef *pRetVal);
- STDMETHOD(GetMethod)(mdMethodDef method,
- ISymUnmanagedMethod **pRetVal);
- STDMETHOD(GetMethodByVersion)(mdMethodDef method,
- int version,
- ISymUnmanagedMethod **pRetVal);
- STDMETHOD(GetVariables)(mdToken parent,
- ULONG32 cVars,
- ULONG32 *pcVars,
- ISymUnmanagedVariable *pVars[]);
- STDMETHOD(GetGlobalVariables)(ULONG32 cVars,
- ULONG32 *pcVars,
- ISymUnmanagedVariable *pVars[]);
- STDMETHOD(GetMethodFromDocumentPosition)(ISymUnmanagedDocument *document,
- ULONG32 line,
- ULONG32 column,
- ISymUnmanagedMethod **pRetVal);
- STDMETHOD(GetSymAttribute)(mdToken parent,
- __in LPWSTR name,
- ULONG32 cBuffer,
- ULONG32 *pcBuffer,
- __out_bcount_part_opt(cBuffer, *pcBuffer) BYTE buffer[]);
- STDMETHOD(GetNamespaces)(ULONG32 cNameSpaces,
- ULONG32 *pcNameSpaces,
- ISymUnmanagedNamespace *namespaces[]);
- STDMETHOD(Initialize)(IUnknown *importer,
- const WCHAR* szFileName,
- const WCHAR* szsearchPath,
- IStream *pIStream);
- STDMETHOD(UpdateSymbolStore)(const WCHAR *filename,
- IStream *pIStream);
-
- STDMETHOD(ReplaceSymbolStore)(const WCHAR *filename,
- IStream *pIStream);
-
- STDMETHOD(GetSymbolStoreFileName)(ULONG32 cchName,
- ULONG32 *pcchName,
- __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
-
- STDMETHOD(GetMethodsFromDocumentPosition)(ISymUnmanagedDocument* document,
- ULONG32 line,
- ULONG32 column,
- ULONG32 cMethod,
- ULONG32* pcMethod,
- ISymUnmanagedMethod* pRetVal[]);
-
- STDMETHOD(GetDocumentVersion)(ISymUnmanagedDocument *pDoc, int* version, BOOL* pbCurrent);
-
- STDMETHOD(GetMethodVersion)(ISymUnmanagedMethod* pMethod, int* version);
-
- //-----------------------------------------------------------
- // Methods not exposed via a COM interface.
- //-----------------------------------------------------------
-public:
- HRESULT GetDocument(UINT32 DocumentEntry, SymDocument **ppDocument);
-private:
- void Cleanup();
-
- HRESULT InitializeFromFile(const WCHAR* szFileName,
- const WCHAR* szsearchPath);
-
- HRESULT InitializeFromStream(IStream * pIStream);
-
- HRESULT VerifyPEDebugInfo(const WCHAR* szFileName);
-
- HRESULT ValidateData();
-
- HRESULT ValidateBytes(UINT32 bytesIndex, UINT32 bytesLength);
-
-private:
- // Data Members
- UINT32 m_refCount;
-
- // Symbol File Name
- WCHAR m_szPath[ _MAX_PATH ];
- WCHAR m_szStoredSymbolName[ _MAX_PATH ];
-
- PDBInfo *m_pPDBInfo;
- SymDocument **m_pDocs;
- IUnknown *m_pImporter;
- PDBDataPointers m_DataPointers;
-
- // Are we initialized yet?
- bool m_fInitialized;
-
- // Did we initialize from stream
- bool m_fInitializeFromStream;
- };
-
-/* ------------------------------------------------------------------------- *
- * SymDocument class
- * ------------------------------------------------------------------------- */
-
-class SymDocument : public ISymUnmanagedDocument
-{
-// ctor/dtor
-public:
- SymDocument(SymReader *pReader,
- PDBDataPointers *pData,
- UINT32 CountOfMethods,
- UINT32 DocumentEntry)
- {
- m_refCount = 0;
- m_pData = pData;
- m_DocumentEntry = DocumentEntry;
- m_CountOfMethods = CountOfMethods;
- m_pReader = pReader;
- pReader->AddRef();
-
- }
- virtual ~SymDocument()
- {
- RELEASE(m_pReader);
- }
-
-// IUnknown
-public:
- //-----------------------------------------------------------
- // IUnknown support
- //-----------------------------------------------------------
- ULONG STDMETHODCALLTYPE AddRef()
- {
- return (InterlockedIncrement((LONG *) &m_refCount));
- }
-
- ULONG STDMETHODCALLTYPE Release()
- {
- LONG refCount = InterlockedDecrement((LONG *) &m_refCount);
- if (refCount == 0)
- DELETE(this);
-
- return (refCount);
- }
- STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
-
-// ISymUnmanagedDocument
-public:
- STDMETHOD(GetURL)(ULONG32 cchUrl,
- ULONG32 *pcchUrl,
- __out_ecount_part_opt(cchUrl, *pcchUrl) WCHAR szUrl[]);
- STDMETHOD(GetDocumentType)(GUID *pRetVal);
- STDMETHOD(GetLanguage)(GUID *pRetVal);
- STDMETHOD(GetLanguageVendor)(GUID *pRetVal);
- STDMETHOD(GetCheckSumAlgorithmId)(GUID *pRetVal);
- STDMETHOD(GetCheckSum)(ULONG32 cData,
- ULONG32 *pcData,
- BYTE data[]);
- STDMETHOD(FindClosestLine)(ULONG32 line, ULONG32 *pRetVal);
- STDMETHOD(HasEmbeddedSource)(BOOL *pRetVal);
- STDMETHOD(GetSourceLength)(ULONG32 *pRetVal);
- STDMETHOD(GetSourceRange)(ULONG32 startLine,
- ULONG32 startColumn,
- ULONG32 endLine,
- ULONG32 endColumn,
- ULONG32 cSourceBytes,
- ULONG32 *pcSourceBytes,
- BYTE source[]);
-
- //-----------------------------------------------------------
- // Methods not exposed via a COM interface.
- //-----------------------------------------------------------
- UINT32 GetDocumentEntry()
- {
- return m_DocumentEntry;
- }
-
-// Data members
-private:
- UINT32 m_refCount;
-
- SymReader *m_pReader;
-
- // Data Pointer
- PDBDataPointers *m_pData;
-
- // Entry into the document array
- UINT32 m_DocumentEntry;
-
- // Total number of methods in the ildb
- UINT32 m_CountOfMethods;
-
-};
-
-/* ------------------------------------------------------------------------- *
- * SymMethod class
- * ------------------------------------------------------------------------- */
-
-class SymMethod : public ISymUnmanagedMethod
-{
-// ctor/dtor
-public:
- SymMethod(SymReader *pSymReader, PDBDataPointers *pData, UINT32 MethodEntry)
- {
- m_pData = pData;
- m_MethodEntry = MethodEntry;
- m_refCount = 0;
- m_pReader = pSymReader;
- pSymReader->AddRef();
- }
-
- virtual ~SymMethod()
- {
- RELEASE(m_pReader);
- };
-
-public:
-
- //-----------------------------------------------------------
- // IUnknown support
- //-----------------------------------------------------------
- ULONG STDMETHODCALLTYPE AddRef()
- {
- return (InterlockedIncrement((LONG *) &m_refCount));
- }
-
- ULONG STDMETHODCALLTYPE Release()
- {
- LONG refCount = InterlockedDecrement((LONG *) &m_refCount);
- if (refCount == 0)
- DELETE(this);
-
- return (refCount);
- }
- STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
-
-// ISymUnmanagedMethod
-public:
- STDMETHOD(GetToken)(mdMethodDef *pRetVal);
- STDMETHOD(GetSequencePointCount)(ULONG32 *pRetVal);
-
- STDMETHOD(GetRootScope)(ISymUnmanagedScope **pRetVal);
- STDMETHOD(GetScopeFromOffset)(ULONG32 offset,
- ISymUnmanagedScope **pRetVal);
- STDMETHOD(GetOffset)(ISymUnmanagedDocument *document,
- ULONG32 line,
- ULONG32 column,
- ULONG32 *pRetVal);
- STDMETHOD(GetRanges)(ISymUnmanagedDocument *document,
- ULONG32 line,
- ULONG32 column,
- ULONG32 cRanges,
- ULONG32 *pcRanges,
- ULONG32 ranges[]);
- STDMETHOD(GetParameters)(ULONG32 cParams,
- ULONG32 *pcParams,
- ISymUnmanagedVariable *params[]);
- STDMETHOD(GetNamespace)(ISymUnmanagedNamespace **pRetVal);
- STDMETHOD(GetSourceStartEnd)(ISymUnmanagedDocument *docs[2],
- ULONG32 lines[2],
- ULONG32 columns[2],
- BOOL *pRetVal);
- STDMETHOD(GetSequencePoints)(ULONG32 cpoints,
- ULONG32* pcpoints,
- ULONG32 offsets[],
- ISymUnmanagedDocument *documents[],
- ULONG32 lines[],
- ULONG32 columns[],
- ULONG32 endlines[],
- ULONG32 endcolumns[]);
-
-// Data members
-private:
- // AddRef/Release support
- UINT32 m_refCount;
-
- // Data Pointer
- PDBDataPointers *m_pData;
-
- // SymReader
- SymReader *m_pReader;
-
- // Entry into the SymMethodInfo array
- UINT32 m_MethodEntry;
-
-};
-
-/* ------------------------------------------------------------------------- *
- * SymScope class
- * ------------------------------------------------------------------------- */
-
-class SymScope : public ISymUnmanagedScope
-{
-// ctor/dtor
-public:
- SymScope(
- ISymUnmanagedMethod *pSymMethod,
- PDBDataPointers *pData,
- UINT32 MethodEntry,
- UINT32 ScopeEntry)
- {
- m_pSymMethod = pSymMethod;
- m_pSymMethod->AddRef();
- m_pData = pData;
- m_MethodEntry = MethodEntry;
- m_ScopeEntry = ScopeEntry;
- m_refCount = 0;
- }
- virtual ~SymScope()
- {
- RELEASE(m_pSymMethod);
- }
-
-public:
- //-----------------------------------------------------------
- // IUnknown support
- //-----------------------------------------------------------
- ULONG STDMETHODCALLTYPE AddRef()
- {
- return (InterlockedIncrement((LONG *) &m_refCount));
- }
-
- ULONG STDMETHODCALLTYPE Release()
- {
- LONG refCount = InterlockedDecrement((LONG *) &m_refCount);
- if (refCount == 0)
- DELETE(this);
-
- return (refCount);
- }
- STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
-
-// ISymUnmanagedScope
-public:
- STDMETHOD(GetMethod)(ISymUnmanagedMethod **pRetVal);
- STDMETHOD(GetParent)(ISymUnmanagedScope **pRetVal);
- STDMETHOD(GetChildren)(ULONG32 cChildren,
- ULONG32 *pcChildren,
- ISymUnmanagedScope *children[]);
- STDMETHOD(GetStartOffset)(ULONG32 *pRetVal);
- STDMETHOD(GetEndOffset)(ULONG32 *pRetVal);
- STDMETHOD(GetLocalCount)(ULONG32 *pRetVal);
- STDMETHOD(GetLocals)(ULONG32 cLocals,
- ULONG32 *pcLocals,
- ISymUnmanagedVariable *locals[]);
- STDMETHOD(GetNamespaces)(ULONG32 cNameSpaces,
- ULONG32 *pcNameSpaces,
- ISymUnmanagedNamespace *namespaces[]);
-
-// Data members
-private:
-
- UINT32 m_refCount; // Add/Ref Release
-
- ISymUnmanagedMethod *m_pSymMethod;
-
- // Data Pointer
- PDBDataPointers *m_pData;
- // Entry into the SymMethodInfo array
- UINT32 m_MethodEntry;
- // Entry into the scope array
- UINT32 m_ScopeEntry;
-};
-
-/* ------------------------------------------------------------------------- *
- * SymReaderVar class
- * ------------------------------------------------------------------------- */
-
-class SymReaderVar : public ISymUnmanagedVariable
-{
-// ctor/dtor
-public:
- SymReaderVar(SymScope *pScope, PDBDataPointers *pData, UINT32 VarEntry)
- {
- m_pData = pData;
- m_VarEntry = VarEntry;
- m_refCount = 0;
- m_pScope = pScope;
- pScope->AddRef();
- }
- virtual ~SymReaderVar()
- {
- RELEASE(m_pScope);
- }
-
-public:
- //-----------------------------------------------------------
- // IUnknown support
- //-----------------------------------------------------------
- ULONG STDMETHODCALLTYPE AddRef()
- {
- return (InterlockedIncrement((LONG *) &m_refCount));
- }
-
- ULONG STDMETHODCALLTYPE Release()
- {
- LONG refCount = InterlockedDecrement((LONG *) &m_refCount);
- if (refCount == 0)
- DELETE(this);
-
- return (refCount);
- }
- STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
-
-// ISymUnmanagedReaderVar
-public:
- STDMETHOD(GetName)(ULONG32 cchName,
- ULONG32 *pcchName,
- __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
- STDMETHOD(GetAttributes)(ULONG32 *pRetVal);
- STDMETHOD(GetSignature)(ULONG32 cSig,
- ULONG32 *pcSig,
- BYTE sig[]);
- STDMETHOD(GetAddressKind)(ULONG32 *pRetVal);
- STDMETHOD(GetAddressField1)(ULONG32 *pRetVal);
- STDMETHOD(GetAddressField2)(ULONG32 *pRetVal);
- STDMETHOD(GetAddressField3)(ULONG32 *pRetVal);
- STDMETHOD(GetStartOffset)(ULONG32 *pRetVal);
- STDMETHOD(GetEndOffset)(ULONG32 *pRetVal);
-
-
-// Data members
-private:
- UINT32 m_refCount; // Add/Ref Release
-
- // Data Pointer
- PDBDataPointers *m_pData;
-
- // Scope of the variable
- SymScope *m_pScope;
-
- // Entry into the SymMethodInfo array
- UINT32 m_VarEntry;
-};
-
-class SymReaderNamespace : public ISymUnmanagedNamespace
-{
-
-public:
- SymReaderNamespace(SymScope *pScope, PDBDataPointers *pData, UINT32 NamespaceEntry)
- {
- m_pData = pData;
- m_NamespaceEntry = NamespaceEntry;
- m_refCount = 0;
- m_pScope = pScope;
- pScope->AddRef();
- }
- virtual ~SymReaderNamespace()
- {
- }
-
-public:
- //-----------------------------------------------------------
- // IUnknown support
- //-----------------------------------------------------------
- ULONG STDMETHODCALLTYPE AddRef()
- {
- return (InterlockedIncrement((LONG *) &m_refCount));
- }
-
- ULONG STDMETHODCALLTYPE Release()
- {
- LONG refCount = InterlockedDecrement((LONG *) &m_refCount);
- if (refCount == 0)
- DELETE(this);
-
- return (refCount);
- }
- STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
-
-public:
- //-----------------------------------------------------------
- // ISymUnmanagedNamespace support
- //-----------------------------------------------------------
- STDMETHOD(GetName)(ULONG32 cchName,
- ULONG32 *pcchName,
- __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
- STDMETHOD(GetNamespaces)(ULONG32 cNamespaces,
- ULONG32 *pcNamespaces,
- ISymUnmanagedNamespace* namespaces[]);
- STDMETHOD(GetVariables)(ULONG32 cchName,
- ULONG32 *pcchName,
- ISymUnmanagedVariable *pVars[]);
-
-private:
- UINT32 m_refCount; // Add/Ref Release
-
- // Owning scope
- SymScope *m_pScope;
-
- // Data Pointer
- PDBDataPointers *m_pData;
- // Entry into the NameSpace array
- UINT32 m_NamespaceEntry;
-
-};
-
-#endif
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ===========================================================================
-// File: symwrite.cpp
-//
-
-//
-// Note: The various SymWriter_* and SymDocumentWriter_* are entry points
-// called via PInvoke from the managed symbol wrapper used by managed languages
-// to emit debug information (such as jscript)
-// ===========================================================================
-
-#include "pch.h"
-#include "symwrite.h"
-
-
-// -------------------------------------------------------------------------
-// SymWriter class
-// -------------------------------------------------------------------------
-
-// This is a COM object which is called both directly from the runtime, and from managed code
-// via PInvoke (CoreSymWrapper) and IJW (ISymWrapper). This is an unusual pattern, and it's not
-// clear exactly how best to address it. Eg., should we be using BEGIN_EXTERNAL_ENTRYPOINT
-// macros? Conceptually this is just a drop-in replacement for diasymreader.dll, and could
-// live in a different DLL instead of being statically linked into the runtime. But since it
-// relies on utilcode (and actually gets the runtime utilcode, not the nohost utilcode like
-// other external tools), it does have some properties of runtime code.
-//
-
-//-----------------------------------------------------------
-// NewSymWriter
-// Static function used to create a new instance of SymWriter
-//-----------------------------------------------------------
-HRESULT SymWriter::NewSymWriter(const GUID& id, void **object)
-{
- if (id != IID_ISymUnmanagedWriter)
- return (E_UNEXPECTED);
-
- SymWriter *writer = NEW(SymWriter());
-
- if (writer == NULL)
- return (E_OUTOFMEMORY);
-
- *object = (ISymUnmanagedWriter*)writer;
- writer->AddRef();
-
- return (S_OK);
-}
-
-//-----------------------------------------------------------
-// SymWriter Constuctor
-//-----------------------------------------------------------
-SymWriter::SymWriter() :
- m_refCount(0),
- m_openMethodToken(mdMethodDefNil),
- m_LargestMethodToken(mdMethodDefNil),
- m_pmethod(NULL),
- m_currentScope(k_noScope),
- m_hFile(NULL),
- m_pIStream(NULL),
- m_pStringPool(NULL),
- m_closed( false ),
- m_sortLines (false),
- m_sortMethodEntries(false)
-{
- memset(m_szPath, 0, sizeof(m_szPath));
- memset(&ModuleLevelInfo, 0, sizeof(PDBInfo));
-}
-
-//-----------------------------------------------------------
-// SymWriter QI
-//-----------------------------------------------------------
-COM_METHOD SymWriter::QueryInterface(REFIID riid, void **ppInterface)
-{
- if (ppInterface == NULL)
- return E_INVALIDARG;
-
- if (riid == IID_ISymUnmanagedWriter )
- *ppInterface = (ISymUnmanagedWriter*)this;
- else if (riid == IID_ISymUnmanagedWriter2 )
- *ppInterface = (ISymUnmanagedWriter2*)this;
- else if (riid == IID_ISymUnmanagedWriter3 )
- *ppInterface = (ISymUnmanagedWriter3*)this;
- else if (riid == IID_IUnknown)
- *ppInterface = (IUnknown*)(ISymUnmanagedWriter*)this;
- else
- {
- *ppInterface = NULL;
- return E_NOINTERFACE;
- }
-
- AddRef();
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// SymWriter Destructor
-//-----------------------------------------------------------
-SymWriter::~SymWriter()
-{
- // Note that this must be thread-safe - it may be invoked on the finalizer thread
- // But since this dtor can only be invoked when all references have been released,
- // no other threads can be manipulating the writer.
- // Ideally we'd probably just add locking to all methods, but this is low-priority
- // because diasymreader.dll isn't thread-safe and so we need to ensure the CLR's use
- // of these interfaces are properly syncrhonized.
- if ( !m_closed )
- Close();
- RELEASE(m_pIStream);
- DELETE(m_pStringPool);
-}
-
-//-----------------------------------------------------------
-// SymWriter Initialize the SymWriter
-//-----------------------------------------------------------
-COM_METHOD SymWriter::Initialize
-(
- IUnknown *emitter, // Emitter (IMetaData Emit/Import) - unused by ILDB
- const WCHAR *szFilename, // FileName of the exe we're creating
- IStream *pIStream, // Stream to store into
- BOOL fFullBuild // Is this a full build or an incremental build
-)
-{
- HRESULT hr = S_OK;
-
- // Incremental compile not implemented
- _ASSERTE(fFullBuild);
-
- if (emitter == NULL)
- return E_INVALIDARG;
-
- if (pIStream != NULL)
- {
- m_pIStream = pIStream;
- pIStream->AddRef();
- }
- else
- {
- if (szFilename == NULL)
- {
- IfFailRet(E_INVALIDARG);
- }
- }
-
- m_pStringPool = NEW(StgStringPool());
- IfFailRet(m_pStringPool->InitNew());
-
- if (szFilename != NULL)
- {
- WCHAR fullpath[_MAX_PATH];
- WCHAR drive[_MAX_DRIVE];
- WCHAR dir[_MAX_DIR];
- WCHAR fname[_MAX_FNAME];
- _wsplitpath_s( szFilename, drive, COUNTOF(drive), dir, COUNTOF(dir), fname, COUNTOF(fname), NULL, 0 );
- _wmakepath_s( fullpath, COUNTOF(fullpath), drive, dir, fname, W("ildb") );
- if (wcsncpy_s( m_szPath, COUNTOF(m_szPath), fullpath, _TRUNCATE) == STRUNCATE)
- return HrFromWin32(ERROR_INSUFFICIENT_BUFFER);
- }
-
- // Note that we don't need the emitter - ILDB is agnostic to the module metadata.
-
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter Initialize2 the SymWriter
-// Delegate to Initialize then use the szFullPathName param
-//-----------------------------------------------------------
-COM_METHOD SymWriter::Initialize2
-(
- IUnknown *emitter, // Emitter (IMetaData Emit/Import)
- const WCHAR *szTempPath, // Location of the file
- IStream *pIStream, // Stream to store into
- BOOL fFullBuild, // Full build or not
- const WCHAR *szFullPathName // Final destination of the ildb
-)
-{
- HRESULT hr = S_OK;
- IfFailGo( Initialize( emitter, szTempPath, pIStream, fFullBuild ) );
- // We don't need the final location of the ildb
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter GetorCreateDocument
-// creates a new symbol document writer for a specified source
-// Arguments:
-// input: wcsUrl - The source file name
-// output: ppRetVal - The new document writer
-// Return Value: hr - S_OK if success, OOM otherwise
-//-----------------------------------------------------------
-HRESULT SymWriter::GetOrCreateDocument(
- const WCHAR *wcsUrl, // Document name
- const GUID *pLanguage, // What Language we're compiling
- const GUID *pLanguageVendor, // What vendor
- const GUID *pDocumentType, // Type
- ISymUnmanagedDocumentWriter **ppRetVal // [out] Created DocumentWriter
-)
-{
- ULONG UrlEntry;
- DWORD strLength = WszWideCharToMultiByte(CP_UTF8, 0, wcsUrl, -1, 0, 0, 0, 0);
- LPSTR multiByteURL = (LPSTR) new char [strLength];
- HRESULT hr = S_OK;
-
- if (multiByteURL == NULL)
- {
- return E_OUTOFMEMORY;
- }
-
- WszWideCharToMultiByte(CP_UTF8, 0, wcsUrl, -1, multiByteURL, strLength, 0, 0);
-
- if (m_pStringPool->FindString(multiByteURL, &UrlEntry) == S_FALSE) // no file of that name has been seen before
- {
- hr = CreateDocument(wcsUrl, pLanguage, pLanguageVendor, pDocumentType, ppRetVal);
- }
- else // we already have a writer for this file
- {
- UINT32 docInfo = 0;
-
- CRITSEC_COOKIE cs = ClrCreateCriticalSection(CrstLeafLock, CRST_DEFAULT);
-
- ClrEnterCriticalSection(cs);
-
- while ((docInfo < m_MethodInfo.m_documents.count()) && (m_MethodInfo.m_documents[docInfo].UrlEntry() != UrlEntry))
- {
- docInfo++;
- }
-
- if (docInfo == m_MethodInfo.m_documents.count()) // something went wrong and we didn't find the writer
- {
- hr = CreateDocument(wcsUrl, pLanguage, pLanguageVendor, pDocumentType, ppRetVal);
- }
- else
- {
- *ppRetVal = m_MethodInfo.m_documents[docInfo].DocumentWriter();
- (*ppRetVal)->AddRef();
- }
- ClrLeaveCriticalSection(cs);
- }
-
- delete [] multiByteURL;
- return hr;
-
-} // SymWriter::GetOrCreateDocument
-
-//-----------------------------------------------------------
-// SymWriter CreateDocument
-// creates a new symbol document writer for a specified source
-// Arguments:
-// input: wcsUrl - The source file name
-// output: ppRetVal - The new document writer
-// Return Value: hr - S_OK if success, OOM otherwise
-//-----------------------------------------------------------
-HRESULT SymWriter::CreateDocument(const WCHAR *wcsUrl, // Document name
- const GUID *pLanguage, // What Language we're compiling
- const GUID *pLanguageVendor, // What vendor
- const GUID *pDocumentType, // Type
- ISymUnmanagedDocumentWriter **ppRetVal // [out] Created DocumentWriter
-)
-
-{
- DocumentInfo* pDocument = NULL;
- SymDocumentWriter *sdw = NULL;
- UINT32 DocumentEntry;
- ULONG UrlEntry;
- HRESULT hr = NOERROR;
-
- DocumentEntry = m_MethodInfo.m_documents.count();
- IfNullGo(pDocument = m_MethodInfo.m_documents.next());
- memset(pDocument, 0, sizeof(DocumentInfo));
-
- // Create the new document writer.
- sdw = NEW(SymDocumentWriter(DocumentEntry, this));
- IfNullGo(sdw);
-
- pDocument->SetLanguage(*pLanguage);
- pDocument->SetLanguageVendor(*pLanguageVendor);
- pDocument->SetDocumentType(*pDocumentType);
- pDocument->SetDocumentWriter(sdw);
-
- // stack check needed to call back into utilcode
- hr = m_pStringPool->AddStringW(wcsUrl, (UINT32 *)&UrlEntry);
- IfFailGo(hr);
-
- pDocument->SetUrlEntry(UrlEntry);
-
- // Pass out the new ISymUnmanagedDocumentWriter.
- sdw->AddRef();
- *ppRetVal = (ISymUnmanagedDocumentWriter*)sdw;
- sdw = NULL;
-
-ErrExit:
- DELETE(sdw);
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter DefineDocument
-//-----------------------------------------------------------
-COM_METHOD SymWriter::DefineDocument(
- const WCHAR *wcsUrl, // Document name
- const GUID *pLanguage, // What Language we're compiling
- const GUID *pLanguageVendor, // What vendor
- const GUID *pDocumentType, // Type
- ISymUnmanagedDocumentWriter **ppRetVal // [out] Created DocumentWriter
-)
-{
- HRESULT hr = NOERROR;
-
- IfFalseGo(wcsUrl, E_INVALIDARG);
- IfFalseGo(pLanguage, E_INVALIDARG);
- IfFalseGo(pLanguageVendor, E_INVALIDARG);
- IfFalseGo(pDocumentType, E_INVALIDARG);
- IfFalseGo(ppRetVal, E_INVALIDARG);
-
- // Init out parameter
- *ppRetVal = NULL;
-
- hr = GetOrCreateDocument(wcsUrl, pLanguage, pLanguageVendor, pDocumentType, ppRetVal);
-ErrExit:
- return hr;
-}
-
-
-//-----------------------------------------------------------
-// SymWriter SetDocumentSrc
-//-----------------------------------------------------------
-HRESULT SymWriter::SetDocumentSrc(
- UINT32 DocumentEntry,
- DWORD SourceSize,
- BYTE* pSource
-)
-{
- DocumentInfo* pDocument = NULL;
- HRESULT hr = S_OK;
-
- IfFalseGo( SourceSize == 0 || pSource, E_INVALIDARG);
- IfFalseGo( DocumentEntry < m_MethodInfo.m_documents.count(), E_INVALIDARG);
-
- pDocument = &m_MethodInfo.m_documents[DocumentEntry];
-
- if (pSource)
- {
- UINT32 i;
- IfFalseGo( m_MethodInfo.m_bytes.grab(SourceSize, &i), E_OUTOFMEMORY);
- memcpy(&m_MethodInfo.m_bytes[i], pSource, SourceSize);
- pDocument->SetSourceEntry(i);
- pDocument->SetSourceSize(SourceSize);
- }
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter SetDocumentCheckSum
-//-----------------------------------------------------------
-HRESULT SymWriter::SetDocumentCheckSum(
- UINT32 DocumentEntry,
- GUID AlgorithmId,
- DWORD CheckSumSize,
- BYTE* pCheckSum
-)
-{
- DocumentInfo* pDocument = NULL;
- HRESULT hr = S_OK;
-
- IfFalseGo( CheckSumSize == 0 || pCheckSum, E_INVALIDARG);
- IfFalseGo( DocumentEntry < m_MethodInfo.m_documents.count(), E_INVALIDARG);
-
- pDocument = &m_MethodInfo.m_documents[DocumentEntry];
-
- if (pCheckSum)
- {
- UINT32 i;
- IfFalseGo( m_MethodInfo.m_bytes.grab(CheckSumSize, &i), E_OUTOFMEMORY);
- memcpy(&m_MethodInfo.m_bytes[i], pCheckSum, CheckSumSize);
- pDocument->SetCheckSumEntry(i);
- pDocument->SetCheckSymSize(CheckSumSize);
- }
-
- pDocument->SetAlgorithmId(AlgorithmId);
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter SetUserEntryPoint
-//-----------------------------------------------------------
-COM_METHOD SymWriter::SetUserEntryPoint(mdMethodDef entryMethod)
-{
- HRESULT hr = S_OK;
-
- // Make sure that an entry point hasn't already been set.
- if (ModuleLevelInfo.m_userEntryPoint == 0)
- ModuleLevelInfo.m_userEntryPoint = entryMethod;
-
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter OpenMethod
-// Get ready to get information about a new method
-//-----------------------------------------------------------
-COM_METHOD SymWriter::OpenMethod(mdMethodDef method)
-{
- HRESULT hr = S_OK;
-
- // We can only have one open method at a time.
- if (m_openMethodToken != mdMethodDefNil)
- return E_INVALIDARG;
-
- m_LargestMethodToken = max(method, m_LargestMethodToken);
-
- if (m_LargestMethodToken != method)
- {
- m_sortMethodEntries = true;
- // Check to see if we're trying to open a method we've already done
- unsigned i;
- for (i = 0; i < m_MethodInfo.m_methods.count(); i++)
- {
- if (m_MethodInfo.m_methods[i].MethodToken() == method)
- {
- return E_INVALIDARG;
- }
- }
- }
-
- // Remember the token for this method.
- m_openMethodToken = method;
-
- IfNullGo( m_pmethod = m_MethodInfo.m_methods.next() );
- m_pmethod->SetMethodToken(m_openMethodToken);
- m_pmethod->SetStartScopes(m_MethodInfo.m_scopes.count());
- m_pmethod->SetStartVars(m_MethodInfo.m_vars.count());
- m_pmethod->SetStartUsing(m_MethodInfo.m_usings.count());
- m_pmethod->SetStartConstant(m_MethodInfo.m_constants.count());
- m_pmethod->SetStartDocuments(m_MethodInfo.m_documents.count());
- m_pmethod->SetStartSequencePoints(m_MethodInfo.m_auxSequencePoints.count());
-
- // By default assume the lines are inserted in the correct order
- m_sortLines = false;
-
- // Initialize the maximum scope end offset for this method
- m_maxScopeEnd = 1;
-
- // Open the implicit root scope for the method
- _ASSERTE(m_currentScope == k_noScope);
-
- IfFailRet(OpenScope(0, NULL));
-
- _ASSERTE(m_currentScope != k_noScope);
-
-ErrExit:
- return hr;
-}
-
-COM_METHOD SymWriter::OpenMethod2(
- mdMethodDef method,
- ULONG32 isect,
- ULONG32 offset)
-{
- // This symbol writer doesn't support section offsets
- _ASSERTE(FALSE);
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// compareAuxLines
-// Used to sort SequencePoint
-//-----------------------------------------------------------
-int __cdecl SequencePoint::compareAuxLines(const void *elem1, const void *elem2 )
-{
- SequencePoint* p1 = (SequencePoint*)elem1;
- SequencePoint* p2 = (SequencePoint*)elem2;
- return p1->Offset() - p2->Offset();
-}
-
-//-----------------------------------------------------------
-// SymWriter CloseMethod
-// We're done with this function, write it out.
-//-----------------------------------------------------------
-COM_METHOD SymWriter::CloseMethod()
-{
- HRESULT hr = S_OK;
- UINT32 CountOfSequencePoints;
-
- // Must have an open method.
- if (m_openMethodToken == mdMethodDefNil)
- return E_UNEXPECTED;
-
- // All scopes up to the root must have been closed (and the root must not have been closed).
- _ASSERTE(m_currentScope != k_noScope);
- if (m_MethodInfo.m_scopes[m_currentScope].ParentScope() != k_noScope)
- return E_FAIL;
-
- // Close the implicit root scope using the largest end offset we've seen in this method, or 1 if none.
- IfFailRet(CloseScopeInternal(m_maxScopeEnd));
-
- m_pmethod->SetEndScopes(m_MethodInfo.m_scopes.count());
- m_pmethod->SetEndVars(m_MethodInfo.m_vars.count());
- m_pmethod->SetEndUsing(m_MethodInfo.m_usings.count());
- m_pmethod->SetEndConstant(m_MethodInfo.m_constants.count());
- m_pmethod->SetEndDocuments(m_MethodInfo.m_documents.count());
- m_pmethod->SetEndSequencePoints(m_MethodInfo.m_auxSequencePoints.count());
-
- CountOfSequencePoints = m_pmethod->EndSequencePoints() - m_pmethod->StartSequencePoints();
- // Write any sequence points.
- if (CountOfSequencePoints > 0 ) {
- // sort the sequence points
- if ( m_sortLines )
- {
- qsort(&m_MethodInfo.m_auxSequencePoints[m_pmethod->StartSequencePoints()],
- CountOfSequencePoints,
- sizeof( SequencePoint ),
- SequencePoint::compareAuxLines );
- }
- }
-
- // All done with this method.
- m_openMethodToken = mdMethodDefNil;
-
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter DefineSequencePoints
-// Define the sequence points for this function
-//-----------------------------------------------------------
-COM_METHOD SymWriter::DefineSequencePoints(
- ISymUnmanagedDocumentWriter *document, //
- ULONG32 spCount, // Count of sequence points
- ULONG32 offsets[], // Offsets
- ULONG32 lines[], // Beginning Lines
- ULONG32 columns[], // [optional] Columns
- ULONG32 endLines[], // [optional] End Lines
- ULONG32 endColumns[] // [optional] End Columns
-)
-{
- HRESULT hr = S_OK;
- DWORD docnum;
-
- // We must have a document, offsets, and lines.
- IfFalseGo(document && offsets && lines, E_INVALIDARG);
- // Must have some sequence points
- IfFalseGo(spCount != 0, E_INVALIDARG);
- // Must have an open method.
- IfFalseGo(m_openMethodToken != mdMethodDefNil, E_INVALIDARG);
-
- // Remember that we've loaded the sequence points and
- // which document they were for.
- docnum = (DWORD)((SymDocumentWriter *)document)->GetDocumentEntry();;
-
- // if sets of lines have been inserted out-of-order, remember to sort when emitting
- if ( m_MethodInfo.m_auxSequencePoints.count() > 0 && m_MethodInfo.m_auxSequencePoints[ m_MethodInfo.m_auxSequencePoints.count()-1 ].Offset() > offsets[0] )
- m_sortLines = true;
-
- // Copy the incomming arrays into the internal format.
-
- for ( UINT32 i = 0; i < spCount; i++)
- {
- SequencePoint * paux;
- IfNullGo(paux = m_MethodInfo.m_auxSequencePoints.next());
- paux->SetOffset(offsets[i]);
- paux->SetStartLine(lines[i]);
- paux->SetStartColumn(columns ? columns[i] : 0);
- // If no endLines specified, assume same as start
- paux->SetEndLine(endLines ? endLines[i] : lines[i]);
- paux->SetEndColumn(endColumns ? endColumns[i]: 0);
- paux->SetDocument(docnum);
- }
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter OpenScope
-// Open a new scope for this function
-//-----------------------------------------------------------
-COM_METHOD SymWriter::OpenScope(ULONG32 startOffset, ULONG32 *scopeID)
-{
- HRESULT hr = S_OK;
-
- // Make sure the startOffset is within the current scope.
- if ((m_currentScope != k_noScope) &&
- (unsigned int)startOffset < m_MethodInfo.m_scopes[m_currentScope].StartOffset())
- return E_INVALIDARG;
-
- // Fill in the new scope.
- UINT32 newScope = m_MethodInfo.m_scopes.count();
-
- // Make sure that adding 1 below won't overflow (although "next" should fail much
- // sooner if we were anywhere near close enough).
- if (newScope >= UINT_MAX)
- return E_UNEXPECTED;
-
- SymLexicalScope *sc;
- IfNullGo( sc = m_MethodInfo.m_scopes.next());
- sc->SetParentScope(m_currentScope); // parent is the current scope.
- sc->SetStartOffset(startOffset);
- sc->SetHasChildren(FALSE);
- sc->SetHasVars(FALSE);
- sc->SetEndOffset(0);
-
- // The current scope has a child now.
- if (m_currentScope != k_noScope)
- m_MethodInfo.m_scopes[m_currentScope].SetHasChildren(TRUE);
-
- // The new scope is now the current scope.
- m_currentScope = newScope;
- _ASSERTE(m_currentScope != k_noScope);
-
- // Pass out the "scope id", which is a _1_ based id for the scope.
- if (scopeID)
- *scopeID = m_currentScope + 1;
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter CloseScope
-//-----------------------------------------------------------
-COM_METHOD SymWriter::CloseScope(
- ULONG32 endOffset // Closing offset of scope
-)
-{
- // This API can only be used to close explicit user scopes.
- // The implicit root scope is only closed internally by CloseMethod.
- if ((m_currentScope == k_noScope) || (m_MethodInfo.m_scopes[m_currentScope].ParentScope() == k_noScope))
- return E_FAIL;
-
- HRESULT hr = CloseScopeInternal(endOffset);
-
- _ASSERTE(m_currentScope != k_noScope);
-
- return hr;
-}
-
-//-----------------------------------------------------------
-// CloseScopeInternal
-// Implementation for ISymUnmanagedWriter::CloseScope but can be called even to
-// close the implicit root scope.
-//-----------------------------------------------------------
-COM_METHOD SymWriter::CloseScopeInternal(
- ULONG32 endOffset // Closing offset of scope
-)
-{
- _ASSERTE(m_currentScope != k_noScope);
-
- // Capture the end offset
- m_MethodInfo.m_scopes[m_currentScope].SetEndOffset(endOffset);
-
- // The current scope is now the parent scope.
- m_currentScope = m_MethodInfo.m_scopes[m_currentScope].ParentScope();
-
- // Update the maximum scope end offset for this method
- if (endOffset > m_maxScopeEnd)
- m_maxScopeEnd = endOffset;
-
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// SymWriter SetScopeRange
-// Set the Start/End Offset for this scope
-//-----------------------------------------------------------
-COM_METHOD SymWriter::SetScopeRange(
- ULONG32 scopeID, // ID for the scope
- ULONG32 startOffset, // Start Offset
- ULONG32 endOffset // End Offset
-)
-{
- if (scopeID <= 0)
- return E_INVALIDARG;
-
- if (scopeID > m_MethodInfo.m_scopes.count() )
- return E_INVALIDARG;
-
- // Remember the new start and end offsets. Also remember that the
- // scopeID is _1_ based!!!
- SymLexicalScope *sc = &(m_MethodInfo.m_scopes[scopeID - 1]);
- sc->SetStartOffset(startOffset);
- sc->SetEndOffset(endOffset);
-
- // Update the maximum scope end offset for this method
- if (endOffset > m_maxScopeEnd)
- m_maxScopeEnd = endOffset;
-
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// SymWriter DefineLocalVariable
-//-----------------------------------------------------------
-COM_METHOD SymWriter::DefineLocalVariable(
- const WCHAR *name, // Name of the variable
- ULONG32 attributes, // Attributes for the var
- ULONG32 cSig, // Signature for the variable
- BYTE signature[],
- ULONG32 addrKind,
- ULONG32 addr1, ULONG32 addr2, ULONG32 addr3,
- ULONG32 startOffset, ULONG32 endOffset)
-{
- HRESULT hr = S_OK;
- ULONG NameEntry;
-
- // We must have a current scope.
- if (m_currentScope == k_noScope)
- return E_FAIL;
-
- // We must have a name and a signature.
- if (!name || !signature)
- return E_INVALIDARG;
-
- if (cSig == 0)
- return E_INVALIDARG;
-
- // Make a new local variable and copy the data.
- SymVariable *var;
- IfNullGo( var = m_MethodInfo.m_vars.next());
- var->SetIsParam(FALSE);
- var->SetAttributes(attributes);
- var->SetAddrKind(addrKind);
- var->SetIsHidden(attributes & VAR_IS_COMP_GEN);
- var->SetAddr1(addr1);
- var->SetAddr2(addr2);
- var->SetAddr3(addr3);
-
-
- // Length of the sig?
- ULONG32 sigLen;
- sigLen = cSig;
-
- // Copy the name.
- hr = m_pStringPool->AddStringW(name, (UINT32 *)&NameEntry);
- IfFailGo(hr);
- var->SetName(NameEntry);
-
- // Copy the signature
- // Note that we give this back exactly as-is, but callers typically remove any calling
- // convention prefix.
- UINT32 i;
- IfFalseGo(m_MethodInfo.m_bytes.grab(sigLen, &i), E_OUTOFMEMORY);
- memcpy(&m_MethodInfo.m_bytes[i], signature, sigLen);
- var->SetSignature(i);
- var->SetSignatureSize(sigLen);
-
- // This var is in the current scope
- var->SetScope(m_currentScope);
- m_MethodInfo.m_scopes[m_currentScope].SetHasVars(TRUE);
-
- var->SetStartOffset(startOffset);
- var->SetEndOffset(endOffset);
-
-ErrExit:
- return hr;
-}
-
-COM_METHOD SymWriter::DefineLocalVariable2(
- const WCHAR *name,
- ULONG32 attributes,
- mdSignature sigToken,
- ULONG32 addrKind,
- ULONG32 addr1, ULONG32 addr2, ULONG32 addr3,
- ULONG32 startOffset, ULONG32 endOffset)
-{
- // This symbol writer doesn't support definiting signatures via tokens
- _ASSERTE(FALSE);
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// SymWriter DefineParameter
-//-----------------------------------------------------------
-COM_METHOD SymWriter::DefineParameter(
- const WCHAR *name, // Param name
- ULONG32 attributes, // Attribute for the parameter
- ULONG32 sequence,
- ULONG32 addrKind,
- ULONG32 addr1, ULONG32 addr2, ULONG32 addr3)
-{
- HRESULT hr = S_OK;
- ULONG NameEntry;
-
- // We must have a method.
- if (m_openMethodToken == mdMethodDefNil)
- return E_INVALIDARG;
-
- // We must have a name.
- if (!name)
- return E_INVALIDARG;
-
- SymVariable *var;
- IfNullGo( var = m_MethodInfo.m_vars.next());
- var->SetIsParam(TRUE);
- var->SetAttributes(attributes);
- var->SetAddrKind(addrKind);
- var->SetIsHidden(attributes & VAR_IS_COMP_GEN);
- var->SetAddr1(addr1);
- var->SetAddr2(addr2);
- var->SetAddr3(addr3);
- var->SetSequence(sequence);
-
-
- // Copy the name.
- hr = m_pStringPool->AddStringW(name, (UINT32 *)&NameEntry);
- IfFailGo(hr);
- var->SetName(NameEntry);
-
- // This var is in the current scope
- if (m_currentScope != k_noScope)
- m_MethodInfo.m_scopes[m_currentScope].SetHasVars(TRUE);
-
- var->SetStartOffset(0);
- var->SetEndOffset(0);
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// verifyConstTypes
-// Verify that the type is a type we support
-//-----------------------------------------------------------
-static bool verifyConstTypes( DWORD vt )
-{
- switch ( vt ) {
- case VT_UI8:
- case VT_I8:
- case VT_I4:
- case VT_UI1: // value < LF_NUMERIC
- case VT_I2:
- case VT_R4:
- case VT_R8:
- case VT_BOOL: // value < LF_NUMERIC
- case VT_DATE:
- case VT_BSTR:
- case VT_I1:
- case VT_UI2:
- case VT_UI4:
- case VT_INT:
- case VT_UINT:
- case VT_DECIMAL:
- return true;
- }
- return false;
-}
-
-//-----------------------------------------------------------
-// SymWriter DefineConstant
-//-----------------------------------------------------------
-COM_METHOD SymWriter::DefineConstant(
- const WCHAR __RPC_FAR *name,
- VARIANT value,
- ULONG32 cSig,
- unsigned char __RPC_FAR signature[])
-{
- HRESULT hr = S_OK;
- ULONG ValueBstr = 0;
- ULONG Name;
-
- // currently we only support local constants
-
- // We must have a method.
- if (m_openMethodToken == mdMethodDefNil)
- return E_INVALIDARG;
-
- // We must have a name and signature.
- IfFalseGo(name, E_INVALIDARG);
- IfFalseGo(signature, E_INVALIDARG);
- IfFalseGo(cSig > 0, E_INVALIDARG);
-
- //
- // Support byref decimal values
- //
- if ( (V_VT(&value)) == ( VT_BYREF | VT_DECIMAL ) ) {
- if ( V_DECIMALREF(&value) == NULL )
- return E_INVALIDARG;
- V_DECIMAL(&value) = *V_DECIMALREF(&value);
- V_VT(&value) = VT_DECIMAL;
- }
-
- // we only support non-ref constants
- if ( ( V_VT(&value) & VT_BYREF ) != 0 )
- return E_INVALIDARG;
-
- if ( !verifyConstTypes( V_VT(&value) ) )
- return E_INVALIDARG;
-
- // If it's a BSTR, we need to persist the Bstr as an entry into
- // the stringpool
- if (V_VT(&value) == VT_BSTR)
- {
- // Copy the bstrValue.
- hr = m_pStringPool->AddStringW(V_BSTR(&value), (UINT32 *)&ValueBstr);
- IfFailGo(hr);
- V_BSTR(&value) = NULL;
- }
-
- SymConstant *con;
- IfNullGo( con = m_MethodInfo.m_constants.next());
- con->SetValue(value, ValueBstr);
-
-
- // Copy the name.
- hr = m_pStringPool->AddStringW(name, (UINT32 *)&Name);
- IfFailGo(hr);
- con->SetName(Name);
-
- // Copy the signature
- UINT32 i;
- IfFalseGo(m_MethodInfo.m_bytes.grab(cSig, &i), E_OUTOFMEMORY);
- memcpy(&m_MethodInfo.m_bytes[i], signature, cSig);
- con->SetSignature(i);
- con->SetSignatureSize(cSig);
-
- // This const is in the current scope
- con->SetParentScope(m_currentScope);
- m_MethodInfo.m_scopes[m_currentScope].SetHasVars(TRUE);
-
-ErrExit:
- return hr;
-}
-
-COM_METHOD SymWriter::DefineConstant2(
- const WCHAR *name,
- VARIANT value,
- mdSignature sigToken)
-{
- // This symbol writer doesn't support definiting signatures via tokens
- _ASSERTE(FALSE);
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// SymWriter Abort
-//-----------------------------------------------------------
-COM_METHOD SymWriter::Abort(void)
-{
- m_closed = true;
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// SymWriter DefineField
-//-----------------------------------------------------------
-COM_METHOD SymWriter::DefineField(
- mdTypeDef parent,
- const WCHAR *name,
- ULONG32 attributes,
- ULONG32 csig,
- BYTE signature[],
- ULONG32 addrKind,
- ULONG32 addr1, ULONG32 addr2, ULONG32 addr3)
-{
- // This symbol store doesn't support extra random variable
- // definitions.
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// SymWriter DefineGlobalVariable
-//-----------------------------------------------------------
-COM_METHOD SymWriter::DefineGlobalVariable(
- const WCHAR *name,
- ULONG32 attributes,
- ULONG32 csig,
- BYTE signature[],
- ULONG32 addrKind,
- ULONG32 addr1, ULONG32 addr2, ULONG32 addr3)
-{
- // This symbol writer doesn't support global variables
- _ASSERTE(FALSE);
- return E_NOTIMPL;
-}
-
-COM_METHOD SymWriter::DefineGlobalVariable2(
- const WCHAR *name,
- ULONG32 attributes,
- mdSignature sigToken,
- ULONG32 addrKind,
- ULONG32 addr1, ULONG32 addr2, ULONG32 addr3)
-{
- // This symbol writer doesn't support global variables
- _ASSERTE(FALSE);
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// compareMethods
-// Used to sort method entries
-//-----------------------------------------------------------
-int __cdecl SymMethodInfo::compareMethods(const void *elem1, const void *elem2 )
-{
- SymMethodInfo* p1 = (SymMethodInfo*)elem1;
- SymMethodInfo* p2 = (SymMethodInfo*)elem2;
- return p1->MethodToken() - p2->MethodToken();
-}
-
-//-----------------------------------------------------------
-// SymWriter Close
-//-----------------------------------------------------------
-COM_METHOD SymWriter::Close()
-{
- HRESULT hr = Commit();
- m_closed = true;
- for (UINT32 docInfo = 0; docInfo < m_MethodInfo.m_documents.count(); docInfo++)
- {
- m_MethodInfo.m_documents[docInfo].SetDocumentWriter(NULL);
- }
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter Commit
-//-----------------------------------------------------------
-COM_METHOD SymWriter::Commit(void)
-{
- // Sort the entries if need be
- if (m_sortMethodEntries)
- {
- // First remap any tokens we need to
- if (m_MethodMap.count())
- {
- unsigned i;
- for (i = 0; i< m_MethodMap.count(); i++)
- {
- m_MethodInfo.m_methods[m_MethodMap[i].MethodEntry].SetMethodToken(m_MethodMap[i].m_MethodToken);
- }
- }
-
- // Now sort the array
- qsort(&m_MethodInfo.m_methods[0],
- m_MethodInfo.m_methods.count(),
- sizeof( SymMethodInfo ),
- SymMethodInfo::compareMethods );
- m_sortMethodEntries = false;
- }
- return WritePDB();
-}
-
-//-----------------------------------------------------------
-// SymWriter SetSymAttribute
-//-----------------------------------------------------------
-COM_METHOD SymWriter::SetSymAttribute(
- mdToken parent,
- const WCHAR *name,
- ULONG32 cData,
- BYTE data[])
-{
- // Setting attributes on the symbol isn't supported
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// SymWriter OpenNamespace
-//-----------------------------------------------------------
-COM_METHOD SymWriter::OpenNamespace(const WCHAR *name)
-{
- // This symbol store doesn't support namespaces.
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// SymWriter OpenNamespace
-//-----------------------------------------------------------
-COM_METHOD SymWriter::CloseNamespace()
-{
- // This symbol store doesn't support namespaces.
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// SymWriter UsingNamespace
-// Add a Namespace to the list of namespace for this method
-//-----------------------------------------------------------
-COM_METHOD SymWriter::UsingNamespace(const WCHAR *fullName)
-{
- HRESULT hr = S_OK;
- ULONG Name;
-
- // We must have a current scope.
- if (m_currentScope == k_noScope)
- return E_FAIL;
-
- // We must have a name.
- if (!fullName)
- return E_INVALIDARG;
-
-
- SymUsingNamespace *use;
- IfNullGo( use = m_MethodInfo.m_usings.next());
-
- // Copy the name.
- hr = m_pStringPool->AddStringW(fullName, (UINT32 *)&Name);
- IfFailGo(hr);
- use->SetName(Name);
-
- use->SetParentScope(m_currentScope);
-
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter SetMethodSourceRange
-//-----------------------------------------------------------
-COM_METHOD SymWriter::SetMethodSourceRange(
- ISymUnmanagedDocumentWriter *startDoc,
- ULONG32 startLine,
- ULONG32 startColumn,
- ISymUnmanagedDocumentWriter *endDoc,
- ULONG32 endLine,
- ULONG32 endColumn)
-{
- // This symbol store doesn't support source ranges.
- return E_NOTIMPL;
-}
-
-//-----------------------------------------------------------
-// UnicodeToUTF8
-// Translate the Unicode string to a UTF8 string
-// Return the length in UTF8 of the Unicode string
-// Including NULL terminator
-//-----------------------------------------------------------
-inline int WINAPI UnicodeToUTF8(
- LPCWSTR pUni, // Unicode string
- __out_bcount_opt(cbUTF) PSTR pUTF8, // [optional, out] Buffer for UTF8 string
- int cbUTF // length of UTF8 buffer
-)
-{
- // Pass in the length including the NULL terminator
- int cchSrc = (int)wcslen(pUni)+1;
- return WideCharToMultiByte(CP_UTF8, 0, pUni, cchSrc, pUTF8, cbUTF, NULL, NULL);
-}
-
-//-----------------------------------------------------------
-// SymWriter GetDebugCVInfo
-// Get the size and potentially the debug info
-//-----------------------------------------------------------
-COM_METHOD SymWriter::GetDebugCVInfo(
- DWORD cbBuf, // [optional] Size of buf
- DWORD *pcbBuf, // [out] Size needed for the DebugInfo
- BYTE buf[]) // [optional, out] Buffer for DebugInfo
-{
-
- if ( *m_szPath == 0 )
- return E_UNEXPECTED;
-
- // We need to change the .ildb extension to .pdb to be
- // compatible with VS7
- WCHAR fullpath[_MAX_PATH];
- WCHAR drive[_MAX_DRIVE];
- WCHAR dir[_MAX_DIR];
- WCHAR fname[_MAX_FNAME];
- if (_wsplitpath_s( m_szPath, drive, COUNTOF(drive), dir, COUNTOF(dir), fname, COUNTOF(fname), NULL, 0 ))
- return E_FAIL;
- if (_wmakepath_s( fullpath, COUNTOF(fullpath), drive, dir, fname, W("pdb") ))
- return E_FAIL;
-
- // Get UTF-8 string size, including the Null Terminator
- int Utf8Length = UnicodeToUTF8( fullpath, NULL, 0 );
- if (Utf8Length < 0 )
- return HRESULT_FROM_GetLastError();
-
- DWORD dwSize = sizeof(RSDSI) + DWORD(Utf8Length);
-
- // If the caller is just checking for the size
- if ( cbBuf == 0 && pcbBuf != NULL )
- {
- *pcbBuf = dwSize;
- return S_OK;
- }
-
- if (cbBuf < dwSize)
- {
- return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
- }
-
- if ( buf == NULL )
- {
- return E_INVALIDARG;
- }
-
- RSDSI* pRsdsi = (RSDSI*)buf;
- pRsdsi->dwSig = VAL32(0x53445352); // "SDSR";
- pRsdsi->guidSig = ILDB_VERSION_GUID;
- SwapGuid(&(pRsdsi->guidSig));
- // Age of 0 represent VC6.0 format so make sure it's 1
- pRsdsi->age = VAL32(1);
- UnicodeToUTF8( fullpath, pRsdsi->szPDB, Utf8Length );
- if ( pcbBuf )
- *pcbBuf = dwSize;
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// SymWriter GetDebugInfo
-// Get the size and potentially the debug info
-//-----------------------------------------------------------
-COM_METHOD SymWriter::GetDebugInfo(
- IMAGE_DEBUG_DIRECTORY *pIDD, // [out] IDD to fill in
- DWORD cData, // [optional] size of data
- DWORD *pcData, // [optional, out] return needed size for DebugInfo
- BYTE data[]) // [optional] Buffer to store into
-{
- HRESULT hr = S_OK;
- if ( cData == 0 && pcData != NULL )
- {
- // just checking for the size
- return GetDebugCVInfo( 0, pcData, NULL );
- }
-
- if ( pIDD == NULL )
- return E_INVALIDARG;
-
- DWORD cTheData = 0;
- IfFailGo( GetDebugCVInfo( cData, &cTheData, data ) );
-
- memset( pIDD, 0, sizeof( *pIDD ) );
- pIDD->Type = VAL32(IMAGE_DEBUG_TYPE_CODEVIEW);
- pIDD->SizeOfData = VAL32(cTheData);
-
- if ( pcData ) {
- *pcData = cTheData;
- }
-
-ErrExit:
- return hr;
-}
-
-COM_METHOD SymWriter::RemapToken(mdToken oldToken, mdToken newToken)
-{
- HRESULT hr = NOERROR;
- if (oldToken != newToken)
- {
- // We only care about methods
- if ((TypeFromToken(oldToken) == mdtMethodDef) ||
- (TypeFromToken(newToken) == mdtMethodDef))
- {
- // Make sure they are both methods
- _ASSERTE(TypeFromToken(newToken) == mdtMethodDef);
- _ASSERTE(TypeFromToken(oldToken) == mdtMethodDef);
-
- // Make sure we sort before saving
- m_sortMethodEntries = true;
-
- // Check to see if we're trying to map a token we know about
- unsigned i;
- for (i = 0; i < m_MethodInfo.m_methods.count(); i++)
- {
- if (m_MethodInfo.m_methods[i].MethodToken() == oldToken)
- {
- // Remember the map, we need to actually do the actual
- // mapping later because we might already have a function
- // with a token 'newToken'
- SymMap *pMethodMap;
- IfNullGo( pMethodMap = m_MethodMap.next() );
- pMethodMap->m_MethodToken = newToken;
- pMethodMap->MethodEntry = i;
- break;
- }
- }
- }
- }
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter Write
-// Write the information to a file or to a stream
-//-----------------------------------------------------------
-COM_METHOD SymWriter::Write(void *pData, DWORD SizeOfData)
-{
- HRESULT hr = NOERROR;
- DWORD NumberOfBytesWritten = 0;
- if (m_pIStream)
- {
- IfFailGo(m_pIStream->Write(pData,
- SizeOfData,
- &NumberOfBytesWritten));
- }
- else
- {
- // Write out a signature to recognize that we're an ildb
- if (!WriteFile(m_hFile, pData, SizeOfData, &NumberOfBytesWritten, NULL))
- return HrFromWin32(GetLastError());
- }
- _ASSERTE(NumberOfBytesWritten == SizeOfData);
-ErrExit:
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter WriteStringPool
-// Write the information to a file or to a stream
-//-----------------------------------------------------------
-COM_METHOD SymWriter::WriteStringPool()
-{
- IStream *pIStream = NULL;
- BYTE *pStreamMem = NULL;
-
- HRESULT hr = NOERROR;
- if (m_pIStream)
- {
- IfFailGo(m_pStringPool->PersistToStream(m_pIStream));
- }
- else
- {
- LARGE_INTEGER disp = { {0, 0} };
- DWORD NumberOfBytes;
- DWORD SizeOfData;
- STATSTG statStg;
-
- IfFailGo(CreateStreamOnHGlobal(NULL,
- TRUE,
- &pIStream));
-
- IfFailGo(m_pStringPool->PersistToStream(pIStream));
-
- IfFailGo(pIStream->Stat(&statStg, STATFLAG_NONAME));
- SizeOfData = statStg.cbSize.u.LowPart;
-
- IfFailGo(pIStream->Seek(disp, STREAM_SEEK_SET, NULL));
-
- pStreamMem = NEW(BYTE[SizeOfData]);
- IfFailGo(pIStream->Read(pStreamMem, SizeOfData, &NumberOfBytes));
-
- if (!WriteFile(m_hFile, pStreamMem, SizeOfData, &NumberOfBytes, NULL))
- return HrFromWin32(GetLastError());
-
- _ASSERTE(NumberOfBytes == SizeOfData);
-
- }
-ErrExit:
- RELEASE(pIStream);
- DELETEARRAY(pStreamMem);
- return hr;
-}
-
-//-----------------------------------------------------------
-// SymWriter WritePDB
-// Write the PDB information to a file or to a stream
-//-----------------------------------------------------------
-COM_METHOD SymWriter::WritePDB()
-{
-
- HRESULT hr = NOERROR;
- GUID ildb_guid = ILDB_VERSION_GUID;
-
- // Make sure the ModuleLevelInfo is set
- ModuleLevelInfo.m_CountOfVars = VAL32(m_MethodInfo.m_vars.count());
- ModuleLevelInfo.m_CountOfBytes = VAL32(m_MethodInfo.m_bytes.count());
- ModuleLevelInfo.m_CountOfUsing = VAL32(m_MethodInfo.m_usings.count());
- ModuleLevelInfo.m_CountOfScopes = VAL32(m_MethodInfo.m_scopes.count());
- ModuleLevelInfo.m_CountOfMethods = VAL32(m_MethodInfo.m_methods.count());
- if (m_pStringPool)
- {
- DWORD dwSaveSize;
- IfFailGo(m_pStringPool->GetSaveSize((UINT32 *)&dwSaveSize));
- ModuleLevelInfo.m_CountOfStringBytes = VAL32(dwSaveSize);
- }
- else
- {
- ModuleLevelInfo.m_CountOfStringBytes = 0;
- }
- ModuleLevelInfo.m_CountOfConstants = VAL32(m_MethodInfo.m_constants.count());
- ModuleLevelInfo.m_CountOfDocuments = VAL32(m_MethodInfo.m_documents.count());
- ModuleLevelInfo.m_CountOfSequencePoints = VAL32(m_MethodInfo.m_auxSequencePoints.count());
-
- // Open the file
- if (m_pIStream == NULL)
- {
- // We need to open the output file.
- m_hFile = WszCreateFile(m_szPath,
- GENERIC_WRITE,
- 0,
- NULL,
- CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- if (m_hFile == INVALID_HANDLE_VALUE)
- {
- IfFailGo(HrFromWin32(GetLastError()));
- }
- }
- else
- {
- // We're writing to a stream. Make sure we're at the beginning
- // (eg. if this is being called more than once).
- // Note that technically we should probably call SetSize to truncate the
- // stream to ensure we don't leave reminants of the previous contents
- // at the end of the new stream. But with our current CGrowableStream
- // implementation, this would have a big performance impact (causing us to
- // do linear growth and lots of reallocations at every write). We only
- // ever add data to a symbol writer (don't remove anything), and so subsequent
- // streams should always get larger. Regardless, ILDB supports trailing garbage
- // without a problem (we used to always have the remainder of a page at the end
- // of the stream), and so this is not an issue of correctness.
- LARGE_INTEGER pos0;
- pos0.QuadPart = 0;
- IfFailGo(m_pIStream->Seek(pos0, STREAM_SEEK_SET, NULL));
- }
-
-#if _DEBUG
- // We need to make sure the Variant entry in the constants is 8 byte
- // aligned so make sure everything up to the there is aligned correctly
- if ((ILDB_SIGNATURE_SIZE % 8) ||
- (sizeof(PDBInfo) % 8) ||
- (sizeof(GUID) % 8))
- {
- _ASSERTE(!"We need to safe the data in an aligned format");
- }
-#endif
-
- // Write out a signature to recognize that we're an ildb
- IfFailGo(Write((void *)ILDB_SIGNATURE, ILDB_SIGNATURE_SIZE));
- // Write out a guid representing the version
- SwapGuid(&ildb_guid);
- IfFailGo(Write((void *)&ildb_guid, sizeof(GUID)));
-
- // Now we need to write the Project level
- IfFailGo(Write(&ModuleLevelInfo, sizeof(PDBInfo)));
-
- // Now we have to write out each array as appropriate
- IfFailGo(Write(m_MethodInfo.m_constants.m_array, sizeof(SymConstant) * m_MethodInfo.m_constants.count()));
-
- // These members are all 4 byte aligned
- IfFailGo(Write(m_MethodInfo.m_methods.m_array, sizeof(SymMethodInfo) * m_MethodInfo.m_methods.count()));
- IfFailGo(Write(m_MethodInfo.m_scopes.m_array, sizeof(SymLexicalScope) * m_MethodInfo.m_scopes.count()));
- IfFailGo(Write(m_MethodInfo.m_vars.m_array, sizeof(SymVariable) * m_MethodInfo.m_vars.count()));
- IfFailGo(Write(m_MethodInfo.m_usings.m_array, sizeof(SymUsingNamespace) * m_MethodInfo.m_usings.count()));
- IfFailGo(Write(m_MethodInfo.m_auxSequencePoints.m_array, sizeof(SequencePoint) * m_MethodInfo.m_auxSequencePoints.count()));
- IfFailGo(Write(m_MethodInfo.m_documents.m_array, sizeof(DocumentInfo) * m_MethodInfo.m_documents.count()));
- IfFailGo(Write(m_MethodInfo.m_bytes.m_array, sizeof(BYTE) * m_MethodInfo.m_bytes.count()));
- IfFailGo(WriteStringPool());
-
-ErrExit:
- if (m_hFile)
- CloseHandle(m_hFile);
- return hr;
-}
-
-/* ------------------------------------------------------------------------- *
- * SymDocumentWriter class
- * ------------------------------------------------------------------------- */
-SymDocumentWriter::SymDocumentWriter(
- UINT32 DocumentEntry,
- SymWriter *pEmitter
-) :
- m_refCount ( 0 ),
- m_DocumentEntry ( DocumentEntry ),
- m_pEmitter( pEmitter )
-{
- _ASSERTE(pEmitter);
- m_pEmitter->AddRef();
-}
-
-SymDocumentWriter::~SymDocumentWriter()
-{
- // Note that this must be thread-safe - it may be invoked on the finalizer thread
- RELEASE(m_pEmitter);
-}
-
-COM_METHOD SymDocumentWriter::QueryInterface(REFIID riid, void **ppInterface)
-{
- if (ppInterface == NULL)
- return E_INVALIDARG;
-
- if (riid == IID_ISymUnmanagedDocumentWriter)
- *ppInterface = (ISymUnmanagedDocumentWriter*)this;
- else if (riid == IID_IUnknown)
- *ppInterface = (IUnknown*)(ISymUnmanagedDocumentWriter*)this;
- else
- {
- *ppInterface = NULL;
- return E_NOINTERFACE;
- }
-
- AddRef();
- return S_OK;
-}
-
-//-----------------------------------------------------------
-// SymDocumentWriter SetSource
-//-----------------------------------------------------------
-COM_METHOD SymDocumentWriter::SetSource(ULONG32 sourceSize,
- BYTE source[])
-{
- return m_pEmitter->SetDocumentSrc(m_DocumentEntry, sourceSize, source);
-}
-
-//-----------------------------------------------------------
-// SymDocumentWriter SetCheckSum
-//-----------------------------------------------------------
-COM_METHOD SymDocumentWriter::SetCheckSum(GUID algorithmId,
- ULONG32 checkSumSize,
- BYTE checkSum[])
-{
- return m_pEmitter->SetDocumentCheckSum(m_DocumentEntry, algorithmId, checkSumSize, checkSum);
-}
-
-
-//-----------------------------------------------------------
-// DocumentInfo SetDocumentWriter
-//-----------------------------------------------------------
-// Set the pointer to the SymDocumentWriter instance corresponding to this instance of DocumentInfo
-// An argument of NULL will call Release
-// Arguments
-// input: pDoc - pointer to the associated SymDocumentWriter or NULL
-
-void DocumentInfo::SetDocumentWriter(SymDocumentWriter * pDoc)
-{
- if (m_pDocumentWriter != NULL)
- {
- m_pDocumentWriter->Release();
- }
- m_pDocumentWriter = pDoc;
- if (m_pDocumentWriter != NULL)
- {
- pDoc->AddRef();
- }
-}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ===========================================================================
-// File: SymWrite.h
-//
-
-// ===========================================================================
-
-#ifndef SYMWRITE_H_
-#define SYMWRITE_H_
-#ifdef _MSC_VER
-#pragma warning(disable:4786)
-#endif
-
-#include <windows.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "cor.h"
-#include "umisc.h"
-#include "stgpool.h"
-#include "safemath.h"
-
-#include <corsym.h>
-#include "pdbdata.h"
-
-class SymDocumentWriter;
-
-#if BIGENDIAN
-/***
-*PUBLIC void VariantSwap
-*Purpose:
-* Swap the Variant members
-*
-*Entry:
-* SrcInBigEndian = whether pvarg is in BIGENDIAN or not
-* pvargDest = Destination variant
-* pvarg = pointer to a VARIANT to swap
-*
-*Exit:
-* Filled in pvarDest
-*
-***********************************************************************/
-inline HRESULT VariantSwap(bool SrcInBigEndian, VARIANT FAR *pvargDest, VARIANT FAR* pvarg)
-{
- if (pvargDest == NULL || pvarg == NULL)
- return E_INVALIDARG;
- VARTYPE vt = VT_EMPTY;
-
- if (SrcInBigEndian)
- {
- vt = V_VT(pvarg);
- }
- *(UINT32*)pvargDest = VAL32(*(UINT32*)pvarg);
- if (!SrcInBigEndian)
- {
- vt = V_VT(pvargDest);
- }
-
- switch (vt)
- {
- case VT_EMPTY:
- case VT_NULL:
- // No Value to swap
- break;
-
- // 1 byte
- case VT_I1:
- case VT_UI1:
- V_I1(pvargDest) = V_I1(pvarg);
- break;
-
- // 2 bytes
- case VT_I2:
- case VT_UI2:
- case VT_INT:
- case VT_UINT:
- case VT_BOOL:
- V_I2(pvargDest) = VAL16(V_I2(pvarg));
- break;
-
- // 4 bytes
- case VT_I4:
- case VT_UI4:
- case VT_R4:
- V_I4(pvargDest) = VAL32(V_I4(pvarg));
- break;
-
- // 8 bytes
- case VT_I8:
- case VT_UI8:
- case VT_R8:
- case VT_DATE:
- V_I8(pvargDest) = VAL64(V_I8(pvarg));
- break;
-
- case VT_DECIMAL:
- DECIMAL_HI32(V_DECIMAL(pvargDest)) = VAL32(DECIMAL_HI32(V_DECIMAL(pvarg)));
- DECIMAL_LO32(V_DECIMAL(pvargDest)) = VAL32(DECIMAL_LO32(V_DECIMAL(pvarg)));
- DECIMAL_MID32(V_DECIMAL(pvargDest)) = VAL32(DECIMAL_MID32(V_DECIMAL(pvarg)));
- break;
-
- // These aren't currently supported
- case VT_CY: //6
- case VT_BSTR: //8
- case VT_DISPATCH: //9
- case VT_ERROR: //10
- case VT_VARIANT: //12
- case VT_UNKNOWN: //13
- case VT_VOID: //24
- case VT_HRESULT: //25
- case VT_PTR: //26
- case VT_SAFEARRAY: //27
- case VT_CARRAY: //28
- case VT_USERDEFINED://29
- case VT_LPSTR: //30
- case VT_LPWSTR: //31
- case VT_FILETIME: //64
- case VT_BLOB: //65
- case VT_STREAM: //66
- case VT_STORAGE: //67
- case VT_STREAMED_OBJECT: //68
- case VT_STORED_OBJECT: //69
- case VT_BLOB_OBJECT: //70
- case VT_CF: //71
- case VT_CLSID: //72
- default:
- _ASSERTE(!"NYI");
- break;
- }
- return NOERROR;
-}
-#endif // BIGENDIAN
-
-// Default space sizes for the various arrays. Make it too small in a
-// checked build so we exercise the growing code.
-#ifdef _DEBUG
-#define DEF_LOCAL_SPACE 2
-#define DEF_MISC_SPACE 64
-#else
-#define DEF_LOCAL_SPACE 64
-#define DEF_MISC_SPACE 1024
-#endif
-
-/* ------------------------------------------------------------------------- *
- * SymVariable struct
- * ------------------------------------------------------------------------- */
-struct SymVariable
-{
-private:
- UINT32 m_Scope; // index of parent scope
- UINT32 m_Name; // index into misc byte array
- ULONG32 m_Attributes; // Attributes
- UINT32 m_Signature; // index into misc byte array
- ULONG32 m_SignatureSize; // Signature size
- ULONG32 m_AddrKind; // Address Kind
- ULONG32 m_Addr1; // Additional info
- ULONG32 m_Addr2;
- ULONG32 m_Addr3;
- ULONG32 m_StartOffset; // StartOffset
- ULONG32 m_EndOffset; // EndOffset
- ULONG32 m_Sequence;
- BOOL m_IsParam; // parameter?
- BOOL m_IsHidden; // Is not visible to the user
-
-public:
- UINT32 Scope()
- {
- return VAL32(m_Scope);
- }
- void SetScope(UINT32 Scope)
- {
- m_Scope = VAL32(Scope);
- }
-
- UINT32 Name()
- {
- return VAL32(m_Name);
- }
- void SetName(UINT32 Name)
- {
- m_Name = VAL32(Name);
- }
-
- ULONG32 Attributes()
- {
- return VAL32(m_Attributes);
- }
- void SetAttributes(ULONG32 Attributes)
- {
- m_Attributes = VAL32(Attributes);
- }
-
- UINT32 Signature()
- {
- return VAL32(m_Signature);
- }
- void SetSignature(UINT32 Signature)
- {
- m_Signature = VAL32(Signature);
- }
- ULONG32 SignatureSize()
- {
- return VAL32(m_SignatureSize);
- }
- void SetSignatureSize(ULONG32 SignatureSize)
- {
- m_SignatureSize = VAL32(SignatureSize);
- }
-
- ULONG32 AddrKind()
- {
- return VAL32(m_AddrKind);
- }
- void SetAddrKind(ULONG32 AddrKind)
- {
- m_AddrKind = VAL32(AddrKind);
- }
- ULONG32 Addr1()
- {
- return VAL32(m_Addr1);
- }
- void SetAddr1(ULONG32 Addr1)
- {
- m_Addr1 = VAL32(Addr1);
- }
-
- ULONG32 Addr2()
- {
- return VAL32(m_Addr2);
- }
- void SetAddr2(ULONG32 Addr2)
- {
- m_Addr2 = VAL32(Addr2);
- }
-
- ULONG32 Addr3()
- {
- return VAL32(m_Addr3);
- }
- void SetAddr3(ULONG32 Addr3)
- {
- m_Addr3 = VAL32(Addr3);
- }
-
- ULONG32 StartOffset()
- {
- return VAL32(m_StartOffset);
- }
- void SetStartOffset(ULONG32 StartOffset)
- {
- m_StartOffset = VAL32(StartOffset);
- }
- ULONG32 EndOffset()
- {
- return VAL32(m_EndOffset);
- }
- void SetEndOffset(ULONG EndOffset)
- {
- m_EndOffset = VAL32(EndOffset);
- }
- ULONG32 Sequence()
- {
- return VAL32(m_Sequence);
- }
- void SetSequence(ULONG32 Sequence)
- {
- m_Sequence = VAL32(Sequence);
- }
-
- BOOL IsParam()
- {
- return VAL32(m_IsParam);
- }
- void SetIsParam(BOOL IsParam)
- {
- m_IsParam = IsParam;
- }
- BOOL IsHidden()
- {
- return VAL32(m_IsHidden);
- }
- void SetIsHidden(BOOL IsHidden)
- {
- m_IsHidden = IsHidden;
- }
-};
-
-/* ------------------------------------------------------------------------- *
- * SymLexicalScope struct
- * ------------------------------------------------------------------------- */
-struct SymLexicalScope
-{
-private:
-
- UINT32 m_ParentScope; // parent index (-1 for no parent)
- ULONG32 m_StartOffset; // start offset
- ULONG32 m_EndOffset; // end offset
- BOOL m_HasChildren; // scope has children
- BOOL m_HasVars; // scope has vars?
-public:
- UINT32 ParentScope()
- {
- return VAL32(m_ParentScope);
- }
- void SetParentScope(UINT32 ParentScope)
- {
- m_ParentScope = VAL32(ParentScope);
- }
-
- ULONG32 StartOffset()
- {
- return VAL32(m_StartOffset);
- }
- void SetStartOffset(ULONG32 StartOffset)
- {
- m_StartOffset = VAL32(StartOffset);
- }
- ULONG32 EndOffset()
- {
- return VAL32(m_EndOffset);
- }
- void SetEndOffset(ULONG32 EndOffset)
- {
- m_EndOffset = VAL32(EndOffset);
- }
- BOOL HasChildren()
- {
- return m_HasChildren;
- }
- void SetHasChildren(BOOL HasChildren)
- {
- m_HasChildren = HasChildren;
- }
- BOOL HasVars()
- {
- return m_HasVars;
- }
- void SetHasVars(BOOL HasVars)
- {
- m_HasVars = HasVars;
- }
-
-};
-
-/* ------------------------------------------------------------------------- *
- * SymUsingNamespace struct
- * ------------------------------------------------------------------------- */
-struct SymUsingNamespace
-{
-private:
-
- UINT32 m_ParentScope; // index of parent scope
- UINT32 m_Name; // Index of name
-public:
- UINT32 ParentScope()
- {
- return VAL32(m_ParentScope);
- }
- void SetParentScope(UINT32 ParentScope)
- {
- m_ParentScope = VAL32(ParentScope);
- }
- UINT32 Name()
- {
- return VAL32(m_Name);
- }
- void SetName(UINT32 Name)
- {
- m_Name = VAL32(Name);
- }
-};
-
-/* ------------------------------------------------------------------------- *
- * SymConstant struct
- * ------------------------------------------------------------------------- */
-struct SymConstant
-{
-private:
-
- VARIANT m_Value; // Constant Value
- UINT32 m_ParentScope; // Parent scope
- UINT32 m_Name; // Name index
- UINT32 m_Signature; // Signature index
- ULONG32 m_SignatureSize;// Signature size
- UINT32 m_ValueBstr; // If the variant is a bstr, store the string
-
-public:
- UINT32 ParentScope()
- {
- return VAL32(m_ParentScope);
- }
- void SetParentScope(UINT32 ParentScope)
- {
- m_ParentScope = VAL32(ParentScope);
- }
- UINT32 Name()
- {
- return VAL32(m_Name);
- }
- void SetName(UINT32 Name)
- {
- m_Name = VAL32(Name);
- }
- UINT32 Signature()
- {
- return VAL32(m_Signature);
- }
- void SetSignature(UINT32 Signature)
- {
- m_Signature = VAL32(Signature);
- }
- ULONG32 SignatureSize()
- {
- return VAL32(m_SignatureSize);
- }
- void SetSignatureSize(ULONG32 SignatureSize)
- {
- m_SignatureSize = VAL32(SignatureSize);
- }
- VARIANT Value(UINT32 *pValueBstr)
- {
- *pValueBstr = VAL32(m_ValueBstr);
-#if BIGENDIAN
- VARIANT VariantValue;
- VariantInit(&VariantValue);
- // VT_BSTR's are dealt with ValueBStr
- if (m_ValueBstr)
- {
- V_VT(&VariantValue) = VT_BSTR;
- }
- else
- {
- VariantSwap(false, &VariantValue, &m_Value);
- }
- return VariantValue;
-#else
- return m_Value;
-#endif
- }
- void SetValue(VARIANT VariantValue, UINT32 ValueBstr)
- {
- m_Value = VariantValue;
- m_ValueBstr = VAL32(ValueBstr);
-#if BIGENDIAN
- // VT_BSTR's are dealt with ValueBStr
- if (m_ValueBstr)
- {
- V_VT(&m_Value) = VAL16(VT_BSTR);
- }
- else
- {
- VariantSwap(true, &m_Value, &VariantValue);
- }
-#endif
- }
-};
-
-/* ------------------------------------------------------------------------- *
- * SymMethodInfo struct
- * ------------------------------------------------------------------------- */
-struct SymMethodInfo
-{
-private:
-
- mdMethodDef m_MethodToken; // Method token
-
- // Start/End Entries into the respective tables
- // End values are extents - one past the last index (and so may actually be an index off
- // the end of the array). Start may equal end if the method has none of the item.
- UINT32 m_StartScopes;
- UINT32 m_EndScopes;
- UINT32 m_StartVars;
- UINT32 m_EndVars;
- UINT32 m_StartUsing;
- UINT32 m_EndUsing;
- UINT32 m_StartConstant;
- UINT32 m_EndConstant;
- UINT32 m_StartDocuments;
- UINT32 m_EndDocuments;
- UINT32 m_StartSequencePoints;
- UINT32 m_EndSequencePoints;
-
-public:
- static int __cdecl compareMethods(const void *elem1, const void *elem2 );
-
- mdMethodDef MethodToken()
- {
- return VAL32(m_MethodToken);
- }
- void SetMethodToken(mdMethodDef MethodToken)
- {
- m_MethodToken = VAL32(MethodToken);
- }
- UINT32 StartScopes()
- {
- return VAL32(m_StartScopes);
- }
- void SetStartScopes(UINT32 StartScopes)
- {
- m_StartScopes = VAL32(StartScopes);
- }
- UINT32 EndScopes()
- {
- return VAL32(m_EndScopes);
- }
- void SetEndScopes(UINT32 EndScopes)
- {
- m_EndScopes = VAL32(EndScopes);
- }
- UINT32 StartVars()
- {
- return VAL32(m_StartVars);
- }
- void SetStartVars(UINT32 StartVars)
- {
- m_StartVars = VAL32(StartVars);
- }
- UINT32 EndVars()
- {
- return VAL32(m_EndVars);
- }
- void SetEndVars(UINT32 EndVars)
- {
- m_EndVars = VAL32(EndVars);
- }
- UINT32 StartUsing()
- {
- return VAL32(m_StartUsing);
- }
- void SetStartUsing(UINT32 StartUsing)
- {
- m_StartUsing = VAL32(StartUsing);
- }
- UINT32 EndUsing()
- {
- return VAL32(m_EndUsing);
- }
- void SetEndUsing(UINT32 EndUsing)
- {
- m_EndUsing = VAL32(EndUsing);
- }
- UINT32 StartConstant()
- {
- return VAL32(m_StartConstant);
- }
- void SetStartConstant(UINT32 StartConstant)
- {
- m_StartConstant = VAL32(StartConstant);
- }
- UINT32 EndConstant()
- {
- return VAL32(m_EndConstant);
- }
- void SetEndConstant(UINT32 EndConstant)
- {
- m_EndConstant = VAL32(EndConstant);
- }
- UINT32 StartDocuments()
- {
- return VAL32(m_StartDocuments);
- }
- void SetStartDocuments(UINT32 StartDocuments)
- {
- m_StartDocuments = VAL32(StartDocuments);
- }
- UINT32 EndDocuments()
- {
- return VAL32(m_EndDocuments);
- }
- void SetEndDocuments(UINT32 EndDocuments)
- {
- m_EndDocuments = VAL32(EndDocuments);
- }
- UINT32 StartSequencePoints()
- {
- return VAL32(m_StartSequencePoints);
- }
- void SetStartSequencePoints(UINT32 StartSequencePoints)
- {
- m_StartSequencePoints = VAL32(StartSequencePoints);
- }
- UINT32 EndSequencePoints()
- {
- return VAL32(m_EndSequencePoints);
- }
- void SetEndSequencePoints(UINT32 EndSequencePoints)
- {
- m_EndSequencePoints = VAL32(EndSequencePoints);
- }
-};
-
-/* ------------------------------------------------------------------------- *
- * SymMap struct
- * ------------------------------------------------------------------------- */
-struct SymMap
-{
- mdMethodDef m_MethodToken; // New Method token
- UINT32 MethodEntry; // Method Entry
-};
-
-/* ------------------------------------------------------------------------- *
- * SequencePoint struct
- * ------------------------------------------------------------------------- */
-struct SequencePoint {
-
-private:
-
- DWORD m_Offset;
- DWORD m_StartLine;
- DWORD m_StartColumn;
- DWORD m_EndLine;
- DWORD m_EndColumn;
- DWORD m_Document;
-
-public:
- bool IsWithin(ULONG32 line, ULONG32 column);
- bool IsWithinLineOnly(ULONG32 line);
- bool IsGreaterThan(ULONG32 line, ULONG32 column);
- bool IsLessThan(ULONG32 line, ULONG32 column);
- bool IsUserLine();
- static int __cdecl compareAuxLines(const void *elem1, const void *elem2 );
-
- DWORD Offset()
- {
- return VAL32(m_Offset);
- }
- void SetOffset(DWORD Offset)
- {
- m_Offset = VAL32(Offset);
- }
- DWORD StartLine()
- {
- return VAL32(m_StartLine);
- }
- void SetStartLine(DWORD StartLine)
- {
- m_StartLine = VAL32(StartLine);
- }
-
- DWORD StartColumn()
- {
- return VAL32(m_StartColumn);
- }
- void SetStartColumn(DWORD StartColumn)
- {
- m_StartColumn = VAL32(StartColumn);
- }
-
- DWORD EndLine()
- {
- return VAL32(m_EndLine);
- }
- void SetEndLine(DWORD EndLine)
- {
- m_EndLine = VAL32(EndLine);
- }
- DWORD EndColumn()
- {
- return VAL32(m_EndColumn);
- }
- void SetEndColumn(DWORD EndColumn)
- {
- m_EndColumn = VAL32(EndColumn);
- }
- DWORD Document()
- {
- return VAL32(m_Document);
- }
- void SetDocument(DWORD Document)
- {
- m_Document = VAL32(Document);
- }
-};
-
-
-/* ------------------------------------------------------------------------- *
- * DocumentInfo struct
- * ------------------------------------------------------------------------- */
-typedef struct DocumentInfo {
-
-private:
-
- GUID m_Language;
- GUID m_LanguageVendor;
- GUID m_DocumentType;
- GUID m_AlgorithmId;
- DWORD m_CheckSumSize;
- UINT32 m_CheckSumEntry;
- UINT32 m_SourceSize;
- UINT32 m_SourceEntry;
- UINT32 m_UrlEntry;
- SymDocumentWriter * m_pDocumentWriter;
-
-public:
-
- GUID Language()
- {
- GUID TmpGuid = m_Language;
- SwapGuid(&TmpGuid);
- return TmpGuid;
- }
- void SetLanguage(GUID Language)
- {
- SwapGuid(&Language);
- m_Language = Language;
- }
- GUID LanguageVendor()
- {
- GUID TmpGuid = m_LanguageVendor;
- SwapGuid(&TmpGuid);
- return TmpGuid;
- }
- void SetLanguageVendor(GUID LanguageVendor)
- {
- SwapGuid(&LanguageVendor);
- m_LanguageVendor = LanguageVendor;
- }
- GUID DocumentType()
- {
- GUID TmpGuid = m_DocumentType;
- SwapGuid(&TmpGuid);
- return TmpGuid;
- }
- void SetDocumentType(GUID DocumentType)
- {
- SwapGuid(&DocumentType);
- m_DocumentType = DocumentType;
- }
-
- // Set the pointer to the SymDocumentWriter instance corresponding to this instance of DocumentInfo
- // An argument of NULL will call Release
- void SetDocumentWriter(SymDocumentWriter * pDoc);
-
- // get the associated SymDocumentWriter
- SymDocumentWriter * DocumentWriter()
- {
- return m_pDocumentWriter;
- }
-
- GUID AlgorithmId()
- {
- GUID TmpGuid = m_AlgorithmId;
- SwapGuid(&TmpGuid);
- return TmpGuid;
- }
- void SetAlgorithmId(GUID AlgorithmId)
- {
- SwapGuid(&AlgorithmId);
- m_AlgorithmId = AlgorithmId;
- }
-
- DWORD CheckSumSize()
- {
- return VAL32(m_CheckSumSize);
- }
- void SetCheckSymSize(DWORD CheckSumSize)
- {
- m_CheckSumSize = VAL32(CheckSumSize);
- }
- UINT32 CheckSumEntry()
- {
- return VAL32(m_CheckSumEntry);
- }
- void SetCheckSumEntry(UINT32 CheckSumEntry)
- {
- m_CheckSumEntry = VAL32(CheckSumEntry);
- }
- UINT32 SourceSize()
- {
- return VAL32(m_SourceSize);
- }
- void SetSourceSize(UINT32 SourceSize)
- {
- m_SourceSize = VAL32(SourceSize);
- }
- UINT32 SourceEntry()
- {
- return VAL32(m_SourceEntry);
- }
- void SetSourceEntry(UINT32 SourceEntry)
- {
- m_SourceEntry = VAL32(SourceEntry);
- }
- UINT32 UrlEntry()
- {
- return VAL32(m_UrlEntry);
- }
- void SetUrlEntry(UINT32 UrlEntry)
- {
- m_UrlEntry = VAL32(UrlEntry);
- }
-
-} DocumentInfo;
-
-template <class T>
-class ArrayStorage
-{
-public:
-
- ArrayStorage( int initialSize = 0 )
- : m_spaceSize(0), m_instanceCount( 0 ), m_array( NULL )
- {
- grow( initialSize );
- }
- ~ArrayStorage()
- {
-
- if ( m_array )
- DELETEARRAY(m_array);
- m_array = NULL;
- m_spaceSize = 0;
- m_instanceCount = 0;
- }
- T* next()
- {
- if( !grow ( m_instanceCount ) )
- return NULL;
- _ASSERTE( m_instanceCount < m_spaceSize );
- return &m_array[ m_instanceCount++ ];
- }
- bool grab(UINT32 n, UINT32 * pIndex)
- {
- S_UINT32 newSize = S_UINT32(m_instanceCount) + S_UINT32(n);
- if (newSize.IsOverflow())
- return false;
- if (!grow(newSize.Value()))
- return false;
- _ASSERTE( m_instanceCount < m_spaceSize );
- *pIndex = m_instanceCount;
- m_instanceCount += n;
- return true;
- }
-
- T& operator[]( UINT32 i ) {
- _ASSERTE( i < m_instanceCount );
- if (i >= m_instanceCount)
- {
- // Help mitigate the impact of buffer overflow
- // Fail fast with a null-reference AV
- volatile char* nullPointer = nullptr;
- *nullPointer;
- }
- return m_array[ i ];
- }
- void reset() {
- m_instanceCount = 0;
- }
- UINT32 size() {
- return m_spaceSize;
- }
- UINT32 count() {
- return m_instanceCount;
- }
-
- UINT32 m_spaceSize; // Total size of array in elements
- UINT32 m_instanceCount; // total T's in the file
- T *m_array; // array of T's
-private:
- bool grow( UINT32 n )
- {
- if (n >= m_spaceSize)
- {
- // Make a new, bigger array.
- UINT32 newSpaceSize;
-
- if (n == 0)
- newSpaceSize = DEF_LOCAL_SPACE;
- else
- newSpaceSize = max( m_spaceSize * 2, n);
-
- // Make sure we're not asking for more than 4GB of bytes to ensure no integer-overflow attacks are possible
- S_UINT32 newBytes = S_UINT32(newSpaceSize) * S_UINT32(sizeof(T));
- if (newBytes.IsOverflow())
- return false;
-
- T *newTs;
- newTs = NEW(T[newSpaceSize]);
- if ( newTs == NULL )
- return false;
-
- // Copy over the old Ts.
- memcpy(newTs, m_array,
- sizeof(T) * m_spaceSize);
-
- // Delete the old Ts.
- DELETEARRAY(m_array);
-
- // Hang onto the new array.
- m_array = newTs;
- m_spaceSize = newSpaceSize;
- }
- return true;
- }
-
-};
-
-typedef struct MethodInfo {
-
- ArrayStorage<SymMethodInfo> m_methods; // Methods information
- ArrayStorage<SymLexicalScope> m_scopes; // Scope information for the method
- ArrayStorage<SymVariable> m_vars; // Variables
- ArrayStorage<SymUsingNamespace> m_usings; // using/imports
- ArrayStorage<SymConstant> m_constants; // Constants
- ArrayStorage<DocumentInfo> m_documents; // Document Source Format
- ArrayStorage<SequencePoint> m_auxSequencePoints; // Sequence Points
- // Array of various bytes (variable signature, etc)
- ArrayStorage<BYTE> m_bytes;
-
-
-public:
-
- MethodInfo() :
- m_bytes( DEF_MISC_SPACE )
- {
- }
-} MethodInfo;
-
-/* ------------------------------------------------------------------------- *
- * SymWriter class
- * ------------------------------------------------------------------------- */
-
-class SymWriter : public ISymUnmanagedWriter3
-{
-public:
- SymWriter();
- virtual ~SymWriter();
-
- //-----------------------------------------------------------
- // IUnknown support
- //-----------------------------------------------------------
- ULONG STDMETHODCALLTYPE AddRef()
- {
- return (InterlockedIncrement((LONG *) &m_refCount));
- }
-
- ULONG STDMETHODCALLTYPE Release()
- {
- // Note that this must be thread-safe - it may be invoked on the finalizer thread
- LONG refCount = InterlockedDecrement((LONG *) &m_refCount);
- if (refCount == 0)
- DELETE(this);
-
- return (refCount);
- }
- COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
-
- //-----------------------------------------------------------
- // ISymUnmanagedWriter
- //-----------------------------------------------------------
- COM_METHOD DefineDocument(const WCHAR *url,
- const GUID *language,
- const GUID *languageVendor,
- const GUID *documentType,
- ISymUnmanagedDocumentWriter **pRetVal);
- COM_METHOD SetUserEntryPoint(mdMethodDef entryMethod);
- COM_METHOD OpenMethod(mdMethodDef method);
- COM_METHOD CloseMethod();
- COM_METHOD DefineSequencePoints(ISymUnmanagedDocumentWriter *document,
- ULONG32 spCount,
- ULONG32 offsets[],
- ULONG32 lines[],
- ULONG32 columns[],
- ULONG32 endLines[],
- ULONG32 encColumns[]);
- COM_METHOD OpenScope(ULONG32 startOffset, ULONG32 *scopeID);
- COM_METHOD CloseScope(ULONG32 endOffset);
- COM_METHOD SetScopeRange(ULONG32 scopeID, ULONG32 startOffset, ULONG32 endOffset);
- COM_METHOD DefineLocalVariable(const WCHAR *name,
- ULONG32 attributes,
- ULONG32 cSig,
- BYTE signature[],
- ULONG32 addrKind,
- ULONG32 addr1, ULONG32 addr2, ULONG32 addr3,
- ULONG32 startOffset, ULONG32 endOffset);
- COM_METHOD DefineParameter(const WCHAR *name,
- ULONG32 attributes,
- ULONG32 sequence,
- ULONG32 addrKind,
- ULONG32 addr1, ULONG32 addr2, ULONG32 addr3);
- COM_METHOD DefineField(mdTypeDef parent,
- const WCHAR *name,
- ULONG32 attributes,
- ULONG32 cSig,
- BYTE signature[],
- ULONG32 addrKind,
- ULONG32 addr1, ULONG32 addr2, ULONG32 addr3);
- COM_METHOD DefineGlobalVariable(const WCHAR *name,
- ULONG32 attributes,
- ULONG32 cSig,
- BYTE signature[],
- ULONG32 addrKind,
- ULONG32 addr1, ULONG32 addr2, ULONG32 addr3);
- COM_METHOD Close();
- COM_METHOD SetSymAttribute(mdToken parent,
- const WCHAR *name,
- ULONG32 cData,
- BYTE data[]);
- COM_METHOD OpenNamespace(const WCHAR *name);
- COM_METHOD CloseNamespace();
- COM_METHOD UsingNamespace(const WCHAR *fullName);
- COM_METHOD SetMethodSourceRange(ISymUnmanagedDocumentWriter *startDoc,
- ULONG32 startLine,
- ULONG32 startColumn,
- ISymUnmanagedDocumentWriter *endDoc,
- ULONG32 endLine,
- ULONG32 endColumn);
- COM_METHOD GetDebugCVInfo(DWORD cData,
- DWORD *pcData,
- BYTE data[]);
-
- COM_METHOD Initialize(IUnknown *emitter,
- const WCHAR *filename,
- IStream *pIStream,
- BOOL fFullBuild);
-
- COM_METHOD Initialize2(IUnknown *emitter,
- const WCHAR *pdbTempPath, // location to write pdb file
- IStream *pIStream,
- BOOL fFullBuild,
- const WCHAR *pdbFinalPath); // location exe should contain for pdb file
-
- COM_METHOD GetDebugInfo(IMAGE_DEBUG_DIRECTORY *pIDD,
- DWORD cData,
- DWORD *pcData,
- BYTE data[]);
-
- COM_METHOD RemapToken(mdToken oldToken,
- mdToken newToken);
-
- COM_METHOD DefineConstant(const WCHAR __RPC_FAR *name,
- VARIANT value,
- ULONG32 cSig,
- unsigned char __RPC_FAR signature[ ]);
-
- COM_METHOD Abort(void);
-
- //-----------------------------------------------------------
- // ISymUnmanagedWriter2
- //-----------------------------------------------------------
- COM_METHOD DefineLocalVariable2(const WCHAR *name,
- ULONG32 attributes,
- mdSignature sigToken,
- ULONG32 addrKind,
- ULONG32 addr1,
- ULONG32 addr2,
- ULONG32 addr3,
- ULONG32 startOffset,
- ULONG32 endOffset);
-
- COM_METHOD DefineGlobalVariable2(const WCHAR *name,
- ULONG32 attributes,
- mdSignature sigToken,
- ULONG32 addrKind,
- ULONG32 addr1,
- ULONG32 addr2,
- ULONG32 addr3);
-
- COM_METHOD DefineConstant2(const WCHAR *name,
- VARIANT value,
- mdSignature sigToken);
-
- //-----------------------------------------------------------
- // ISymUnmanagedWriter3
- //-----------------------------------------------------------
-
- COM_METHOD OpenMethod2(mdMethodDef method,
- ULONG32 isect,
- ULONG32 offset);
-
- COM_METHOD Commit();
-
- //-----------------------------------------------------------
- // Methods not exposed via a COM interface.
- //-----------------------------------------------------------
-
- static HRESULT NewSymWriter(REFIID clsid, void** ppObj);
- HRESULT SetDocumentCheckSum(
- UINT32 DocumentEntry,
- GUID AlgorithmId,
- DWORD CheckSumSize,
- BYTE* pCheckSum);
- HRESULT SetDocumentSrc(UINT32 DocumentEntry,
- DWORD SourceSize,
- BYTE* pSource);
-
- COM_METHOD Write(void *pData, DWORD SizeOfData);
- COM_METHOD WriteStringPool();
- COM_METHOD WritePDB();
-
- COM_METHOD Initialize(const WCHAR *szFilename, IStream *pIStream);
-
- void SetFullPathName(const WCHAR *szFullPathName)
- {
-
- }
-
-private:
- // Helper API for CloserScope
- COM_METHOD CloseScopeInternal(ULONG32 endOffset);
- HRESULT GetOrCreateDocument(
- const WCHAR *wcsUrl, // Document name
- const GUID *pLanguage, // What Language we're compiling
- const GUID *pLanguageVendor, // What vendor
- const GUID *pDocumentType, // Type
- ISymUnmanagedDocumentWriter **ppRetVal // [out] Created DocumentWriter
- );
- HRESULT CreateDocument(
- const WCHAR *wcsUrl, // Document name
- const GUID *pLanguage, // What Language we're compiling
- const GUID *pLanguageVendor, // What vendor
- const GUID *pDocumentType, // Type
- ISymUnmanagedDocumentWriter **ppRetVal // [out] Created DocumentWriter
- );
-
-
- //-----------------------------------------------------------
- // Data members
- //-----------------------------------------------------------
-private:
- UINT32 m_refCount; // AddRef/Release
-
- mdMethodDef m_openMethodToken;
- mdMethodDef m_LargestMethodToken;
- SymMethodInfo * m_pmethod;
-
- // index of currently open scope
- UINT32 m_currentScope;
-
- // special scope "index" meaning there is no such scope
- static const UINT32 k_noScope = (UINT32)-1;
-
- // maximum scope end offset seen so far in this method
- ULONG32 m_maxScopeEnd;
-
- MethodInfo m_MethodInfo;
- ArrayStorage<SymMap> m_MethodMap; // Methods information
-
- // Symbol File Name
- WCHAR m_szPath[ _MAX_PATH ];
- // File Handle
- HANDLE m_hFile;
- // Stream we're storing into if asked to.
- IStream* m_pIStream;
-
- // StringPool we use to store the string into
- StgStringPool *m_pStringPool;
-
- // Project level symbol information
- PDBInfo ModuleLevelInfo;
-
- bool m_closed; // Have we closed the file yet?
- bool m_sortLines; // sort the line for current method
- bool m_sortMethodEntries; // Sort the method entries
-
-
-};
-
-/* ------------------------------------------------------------------------- *
- * SymDocumentWriter class
- * ------------------------------------------------------------------------- */
-
-class SymDocumentWriter : public ISymUnmanagedDocumentWriter
-{
-public:
- SymDocumentWriter(UINT32 DocumentEntry,
- SymWriter *pEmitter);
-
- virtual ~SymDocumentWriter();
-
- //-----------------------------------------------------------
- // IUnknown support
- //-----------------------------------------------------------
- ULONG STDMETHODCALLTYPE AddRef()
- {
- return (InterlockedIncrement((LONG *) &m_refCount));
- }
-
- ULONG STDMETHODCALLTYPE Release()
- {
- // Note that this must be thread-safe - it may be invoked on the finalizer thread
- LONG refCount = InterlockedDecrement((LONG *) &m_refCount);
- if (refCount == 0)
- DELETE(this);
-
- return (refCount);
- }
- COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
-
- //-----------------------------------------------------------
- // ISymUnmanagedDocumentWriter
- //-----------------------------------------------------------
- COM_METHOD SetSource(ULONG32 sourceSize, BYTE source[]);
- COM_METHOD SetCheckSum(GUID algorithmId,
- ULONG32 checkSumSize, BYTE checkSum[]);
-
- //-----------------------------------------------------------
- // Methods not exposed via a COM interface.
- //-----------------------------------------------------------
- //
- // Commit the doc to the pdb
- //
- UINT32 GetDocumentEntry()
- {
- return m_DocumentEntry;
- }
-
- //-----------------------------------------------------------
- // Data members
- //-----------------------------------------------------------
-private:
- UINT32 m_refCount; // AddRef/Release
- UINT32 m_DocumentEntry; // Entry into the documents array
- SymWriter *m_pEmitter; // Associated SymWriter
-};
-
-// Debug Info
-struct RSDSI // RSDS debug info
-{
- DWORD dwSig; // RSDS
- GUID guidSig;
- DWORD age;
- char szPDB[0]; // followed by a zero-terminated UTF8 file name
-};
-
-#endif /* SYMWRITE_H_ */
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// ===========================================================================
-// File: umisc.h
-//
-
-// ===========================================================================
-
-
-// Abstract:
-//
-// A collection of utility macros.
-//
-
-#ifndef UMISC_H
-#define UMISC_H
-
-#define COM_METHOD HRESULT STDMETHODCALLTYPE
-
-inline HRESULT HrFromWin32(DWORD dwWin32Error)
-{
- return HRESULT_FROM_WIN32(dwWin32Error);
-}
-
-// Some helper #def's to safely Release, close & delete Objects under
-// failure conditions
-
-#define RELEASE(x) \
- do \
- { \
- if (x) \
- { \
- IUnknown *punk = x; \
- x = NULL; \
- punk->Release(); \
- } \
- } while (0)
-
-
-#include "debugmacros.h"
-//
-// Good for verifying params withing range.
-//
-#define IfFalseGo(expr, HR) IfFailGo((expr) ? S_OK : (HR))
-
-// ----------------------------------------------------------------------------
-// Validation macros
-// Note that the Win32 APIs like IsBadReadPtr are banned
-//
-#define IsValidReadPtr(ptr, type) ((ptr)!=NULL)
-
-#define IsValidWritePtr(ptr, type) ((ptr)!=NULL)
-
-#define IsValidReadBufferPtr(ptr, type, len) ((ptr)!=NULL)
-
-#define IsValidWriteBufferPtr(ptr, type, len) ((ptr)!=NULL)
-
-#define IsValidInterfacePtr(ptr, type) ((ptr)!=NULL)
-
-#define IsValidCodePtr(ptr) ((ptr)!=NULL)
-
-#define IsValidStringPtr(ptr) ((ptr)!=NULL)
-
-#define IsValidIID(iid) TRUE
-
-#define IsValidCLSID(clsid) TRUE
-
-#endif
{
kSymbolFormatNone, // No symbols available
kSymbolFormatPDB, // PDB symbol format - use diasymreader.dll
- kSymbolFormatILDB, // ILDB symbol format - use ildbsymlib
} SymbolFormat;
//
debug-pal
cordbdi
utilcodestaticnohost
- ildbsymlib
mdcompiler-dbi
mdruntime-dbi
mdruntimerw-dbi
comfloat_wks
corguids
gcinfo
- ildbsymlib
utilcode
v3binder
System.Globalization.Native-Static
CONFIG_DWORD_INFO(INTERNAL_DbgBreakOnSendBreakpoint, W("DbgBreakOnSendBreakpoint"), 0, "Allows an assert when sending a breakpoint to the right side")
CONFIG_DWORD_INFO(INTERNAL_DbgBreakOnSetIP, W("DbgBreakOnSetIP"), 0, "Allows an assert when setting the IP")
CONFIG_DWORD_INFO(INTERNAL_DbgCheckInt3, W("DbgCheckInt3"), 0, "Asserts if the debugger explicitly writes int3 instead of calling SetUnmanagedBreakpoint")
-RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgForcePDBSymbols, W("DbgForcePDBSymbols"), 0, "")
CONFIG_DWORD_INFO(INTERNAL_DbgDACAssertOnMismatch, W("DbgDACAssertOnMismatch"), 0, "Allows an assert when the mscordacwks and mscorwks dll versions don't match")
CONFIG_DWORD_INFO(INTERNAL_DbgDACEnableAssert, W("DbgDACEnableAssert"), 0, "Enables extra validity checking in DAC - assumes target isn't corrupt")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgDACSkipVerifyDlls, W("DbgDACSkipVerifyDlls"), 0, "Allows disabling the check to ensure mscordacwks and mscorwks dll versions match")
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-//*****************************************************************************
-// IldbSymLib.h
-//
-// ILDB debug symbols functions implemented in IldbSymLib.lib
-// Provides support for ILDB-format debug symbols using the same interfaces
-// that diasymreader.dll exposes for PDB symbols.
-//
-//*****************************************************************************
-#ifndef __IldbSymLib_h__
-#define __IldbSymLib_h__
-
-// Get the IClassFactory for one of the ILDB symbols CLSIDs
-STDAPI IldbSymbolsGetClassObject(REFCLSID rclsid, REFIID riid, void** ppvObject);
-
-// Create an inststance of an ILDB ISymUnmanagedReader, ISymUnmanagedWriter or ISymUnmanagedBinder
-STDAPI IldbSymbolsCreateInstance(REFCLSID rclsid, REFIID riid, void** ppvIUnknown);
-
-#endif // __IldbSymLib_h__
#include "../md/compiler/custattr.h"
#include "typekey.h"
#include "peimagelayout.inl"
-#include "ildbsymlib.h"
#if defined(PROFILING_SUPPORTED)
#include "profilermetadataemitvalidator.h"
{
// Memory allocated on LoaderHeap is zero-filled. Spot-check it here.
_ASSERTE(m_pBinder == NULL);
- _ASSERTE(m_symbolFormat == eSymbolFormatNone);
}
file->AddRef();
"reachable or needs to be reimplemented for CoreCLR!");
}
- if (this->GetInMemorySymbolStreamFormat() == eSymbolFormatILDB)
+ // We're going to be working with Windows PDB format symbols. Attempt to CoCreate the symbol binder.
+ // CoreCLR supports not having a symbol reader installed, so CoCreate searches the PATH env var
+ // and then tries coreclr dll location.
+ // On desktop, the framework installer is supposed to install diasymreader.dll as well
+ // and so this shouldn't happen.
+ hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, NATIVE_SYMBOL_READER_DLL, IID_ISymUnmanagedBinder, (void**)&pBinder, NULL);
+ if (FAILED(hr))
{
- // We've got in-memory ILDB symbols, create the ILDB symbol binder
- // Note that in this case, we must be very careful not to use diasymreader.dll
- // at all - we don't trust it, and shouldn't run any code in it
- IfFailThrow(IldbSymbolsCreateInstance(CLSID_CorSymBinder_SxS, IID_ISymUnmanagedBinder, (void**)&pBinder));
- }
- else
- {
- // We're going to be working with Windows PDB format symbols. Attempt to CoCreate the symbol binder.
- // CoreCLR supports not having a symbol reader installed, so CoCreate searches the PATH env var
- // and then tries coreclr dll location.
- // On desktop, the framework installer is supposed to install diasymreader.dll as well
- // and so this shouldn't happen.
- hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, NATIVE_SYMBOL_READER_DLL, IID_ISymUnmanagedBinder, (void**)&pBinder, NULL);
+ PathString symbolReaderPath;
+ hr = GetClrModuleDirectory(symbolReaderPath);
if (FAILED(hr))
{
- PathString symbolReaderPath;
- hr = GetClrModuleDirectory(symbolReaderPath);
- if (FAILED(hr))
- {
- RETURN (NULL);
- }
- symbolReaderPath.Append(NATIVE_SYMBOL_READER_DLL);
- hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, symbolReaderPath.GetUnicode(), IID_ISymUnmanagedBinder, (void**)&pBinder, NULL);
- if (FAILED(hr))
- {
- RETURN (NULL);
- }
+ RETURN (NULL);
+ }
+ symbolReaderPath.Append(NATIVE_SYMBOL_READER_DLL);
+ hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, symbolReaderPath.GetUnicode(), IID_ISymUnmanagedBinder, (void**)&pBinder, NULL);
+ if (FAILED(hr))
+ {
+ RETURN (NULL);
}
}
}
CONTRACTL_END;
- // If the module has symbols in-memory (eg. RefEmit) that are in ILDB
- // format, then there isn't any reason not to supply them. The reader
- // code is always available, and we trust it's security.
- if (this->GetInMemorySymbolStreamFormat() == eSymbolFormatILDB)
- {
- return TRUE;
- }
-
#ifdef DEBUGGING_SUPPORTED
if (!g_pDebugInterface)
{
// Make sure to set the symbol stream on the module before
// attempting to send UpdateModuleSyms messages up for it.
- SetInMemorySymbolStream(pStream, eSymbolFormatPDB);
+ SetInMemorySymbolStream(pStream);
// This can only be called when the module is being created. No-one should have
// tried to use the symbols yet, and so there should not be a reader.
{
BuildClassForModule();
}
-
- // Since the module is being modified, the in-memory symbol stream
- // (if any) has probably also been modified. If we support reading the symbols
- // then we need to commit the changes to the writer and flush any old readers
- // However if we don't support reading then we can skip this which will give
- // a substantial perf improvement. See DDB 671107.
- if(IsSymbolReadingEnabled())
- {
- CONSISTENCY_CHECK(IsReflection()); // this is only used for dynamic modules
- ISymUnmanagedWriter * pWriter = GetReflectionModule()->GetISymUnmanagedWriter();
- if (pWriter != NULL)
- {
- // Serialize with any concurrent reader creations
- // Specifically, if we started creating a reader on one thread, and then updated the
- // symbols on another thread, we need to wait until the initial reader creation has
- // completed and release it so we don't get stuck with a stale reader.
- // Also, if we commit to the stream while we're in the process of creating a reader,
- // the reader will get corrupted/incomplete data.
- // Note that we must also be in co-operative mode here to ensure the debugger helper
- // thread can't be simultaneously reading this stream while the process is synchronized
- // (code:Debugger::GetSymbolBytes)
- CrstHolder holder(&m_ISymUnmanagedReaderCrst);
-
- // Flush writes to the symbol store to the symbol stream
- // Note that we do this when finishing the addition of the class, instead of
- // on-demand in GetISymUnmanagedReader because the writer is not thread-safe.
- // Here, we're inside the lock of TypeBuilder.CreateType, and so it's safe to
- // manipulate the writer.
- SafeComHolderPreemp<ISymUnmanagedWriter3> pWriter3;
- HRESULT thr = pWriter->QueryInterface(IID_ISymUnmanagedWriter3, (void**)&pWriter3);
- CONSISTENCY_CHECK(SUCCEEDED(thr));
- if (SUCCEEDED(thr))
- {
- thr = pWriter3->Commit();
- if (SUCCEEDED(thr))
- {
- // Flush any cached symbol reader to ensure we pick up any new symbols
- ReleaseISymUnmanagedReader();
- }
- }
-
- // If either the QI or Commit failed
- if (FAILED(thr))
- {
- // The only way we expect this might fail is out-of-memory. In that
- // case we silently fail to update the symbol stream with new data, but
- // we leave the existing reader intact.
- CONSISTENCY_CHECK(thr==E_OUTOFMEMORY);
- }
- }
- }
}
//---------------------------------------------------------------------------
m_pInMemoryWriter = NULL;
m_sdataSection = NULL;
- m_pISymUnmanagedWriter = NULL;
m_pCreatingAssembly = NULL;
m_pCeeFileGen = NULL;
m_pDynamicMetadata = NULL;
- m_fSuppressMetadataCapture = false;
}
HRESULT STDMETHODCALLTYPE CreateICeeGen(REFIID riid, void **pCeeGen);
delete m_pInMemoryWriter;
- if (m_pISymUnmanagedWriter)
- {
- m_pISymUnmanagedWriter->Close();
- m_pISymUnmanagedWriter->Release();
- m_pISymUnmanagedWriter = NULL;
- }
-
if (m_pCeeFileGen)
m_pCeeFileGen->Release();
m_CrstLeafLock.Destroy();
}
-// Returns true iff metadata capturing is suppressed.
-//
-// Notes:
-// This is during the window after code:ReflectionModule.SuppressMetadataCapture and before
-// code:ReflectionModule.ResumeMetadataCapture.
-//
-// If metadata updates are suppressed, then class-load notifications should be suppressed too.
-bool ReflectionModule::IsMetadataCaptureSuppressed()
-{
- return m_fSuppressMetadataCapture;
-}
//
// Holder of changed value of MDUpdateMode via IMDInternalEmit::SetMDUpdateMode.
// Returns back the original value on release.
}
CONTRACTL_END;
- // If we've suppresed metadata capture, then skip this. We'll recapture when we enable it. This allows
- // for batching up capture.
// If a debugger is attached, then the CLR will still send ClassLoad notifications for dynamic modules,
// which mean we still need to keep the metadata available. This is the same as Whidbey.
// An alternative (and better) design would be to suppress ClassLoad notifications too, but then we'd
// need some way of sending a "catchup" notification to the debugger after we re-enable notifications.
- if (IsMetadataCaptureSuppressed() && !CORDebuggerAttached())
+ if (!CORDebuggerAttached())
{
return;
}
_ASSERTE(hr == S_OK);
}
-// Suppress the eager metadata serialization.
-//
-// Notes:
-// This casues code:ReflectionModule.CaptureModuleMetaDataToMemory to be a nop.
-// This is not nestable.
-// This exists purely for performance reasons.
-//
-// Don't call this directly. Use a SuppressMetadataCaptureHolder holder to ensure it's
-// balanced with code:ReflectionModule.ResumeMetadataCapture
-//
-// Types generating while eager metadata-capture is suppressed should not actually be executed until
-// after metadata capture is restored.
-void ReflectionModule::SuppressMetadataCapture()
-{
- LIMITED_METHOD_CONTRACT;
- // If this fires, then you probably missed a call to ResumeMetadataCapture.
- CONSISTENCY_CHECK_MSG(!m_fSuppressMetadataCapture, "SuppressMetadataCapture is not nestable");
- m_fSuppressMetadataCapture = true;
-}
-
-// Resumes eager metadata serialization.
-//
-// Notes:
-// This casues code:ReflectionModule.CaptureModuleMetaDataToMemory to resume eagerly serializing metadata.
-// This must be called after code:ReflectionModule.SuppressMetadataCapture.
-//
-void ReflectionModule::ResumeMetadataCapture()
-{
- WRAPPER_NO_CONTRACT;
- _ASSERTE(m_fSuppressMetadataCapture);
- m_fSuppressMetadataCapture = false;
-
- CaptureModuleMetaDataToMemory();
-}
-
#endif // !CROSSGEN_COMPILE
#endif // !DACCESS_COMPILE
typedef DPTR(DynamicILBlobTable) PTR_DynamicILBlobTable;
-// ESymbolFormat specified the format used by a symbol stream
-typedef enum
-{
- eSymbolFormatNone, /* symbol format to use not yet determined */
- eSymbolFormatPDB, /* PDB format from diasymreader.dll - only safe for trusted scenarios */
- eSymbolFormatILDB /* ILDB format from ildbsymbols.dll */
-}ESymbolFormat;
-
-
#ifdef FEATURE_COMINTEROP
//---------------------------------------------------------------------------------------
// Debugger may retrieve this from out-of-process.
PTR_CGrowableStream m_pIStreamSym;
- // Format the above stream is in (if any)
- ESymbolFormat m_symbolFormat;
-
// For protecting additions to the heap
CrstExplicitInit m_LookupTableCrst;
// Get the in-memory symbol stream for this module, if any.
// If none, this will return null. This is used by modules loaded in-memory (eg. from a byte-array)
- // and by dynamic modules. Callers that actually do anything with the return value will almost
- // certainly want to check GetInMemorySymbolStreamFormat to know how to interpret the bytes
- // in the stream.
+ // and by dynamic modules.
PTR_CGrowableStream GetInMemorySymbolStream()
{
LIMITED_METHOD_CONTRACT;
SUPPORTS_DAC;
- // Symbol format should be "none" if-and-only-if our stream is null
- // If this fails, it may mean somebody is trying to examine this module after
- // code:Module::Destruct has been called.
- _ASSERTE( (m_symbolFormat == eSymbolFormatNone) == (m_pIStreamSym == NULL) );
-
return m_pIStreamSym;
}
- // Get the format of the in-memory symbol stream for this module, or
- // eSymbolFormatNone if no in-memory symbols.
- ESymbolFormat GetInMemorySymbolStreamFormat()
- {
- LIMITED_METHOD_CONTRACT;
- SUPPORTS_DAC;
-
- // Symbol format should be "none" if-and-only-if our stream is null
- // If this fails, it may mean somebody is trying to examine this module after
- // code:Module::Destruct has been called.
- _ASSERTE( (m_symbolFormat == eSymbolFormatNone) == (m_pIStreamSym == NULL) );
-
- return m_symbolFormat;
- }
-
#ifndef DACCESS_COMPILE
// Set the in-memory stream for debug symbols
// This must only be called when there is no existing stream.
// This takes an AddRef on the supplied stream.
- void SetInMemorySymbolStream(CGrowableStream *pStream, ESymbolFormat symbolFormat)
+ void SetInMemorySymbolStream(CGrowableStream *pStream)
{
LIMITED_METHOD_CONTRACT;
// Must have provided valid stream data
CONSISTENCY_CHECK(pStream != NULL);
- CONSISTENCY_CHECK(symbolFormat != eSymbolFormatNone);
// we expect set to only be called once
CONSISTENCY_CHECK(m_pIStreamSym == NULL);
- CONSISTENCY_CHECK(m_symbolFormat == eSymbolFormatNone);
- m_symbolFormat = symbolFormat;
m_pIStreamSym = pStream;
m_pIStreamSym->AddRef();
}
{
m_pIStreamSym->Release();
m_pIStreamSym = NULL;
- // We could set m_symbolFormat to eSymbolFormatNone to be consistent with not having
- // a stream, but no-one should be trying to look at it after destruct time, so it's
- // better to leave it inconsistent and get an ASSERT if someone tries to examine the
- // module's sybmol stream after the module was destructed.
}
}
ICeeGenInternal * m_pCeeFileGen;
private:
Assembly *m_pCreatingAssembly;
- ISymUnmanagedWriter *m_pISymUnmanagedWriter;
RefClassWriter *m_pInMemoryWriter;
bool m_fSuppressMetadataCapture;
#if !defined DACCESS_COMPILE && !defined CROSSGEN_COMPILE
- // Returns true iff metadata capturing is suppressed
- bool IsMetadataCaptureSuppressed();
-
- // Toggle whether CaptureModuleMetaDataToMemory should do antyhing. This can be an important perf win to
- // allow batching up metadata capture. Use SuppressMetadataCaptureHolder to ensure they're balanced.
- // These are not nestable.
- void SuppressMetadataCapture();
- void ResumeMetadataCapture();
-
- // Glue functions for holders.
- static void SuppressCaptureWrapper(ReflectionModule * pModule)
- {
- pModule->SuppressMetadataCapture();
- }
- static void ResumeCaptureWrapper(ReflectionModule * pModule)
- {
- pModule->ResumeMetadataCapture();
- }
-
ReflectionModule(Assembly *pAssembly, mdFile token, PEFile *pFile);
#endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE
return m_pInMemoryWriter;
}
- ISymUnmanagedWriter *GetISymUnmanagedWriter()
- {
- LIMITED_METHOD_CONTRACT;
- return m_pISymUnmanagedWriter;
- }
-
- // Note: we now use the same writer instance for the life of a module,
- // so there should no longer be any need for the extra indirection.
- ISymUnmanagedWriter **GetISymUnmanagedWriterAddr()
- {
- LIMITED_METHOD_CONTRACT;
-
- // We must have setup the writer before trying to get
- // the address for it. Any calls to this before a
- // SetISymUnmanagedWriter are very incorrect.
- _ASSERTE(m_pISymUnmanagedWriter != NULL);
-
- return &m_pISymUnmanagedWriter;
- }
-
-#ifndef DACCESS_COMPILE
-#ifndef CROSSGEN_COMPILE
-
- typedef Wrapper<
- ReflectionModule*,
- ReflectionModule::SuppressCaptureWrapper,
- ReflectionModule::ResumeCaptureWrapper> SuppressMetadataCaptureHolder;
-#endif // !CROSSGEN_COMPILE
-
- HRESULT SetISymUnmanagedWriter(ISymUnmanagedWriter *pWriter)
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- INJECT_FAULT(return E_OUTOFMEMORY;);
- }
- CONTRACTL_END
-
-
- // Setting to NULL when we've never set a writer before should
- // do nothing.
- if ((pWriter == NULL) && (m_pISymUnmanagedWriter == NULL))
- return S_OK;
-
- if (m_pISymUnmanagedWriter != NULL)
- {
- // We shouldn't be trying to replace an existing writer anymore
- _ASSERTE( pWriter == NULL );
-
- m_pISymUnmanagedWriter->Release();
- }
-
- m_pISymUnmanagedWriter = pWriter;
- return S_OK;
- }
-#endif // !DACCESS_COMPILE
-
// Eagerly serialize the metadata to a buffer that the debugger can retrieve.
void CaptureModuleMetaDataToMemory();
};
#include <cor.h>
#include "typeparse.h"
#include "typekey.h"
-#include "ildbsymlib.h"
//**************************************************