summaryrefslogtreecommitdiff
path: root/src/vm/sourceline.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/sourceline.cpp')
-rw-r--r--src/vm/sourceline.cpp334
1 files changed, 334 insertions, 0 deletions
diff --git a/src/vm/sourceline.cpp b/src/vm/sourceline.cpp
new file mode 100644
index 0000000000..63d2177625
--- /dev/null
+++ b/src/vm/sourceline.cpp
@@ -0,0 +1,334 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+#include "common.h"
+
+#include "sourceline.h"
+
+//////////////////////////////////////////////////////////////////
+
+#ifdef ENABLE_DIAGNOSTIC_SYMBOL_READING
+
+class CCallback : public IDiaLoadCallback
+{
+ int m_nRefCount;
+public:
+ CCallback() {
+ CONTRACTL
+ {
+ MODE_ANY;
+ GC_NOTRIGGER;
+ NOTHROW;
+ }CONTRACTL_END;
+
+ m_nRefCount = 0;
+ }
+
+ //IUnknown
+ ULONG STDMETHODCALLTYPE AddRef() {
+ LIMITED_METHOD_CONTRACT;
+ m_nRefCount++;
+ return m_nRefCount;
+ }
+
+ ULONG STDMETHODCALLTYPE Release() {
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ SO_TOLERANT;
+ } CONTRACTL_END;
+
+ BEGIN_SO_INTOLERANT_CODE(GetThread());
+ if ( (--m_nRefCount) == 0 )
+ delete this;
+ END_SO_INTOLERANT_CODE;
+
+ return m_nRefCount;
+ }
+
+ HRESULT STDMETHODCALLTYPE QueryInterface( REFIID rid, void **ppUnk ) {
+ WRAPPER_NO_CONTRACT;
+ STATIC_CONTRACT_SO_TOLERANT;
+ if ( ppUnk == NULL ) {
+ return E_INVALIDARG;
+ }
+ if (rid == __uuidof( IDiaLoadCallback ) )
+ *ppUnk = (IDiaLoadCallback *)this;
+ else if (rid == __uuidof( IDiaLoadCallback ) )
+ *ppUnk = (IDiaLoadCallback *)this;
+ else if (rid == __uuidof( IUnknown ) )
+ *ppUnk = (IUnknown *)this;
+ else
+ *ppUnk = NULL;
+
+ if ( *ppUnk != NULL ) {
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+ }
+
+ HRESULT STDMETHODCALLTYPE NotifyDebugDir(
+ BOOL fExecutable,
+ DWORD cbData,
+ BYTE data[]) // really a const struct _IMAGE_DEBUG_DIRECTORY *
+ {
+ LIMITED_METHOD_CONTRACT;
+ STATIC_CONTRACT_SO_TOLERANT;
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE NotifyOpenDBG(
+ LPCOLESTR dbgPath,
+ HRESULT resultCode)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE NotifyOpenPDB(
+ LPCOLESTR pdbPath,
+ HRESULT resultCode)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE RestrictRegistryAccess() // return hr != S_OK to prevent querying the registry for symbol search paths
+ {
+ LIMITED_METHOD_CONTRACT;
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE RestrictSymbolServerAccess() // return hr != S_OK to prevent accessing a symbol server
+ {
+ LIMITED_METHOD_CONTRACT;
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE RestrictOriginalPathAccess() // return hr != S_OK to prevent querying the registry for symbol search paths
+ {
+ LIMITED_METHOD_CONTRACT;
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE RestrictReferencePathAccess() // return hr != S_OK to prevent accessing a symbol server
+ {
+ LIMITED_METHOD_CONTRACT;
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE RestrictDBGAccess()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return S_OK;
+ }
+};
+
+//////////////////////////////////////////////////////////////////
+
+bool SourceLine::LoadDataFromPdb( __in_z LPWSTR wszFilename )
+{
+ CONTRACTL {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ } CONTRACTL_END;
+
+ HRESULT hResult;
+
+// CComPtr(IDiaDataSource) pDataSource;
+
+ hResult = CoInitialize(NULL);
+
+ if (FAILED(hResult)){
+ return FALSE;
+ }
+
+ // Obtain Access To The Provider
+ hResult = CoCreateInstance(CLSID_DiaSource,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IDiaDataSource,
+ (void **) &pSource_);
+
+ if (FAILED(hResult)){
+ return FALSE;
+ }
+
+ CCallback callback;
+ callback.AddRef();
+
+ if ( FAILED( pSource_->loadDataFromPdb( wszFilename ) )
+ && FAILED( pSource_->loadDataForExe( wszFilename, W("symsrv*symsrv.dll*\\\\symbols\\\\symbols"), &callback ) ) )
+ return FALSE;
+ if ( FAILED( pSource_->openSession(&pSession_) ) )
+ return FALSE;
+ if ( FAILED( pSession_->get_globalScope(&pGlobal_) ) )
+ return FALSE;
+
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////
+
+SourceLine::SourceLine( __in_z LPWSTR pszFileName )
+{
+ WRAPPER_NO_CONTRACT;
+ if (LoadDataFromPdb(pszFileName)) {
+ initialized_ = true;
+ }
+ else{
+ initialized_ = false;
+ }
+}
+
+//////////////////////////////////////////////////////////////////
+
+HRESULT SourceLine::GetSourceLine( DWORD dwFunctionToken, DWORD dwOffset, __out_ecount(dwFileNameMaxLen) __out_z LPWSTR pszFileName, DWORD dwFileNameMaxLen, PDWORD pdwLineNumber )
+{
+ CONTRACTL {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ } CONTRACTL_END;
+
+ _ASSERTE(initialized_);
+
+ CComPtr(IDiaSymbol) pSymbol;
+ HRESULT hResult = pSession_->findSymbolByToken(dwFunctionToken, SymTagFunction, &pSymbol);
+
+ if( SUCCEEDED(hResult) && pSymbol != NULL) {
+
+ ULONGLONG length;
+ pSymbol->get_length(&length);
+
+ DWORD rva;
+ CComPtr(IDiaEnumLineNumbers) pLines;
+
+ if(SUCCEEDED(pSymbol->get_relativeVirtualAddress(&rva))) {
+
+ DWORD initialOffset;
+ pSymbol->get_addressOffset(&initialOffset);
+
+ DWORD isect;
+ pSymbol->get_addressSection(&isect);
+
+ hResult = pSession_->findLinesByAddr(isect, initialOffset+dwOffset, 1, &pLines);
+ if( SUCCEEDED(hResult) ){
+
+ CComPtr(IDiaLineNumber) pLine;
+
+ hResult = pLines->Item( 0, &pLine );
+
+ if(SUCCEEDED(hResult)){
+
+ pLine->get_lineNumber(pdwLineNumber);
+
+ CComPtr(IDiaSourceFile) pSourceFile;
+ pLine->get_sourceFile( &pSourceFile );
+
+ BSTR sourceName;
+ pSourceFile->get_fileName( &sourceName );
+
+ wcsncpy_s( pszFileName, dwFileNameMaxLen, sourceName, dwFileNameMaxLen );
+ }
+ }
+ }
+ }
+
+ return hResult;
+}
+
+//////////////////////////////////////////////////////////////////
+
+HRESULT SourceLine::GetLocalName( DWORD dwFunctionToken, DWORD dwSlot, __out_ecount(dwNameMaxLen) __out_z LPWSTR pszName, DWORD dwNameMaxLen )
+{
+ CONTRACTL {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ } CONTRACTL_END;
+
+ CComPtr(IDiaSymbol) pSymbol;
+ HRESULT hResult = pSession_->findSymbolByToken(dwFunctionToken, SymTagFunction, &pSymbol);
+
+ if( SUCCEEDED(hResult) && pSymbol != NULL ) {
+
+ ULONGLONG length;
+ pSymbol->get_length(&length);
+
+ DWORD rva;
+// CComPtr(IDiaEnumLineNumbers) pLines;
+
+ hResult = pSymbol->get_relativeVirtualAddress(&rva);
+
+ if(SUCCEEDED(hResult)) {
+
+ CComPtr( IDiaSymbol ) pBlock;
+ hResult = pSession_->findSymbolByRVA( rva, SymTagBlock, &pBlock );
+
+ if( SUCCEEDED(hResult) && pBlock != NULL ) {
+
+ ULONG celt = 0;
+
+ CComPtr(IDiaSymbol) pLocalSymbol = NULL;
+ CComPtr( IDiaEnumSymbols ) pEnum;
+ hResult = pBlock->findChildren( SymTagData, NULL, nsNone, &pEnum );
+
+ if( SUCCEEDED(hResult) ) {
+
+ //
+ // Find function local by slot
+ //
+ while (SUCCEEDED(hResult = pEnum->Next(1, &pLocalSymbol, &celt)) && celt == 1) {
+
+ DWORD dwThisSlot;
+ pLocalSymbol->get_slot( &dwThisSlot );
+
+ if( dwThisSlot == dwSlot ) {
+
+ BSTR name = NULL;
+ hResult = pLocalSymbol->get_name(&name);
+
+ wcsncpy_s( pszName, dwNameMaxLen, name, _TRUNCATE );
+
+ return S_OK;
+ }
+
+ pLocalSymbol = 0;
+ }
+ }
+ }
+ }
+ }
+
+ return hResult;
+}
+
+#else // !ENABLE_DIAGNOSTIC_SYMBOL_READING
+SourceLine::SourceLine( __in_z LPWSTR pszFileName )
+{
+ LIMITED_METHOD_CONTRACT;
+ initialized_ = false;
+}
+
+HRESULT SourceLine::GetSourceLine( DWORD dwFunctionToken, DWORD dwOffset, __out_ecount(dwFileNameMaxLen) __out_z LPWSTR pszFileName, DWORD dwFileNameMaxLen, PDWORD pdwLineNumber )
+{
+ LIMITED_METHOD_CONTRACT;
+ return E_NOTIMPL;
+}
+
+HRESULT SourceLine::GetLocalName( DWORD dwFunctionToken, DWORD dwSlot, __out_ecount(dwNameMaxLen) __out_z LPWSTR pszName, DWORD dwNameMaxLen )
+{
+ LIMITED_METHOD_CONTRACT;
+ return E_NOTIMPL;
+}
+#endif // ENABLE_DIAGNOSTIC_SYMBOL_READING
+