summaryrefslogtreecommitdiff
path: root/src/binder/debuglog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/binder/debuglog.cpp')
-rw-r--r--src/binder/debuglog.cpp416
1 files changed, 416 insertions, 0 deletions
diff --git a/src/binder/debuglog.cpp b/src/binder/debuglog.cpp
new file mode 100644
index 0000000000..1170c0eb8c
--- /dev/null
+++ b/src/binder/debuglog.cpp
@@ -0,0 +1,416 @@
+// 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.
+// ============================================================
+//
+// DebugLog.cpp
+//
+
+
+//
+// Implements the DebugLog class
+//
+// ============================================================
+
+#if defined(BINDER_DEBUG_LOG)
+
+#include "debuglog.hpp"
+#include "assemblyname.hpp"
+#include "utils.hpp"
+#include "variables.hpp"
+
+#include "ex.h"
+
+namespace BINDER_SPACE
+{
+ namespace
+ {
+ void GetStringFromHR(HRESULT hr,
+ SString &info)
+ {
+ switch(hr)
+ {
+ case S_OK:
+ info.Append(L"S_OK");
+ break;
+ case S_FALSE:
+ info.Append(L"S_FALSE");
+ break;
+ case E_FAIL:
+ info.Append(L"E_FAIL");
+ break;
+ case __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND):
+ info.Append(L"HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)");
+ break;
+ case __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER):
+ info.Append(L"HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)");
+ break;
+ case FUSION_E_REF_DEF_MISMATCH:
+ info.Append(L"FUSION_E_REF_DEF_MISMATCH");
+ break;
+ case FUSION_E_CODE_DOWNLOAD_DISABLED:
+ info.Append(L"FUSION_E_CODE_DOWNLOAD_DISABLED");
+ break;
+ default:
+ info.AppendPrintf(L"%p", hr);
+ break;
+ }
+ }
+
+ HRESULT GetLogFilePath(PathString &logFileDir,
+ PathString &logFilePath)
+ {
+ HRESULT hr = S_OK;
+
+ BOOL fFileExists = TRUE;
+
+ do
+ {
+ LARGE_INTEGER kCount1;
+ LARGE_INTEGER kCount2;
+
+ logFilePath.Clear();
+
+ if (!QueryPerformanceCounter(&kCount1))
+ {
+ hr = HRESULT_FROM_GetLastError();
+ }
+ else if(!QueryPerformanceCounter(&kCount2))
+ {
+ hr = HRESULT_FROM_GetLastError();
+ }
+ else
+ {
+ logFilePath.Printf(L"%s\\Log_%u%u_%u%u.tmp",
+ logFileDir.GetUnicode(),
+ static_cast<UINT32>(kCount1.u.LowPart),
+ kCount1.u.HighPart,
+ static_cast<UINT32>(kCount2.u.LowPart),
+ kCount2.u.HighPart);
+
+ PlatformPath(logFilePath);
+ }
+
+ fFileExists = (FileOrDirectoryExists(logFilePath) == S_OK);
+ }
+ while (fFileExists == TRUE);
+
+ return hr;
+ }
+
+ HRESULT WriteToFile(HANDLE hFile,
+ const BYTE *pbBuffer,
+ DWORD dwcbBuffer)
+ {
+ HRESULT hr = S_OK;
+ DWORD dwNumberOfBytesWritten = 0;
+
+ while ((dwcbBuffer != 0) && (dwNumberOfBytesWritten < dwcbBuffer))
+ {
+ if (WriteFile(hFile, pbBuffer, dwcbBuffer, &dwNumberOfBytesWritten, NULL))
+ {
+ dwcbBuffer -= dwNumberOfBytesWritten;
+ pbBuffer += dwNumberOfBytesWritten;
+ }
+ else
+ {
+ hr = HRESULT_FROM_GetLastError();
+ goto Exit;
+ }
+ }
+
+ Exit:
+ return hr;
+ }
+ };
+
+ /* static */
+ HRESULT DebugLog::Startup()
+ {
+ HRESULT hr = S_OK;
+
+ PathString logFileDir;
+ PathString logFilePath;
+
+ REGUTIL::CORConfigLevel kCorConfigLevel =
+ static_cast<REGUTIL::CORConfigLevel>(REGUTIL::COR_CONFIG_ENV |
+ REGUTIL::COR_CONFIG_FUSION);
+ NewArrayHolder<WCHAR> pwzLogDirectory = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_CoreClrBinderLog);
+
+
+ g_BinderVariables->m_logCS = ClrCreateCriticalSection(CrstCoreCLRBinderLog, CRST_REENTRANCY);
+ if (!g_BinderVariables->m_logCS)
+ {
+ IF_FAIL_GO(E_OUTOFMEMORY);
+ }
+
+
+ if (pwzLogDirectory == NULL)
+ {
+ goto Exit;
+ }
+
+ logFileDir.Set(pwzLogDirectory);
+
+ if (WszCreateDirectory(logFileDir.GetUnicode(), NULL) ||
+ ((hr = HRESULT_FROM_GetLastError()) == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)))
+ {
+ hr = S_OK;
+ }
+
+ IF_FAIL_GO(GetLogFilePath(logFileDir, logFilePath));
+
+ g_BinderVariables->m_hDebugLogFile = WszCreateFile(logFilePath.GetUnicode(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (g_BinderVariables->m_hDebugLogFile == INVALID_HANDLE_VALUE)
+ {
+ IF_FAIL_GO(E_FAIL);
+ }
+ Exit:
+ return hr;
+ }
+
+ // This is not multi-thread aware by any means. That said, neither is any of this logging mechanism.
+ static int s_scopeLevel = 0;
+ static const ANSI s_szScopeIndent[3] = " ";
+
+ /* static */
+ void DebugLog::Enter(WCHAR *pwzScope)
+ {
+ HRESULT hr = S_OK;
+
+ EX_TRY
+ {
+ PathString info;
+
+ info.Append(pwzScope);
+ info.Append(L": Enter");
+ Log(info);
+ }
+ EX_CATCH_HRESULT(hr);
+
+ s_scopeLevel++;
+ }
+
+ /* static */
+ void DebugLog::Leave(WCHAR *pwzScope)
+ {
+ HRESULT hr = S_OK;
+
+ s_scopeLevel--;
+
+ EX_TRY
+ {
+ PathString info;
+
+ info.Append(pwzScope);
+ info.Append(L": Leave(void)");
+ Log(info);
+ }
+ EX_CATCH_HRESULT(hr);
+ }
+
+ /* static */
+ void DebugLog::LeaveHR(WCHAR *pwzScope,
+ HRESULT hrLog)
+ {
+ HRESULT hr = S_OK;
+
+ s_scopeLevel--;
+
+ EX_TRY
+ {
+ PathString info;
+
+ info.Append(pwzScope);
+ info.Append(L": Leave(hr=");
+ GetStringFromHR(hrLog, info);
+ info.Append(L")");
+
+ Log(info);
+ }
+ EX_CATCH_HRESULT(hr);
+ }
+
+ /* static */
+ void DebugLog::LeaveBool(WCHAR *pwzScope,
+ BOOL fResult)
+ {
+ HRESULT hr = S_OK;
+
+ s_scopeLevel--;
+
+ EX_TRY
+ {
+ PathString info;
+
+ info.Append(pwzScope);
+ info.Append(L": Leave(fResult=");
+ info.Append(fResult ? L"TRUE)" : L"FALSE)");
+ Log(info);
+ }
+ EX_CATCH_HRESULT(hr);
+ }
+
+ /* static */
+ void DebugLog::Log(WCHAR *pwzComment)
+ {
+ HRESULT hr = S_OK;
+
+ EX_TRY
+ {
+ PathString info;
+
+ info.Append(pwzComment);
+ Log(info);
+ }
+ EX_CATCH_HRESULT(hr);
+ }
+
+ /* static */
+ void DebugLog::Log(WCHAR *pwzComment,
+ SString &value)
+ {
+ HRESULT hr = S_OK;
+
+ EX_TRY
+ {
+ PathString info;
+
+ info.Append(pwzComment);
+ info.Append(L" = '");
+ info.Append(value);
+ info.Append(L"'");
+
+ Log(info);
+ }
+ EX_CATCH_HRESULT(hr);
+ }
+
+ /* static */
+ void DebugLog::Log(WCHAR *pwzComment,
+ const WCHAR *value)
+ {
+ HRESULT hr = S_OK;
+
+ EX_TRY
+ {
+ PathString info;
+
+ info.Append(pwzComment);
+ info.Append(L" = '");
+ info.Append(value);
+ info.Append(L"'");
+
+ Log(info);
+ }
+ EX_CATCH_HRESULT(hr)
+ }
+
+ /* static */
+ void DebugLog::Log(WCHAR *pwzComment,
+ HRESULT hrLog)
+ {
+ HRESULT hr = S_OK;
+
+ EX_TRY
+ {
+ PathString info;
+
+ info.Append(pwzComment);
+ info.Append(L" = ");
+ GetStringFromHR(hrLog, info);
+
+ Log(info);
+ }
+ EX_CATCH_HRESULT(hr);
+ }
+
+ /* static */
+ void DebugLog::Log(WCHAR *pwzComment,
+ AssemblyName *pAssemblyName)
+ {
+ EX_TRY
+ {
+ PathString assemblyDisplayName;
+ PathString info;
+
+ if (pAssemblyName != NULL)
+ {
+ pAssemblyName->GetDisplayName(assemblyDisplayName,
+ AssemblyName::INCLUDE_VERSION |
+ AssemblyName::INCLUDE_ARCHITECTURE |
+ AssemblyName::INCLUDE_RETARGETABLE);
+ }
+ else
+ {
+ assemblyDisplayName.Set(L"<NULL>");
+ }
+
+ info.Printf(L"(%d):", static_cast<INT32>(assemblyDisplayName.GetCount()));
+ info.Append(assemblyDisplayName);
+
+ Log(pwzComment, info);
+ }
+ EX_CATCH
+ {
+ Log(L"<AssemblyDisplayName: Failure>");
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+ }
+
+ /* static */
+ void DebugLog::Log(WCHAR *pwzComment,
+ void *pData)
+ {
+ HRESULT hr = S_OK;
+
+ EX_TRY
+ {
+ PathString info;
+
+ info.Append(pwzComment);
+ info.AppendPrintf(L" = %p", pData);
+ Log(info);
+ }
+ EX_CATCH_HRESULT(hr);
+ }
+
+ /* static */
+ void DebugLog::Log(SString &info)
+ {
+ HRESULT hr = S_OK;
+
+ StackScratchBuffer scratchBuffer;
+ const BYTE *pbRawBuffer = reinterpret_cast<const BYTE *>(info.GetANSI(scratchBuffer));
+ DWORD dwcbRawBuffer = static_cast<DWORD>(info.GetCount());
+ // Work around SString issue
+ const ANSI ansiCRLF[] = { 0x0d, 0x0a };
+ DWORD dwcbAnsiCRLF = 2 * sizeof(ANSI);
+ s_scopeLevel;
+ for (int iScope = 0; iScope < s_scopeLevel; iScope++)
+ {
+ IF_FAIL_GO(WriteToFile(g_BinderVariables->m_hDebugLogFile, reinterpret_cast<const BYTE *>(&s_szScopeIndent[0]), sizeof(s_szScopeIndent)));
+ }
+ IF_FAIL_GO(WriteToFile(g_BinderVariables->m_hDebugLogFile, pbRawBuffer, dwcbRawBuffer));
+ IF_FAIL_GO(WriteToFile(g_BinderVariables->m_hDebugLogFile,
+ reinterpret_cast<const BYTE *>(ansiCRLF),
+ dwcbAnsiCRLF));
+ // Don't cache anything
+ if (!FlushFileBuffers(g_BinderVariables->m_hDebugLogFile))
+ {
+ WszOutputDebugString(L"DebugLog::Log(info): FlushFileBuffers failed!\n");
+ }
+
+ Exit:
+ return;
+ }
+};
+
+#endif