1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
6 #include "fastserializer.h"
7 #include "profilerdiagnosticprotocolhelper.h"
8 #include "diagnosticsipc.h"
9 #include "diagnosticsprotocol.h"
11 #if defined(FEATURE_PERFTRACING) && defined(FEATURE_PROFAPI_ATTACH_DETACH) && !defined(DACCESS_COMPILE)
12 #include "profilinghelper.h"
13 #include "profilinghelper.inl"
15 void ProfilerDiagnosticProtocolHelper::HandleIpcMessage(DiagnosticsIpc::IpcMessage& message, IpcStream* pStream)
22 PRECONDITION(pStream != nullptr);
26 switch ((ProfilerCommandId)message.GetHeader().CommandId)
28 case ProfilerCommandId::AttachProfiler:
29 ProfilerDiagnosticProtocolHelper::AttachProfiler(message, pStream);
33 STRESS_LOG1(LF_DIAGNOSTICS_PORT, LL_WARNING, "Received unknown request type (%d)\n", message.GetHeader().CommandSet);
34 DiagnosticsIpc::IpcMessage::SendErrorMessage(pStream, CORDIAGIPC_E_UNKNOWN_COMMAND);
40 const AttachProfilerCommandPayload* AttachProfilerCommandPayload::TryParse(BYTE* lpBuffer, uint16_t& BufferSize)
47 PRECONDITION(lpBuffer != nullptr);
51 AttachProfilerCommandPayload* payload = new (nothrow) AttachProfilerCommandPayload;
52 if (payload == nullptr)
58 payload->incomingBuffer = lpBuffer;
59 uint8_t* pBufferCursor = payload->incomingBuffer;
60 uint32_t bufferLen = BufferSize;
61 if (!::TryParse(pBufferCursor, bufferLen, payload->dwAttachTimeout) ||
62 !::TryParse(pBufferCursor, bufferLen, payload->profilerGuid) ||
63 !TryParseString(pBufferCursor, bufferLen, payload->pwszProfilerPath) ||
64 !::TryParse(pBufferCursor, bufferLen, payload->cbClientData) ||
65 !(bufferLen <= payload->cbClientData))
71 payload->pClientData = pBufferCursor;
76 void ProfilerDiagnosticProtocolHelper::AttachProfiler(DiagnosticsIpc::IpcMessage& message, IpcStream *pStream)
83 PRECONDITION(pStream != nullptr);
87 if (pStream == nullptr)
93 NewHolder<const AttachProfilerCommandPayload> payload = message.TryParsePayload<AttachProfilerCommandPayload>();
94 if (payload == nullptr)
96 hr = CORDIAGIPC_E_BAD_ENCODING;
100 if (!g_profControlBlock.fProfControlBlockInitialized)
102 hr = CORPROF_E_RUNTIME_UNINITIALIZED;
106 // Certain actions are only allowable during attach, and this flag is how we track it.
107 ClrFlsSetThreadType(ThreadType_ProfAPI_Attach);
111 hr = ProfilingAPIUtility::LoadProfilerForAttach(&payload->profilerGuid,
112 payload->pwszProfilerPath,
113 payload->pClientData,
114 payload->cbClientData,
115 payload->dwAttachTimeout);
117 EX_CATCH_HRESULT(hr);
119 // Clear the flag so this thread isn't permanently marked as the attach thread.
120 ClrFlsClearThreadType(ThreadType_ProfAPI_Attach);
125 DiagnosticsIpc::IpcMessage::SendErrorMessage(pStream, hr);
129 DiagnosticsIpc::IpcMessage profilerAttachResponse;
130 if (profilerAttachResponse.Initialize(DiagnosticsIpc::GenericSuccessHeader, hr))
131 profilerAttachResponse.Send(pStream);
136 #endif // defined(FEATURE_PERFTRACING) && defined(FEATURE_PROFAPI_ATTACH_DETACH) && !defined(DACCESS_COMPILE)