summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOded Hanson <odhanson@microsoft.com>2018-12-12 02:42:17 +0200
committerJan Vorlicek <janvorli@microsoft.com>2018-12-12 01:42:17 +0100
commit5b687cf51745790ff02c2de3f9f992ddc94bfae1 (patch)
tree0e6b24b35e3482f6e0244cf2f724331c807faef6
parentfc90b973bf806410b836541a3d0af2293152c787 (diff)
downloadcoreclr-5b687cf51745790ff02c2de3f9f992ddc94bfae1.tar.gz
coreclr-5b687cf51745790ff02c2de3f9f992ddc94bfae1.tar.bz2
coreclr-5b687cf51745790ff02c2de3f9f992ddc94bfae1.zip
Added support for debugging a sandboxed app on Mac (#21068)
* Fixed bug in StackString where the size is not initialized correctly to STACK_COUNT * Added CharString and WCharString template classes and a generic CharStringFromLPCWSTR method * Added support for debugging a sandboxed app on Mac This change fixes the usage of IPC while debugging while running in a sandbox. When running in a sandbox, the temporary folder for each process will be different. Thus the pipes being created in TwoWayPipe right now would be created in different directories in the debugger process and the process being debugged. This change configures the folder to be used based on the application group ID that the sandboxed app belongs to. For the same reasons, the names sempahores being used to synchronize the debugger attach need to be prefixed with the application group ID. This change was abit more involved since the name of the semaphore is limited to 31 characters, so we had to encode the semaphore names differently to make them shorter. Last, new APIs to the debugger shim were added to support this new feature. This change only handles the runtime side and the dbgshim. An additional change to vsdbg needs to be done to use the new APIs. fixes #21066 * Fixed build breaks on non Mac Unix platforms * Fixed usage of gApplicationGroupId in non apple environments * Fixed bug in semaphore names * Got rid of usage of StackString * Made PAL_GetApplicationGroupId Apple specific * Added comment about pragma pack * Fixed comment * Added exported symbols * Duplicated applicationGroupId so it can be used from another thread during register complete callback * Renamed BitNum2ByteNum to GetExtraEncodedAreaSize to make intent clearer * Fixed nit comments * Removed redundant changes in StackString * Fixed windows build break * Fixed compilation switch from __APPLE to __APPLE__ * Added missing exports
-rw-r--r--src/debug/debug-pal/CMakeLists.txt2
-rw-r--r--src/debug/debug-pal/unix/processdescriptor.cpp21
-rw-r--r--src/debug/debug-pal/unix/twowaypipe.cpp14
-rw-r--r--src/debug/debug-pal/win/processdescriptor.cpp14
-rw-r--r--src/debug/debug-pal/win/twowaypipe.cpp12
-rw-r--r--src/debug/di/cordb.cpp38
-rw-r--r--src/debug/di/dbgtransportmanager.cpp9
-rw-r--r--src/debug/di/dbgtransportmanager.h11
-rw-r--r--src/debug/di/dbgtransportpipeline.cpp12
-rw-r--r--src/debug/di/eventchannel.h2
-rw-r--r--src/debug/di/eventredirectionpipeline.cpp6
-rw-r--r--src/debug/di/eventredirectionpipeline.h2
-rw-r--r--src/debug/di/localeventchannel.cpp2
-rw-r--r--src/debug/di/nativepipeline.h2
-rw-r--r--src/debug/di/process.cpp50
-rw-r--r--src/debug/di/remoteeventchannel.cpp4
-rw-r--r--src/debug/di/rsmain.cpp61
-rw-r--r--src/debug/di/rspriv.h38
-rw-r--r--src/debug/di/shimdatatarget.h2
-rw-r--r--src/debug/di/shimlocaldatatarget.cpp6
-rw-r--r--src/debug/di/shimpriv.h4
-rw-r--r--src/debug/di/shimprocess.cpp6
-rw-r--r--src/debug/di/shimremotedatatarget.cpp6
-rw-r--r--src/debug/di/windowspipeline.cpp10
-rw-r--r--src/debug/inc/dbgtransportsession.h8
-rw-r--r--src/debug/inc/processdescriptor.h38
-rw-r--r--src/debug/inc/twowaypipe.h11
-rw-r--r--src/debug/shared/dbgtransportsession.cpp14
-rw-r--r--src/dlls/dbgshim/dbgshim.cpp167
-rw-r--r--src/dlls/dbgshim/dbgshim.h15
-rw-r--r--src/dlls/dbgshim/dbgshim.ntdef2
-rw-r--r--src/dlls/dbgshim/dbgshim_unixexports.src2
-rw-r--r--src/dlls/mscordbi/mscordbi.src1
-rw-r--r--src/dlls/mscordbi/mscordbi_unixexports.src1
-rw-r--r--src/pal/inc/pal.h4
-rw-r--r--src/pal/src/include/pal/stackstring.hpp7
-rw-r--r--src/pal/src/thread/process.cpp281
37 files changed, 671 insertions, 214 deletions
diff --git a/src/debug/debug-pal/CMakeLists.txt b/src/debug/debug-pal/CMakeLists.txt
index c96d7f9e06..83e400c28f 100644
--- a/src/debug/debug-pal/CMakeLists.txt
+++ b/src/debug/debug-pal/CMakeLists.txt
@@ -12,6 +12,7 @@ if(WIN32)
set(TWO_WAY_PIPE_SOURCES
win/twowaypipe.cpp
+ win/processdescriptor.cpp
)
endif(WIN32)
@@ -24,6 +25,7 @@ if(CLR_CMAKE_PLATFORM_UNIX)
set(TWO_WAY_PIPE_SOURCES
unix/twowaypipe.cpp
+ unix/processdescriptor.cpp
)
endif(CLR_CMAKE_PLATFORM_UNIX)
diff --git a/src/debug/debug-pal/unix/processdescriptor.cpp b/src/debug/debug-pal/unix/processdescriptor.cpp
new file mode 100644
index 0000000000..6a4975dc6b
--- /dev/null
+++ b/src/debug/debug-pal/unix/processdescriptor.cpp
@@ -0,0 +1,21 @@
+// 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 <pal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <pal_assert.h>
+#include "processdescriptor.h"
+
+ProcessDescriptor ProcessDescriptor::FromCurrentProcess()
+{
+#ifdef __APPLE__
+ return Create(GetCurrentProcessId(), PAL_GetApplicationGroupId());
+#else
+ return Create(GetCurrentProcessId(), nullptr);
+#endif
+}
diff --git a/src/debug/debug-pal/unix/twowaypipe.cpp b/src/debug/debug-pal/unix/twowaypipe.cpp
index 9dfe1e3ecb..b0acb1df7b 100644
--- a/src/debug/debug-pal/unix/twowaypipe.cpp
+++ b/src/debug/debug-pal/unix/twowaypipe.cpp
@@ -14,15 +14,14 @@
// Creates a server side of the pipe.
// Id is used to create pipes names and uniquely identify the pipe on the machine.
// true - success, false - failure (use GetLastError() for more details)
-bool TwoWayPipe::CreateServer(DWORD id)
+bool TwoWayPipe::CreateServer(const ProcessDescriptor& pd)
{
_ASSERTE(m_state == NotInitialized);
if (m_state != NotInitialized)
return false;
- m_id = id;
- PAL_GetTransportPipeName(m_inPipeName, id, "in");
- PAL_GetTransportPipeName(m_outPipeName, id, "out");
+ PAL_GetTransportPipeName(m_inPipeName, pd.m_Pid, pd.m_ApplicationGroupId, "in");
+ PAL_GetTransportPipeName(m_outPipeName, pd.m_Pid, pd.m_ApplicationGroupId, "out");
unlink(m_inPipeName);
@@ -47,16 +46,15 @@ bool TwoWayPipe::CreateServer(DWORD id)
// Connects to a previously opened server side of the pipe.
// Id is used to locate the pipe on the machine.
// true - success, false - failure (use GetLastError() for more details)
-bool TwoWayPipe::Connect(DWORD id)
+bool TwoWayPipe::Connect(const ProcessDescriptor& pd)
{
_ASSERTE(m_state == NotInitialized);
if (m_state != NotInitialized)
return false;
- m_id = id;
//"in" and "out" are switched deliberately, because we're on the client
- PAL_GetTransportPipeName(m_inPipeName, id, "out");
- PAL_GetTransportPipeName(m_outPipeName, id, "in");
+ PAL_GetTransportPipeName(m_inPipeName, pd.m_Pid, pd.m_ApplicationGroupId, "out");
+ PAL_GetTransportPipeName(m_outPipeName, pd.m_Pid, pd.m_ApplicationGroupId, "in");
// Pipe opening order is reversed compared to WaitForConnection()
// in order to avaid deadlock.
diff --git a/src/debug/debug-pal/win/processdescriptor.cpp b/src/debug/debug-pal/win/processdescriptor.cpp
new file mode 100644
index 0000000000..fbc0bf0486
--- /dev/null
+++ b/src/debug/debug-pal/win/processdescriptor.cpp
@@ -0,0 +1,14 @@
+// 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 <windows.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <assert.h>
+#include "processdescriptor.h"
+
+ProcessDescriptor ProcessDescriptor::FromCurrentProcess()
+{
+ return FromPid(GetCurrentProcessId());
+}
diff --git a/src/debug/debug-pal/win/twowaypipe.cpp b/src/debug/debug-pal/win/twowaypipe.cpp
index 6e4c9127d7..fb788b068f 100644
--- a/src/debug/debug-pal/win/twowaypipe.cpp
+++ b/src/debug/debug-pal/win/twowaypipe.cpp
@@ -17,19 +17,19 @@
// Creates a server side of the pipe.
// Id is used to create pipes names and uniquely identify the pipe on the machine.
// true - success, false - failure (use GetLastError() for more details)
-bool TwoWayPipe::CreateServer(DWORD id)
+bool TwoWayPipe::CreateServer(const ProcessDescriptor& pd)
{
_ASSERTE(m_state == NotInitialized);
if (m_state != NotInitialized)
return false;
- m_inboundPipe = CreateOneWayPipe(id, true);
+ m_inboundPipe = CreateOneWayPipe(pd.m_Pid, true);
if (m_inboundPipe == INVALID_HANDLE_VALUE)
{
return false;
}
- m_outboundPipe = CreateOneWayPipe(id, false);
+ m_outboundPipe = CreateOneWayPipe(pd.m_Pid, false);
if (m_outboundPipe == INVALID_HANDLE_VALUE)
{
CloseHandle(m_inboundPipe);
@@ -45,19 +45,19 @@ bool TwoWayPipe::CreateServer(DWORD id)
// Connects to a previously opened server side of the pipe.
// Id is used to locate the pipe on the machine.
// true - success, false - failure (use GetLastError() for more details)
-bool TwoWayPipe::Connect(DWORD id)
+bool TwoWayPipe::Connect(const ProcessDescriptor& pd)
{
_ASSERTE(m_state == NotInitialized);
if (m_state != NotInitialized)
return false;
- m_inboundPipe = OpenOneWayPipe(id, true);
+ m_inboundPipe = OpenOneWayPipe(pd.m_Pid, true);
if (m_inboundPipe == INVALID_HANDLE_VALUE)
{
return false;
}
- m_outboundPipe = OpenOneWayPipe(id, false);
+ m_outboundPipe = OpenOneWayPipe(pd.m_Pid, false);
if (m_outboundPipe == INVALID_HANDLE_VALUE)
{
CloseHandle(m_inboundPipe);
diff --git a/src/debug/di/cordb.cpp b/src/debug/di/cordb.cpp
index ae74c34b54..4febb5125a 100644
--- a/src/debug/di/cordb.cpp
+++ b/src/debug/di/cordb.cpp
@@ -87,9 +87,6 @@ HINSTANCE g_hInst; // Instance handle to this piece of code
// This was used by the Mix07 release of Silverlight, but it didn't properly support versioning
// and we no longer support it's debugger protocol so we require callers to use
// code:CoreCLRCreateCordbObject instead.
-//
-// This is also still used on Mac - multi-instance debugging and debugger
-// versioning isn't really implemented there yet. This probably needs to change.
//*****************************************************************************
STDAPI CreateCordbObject(int iDebuggerVersion, IUnknown ** ppCordb)
{
@@ -112,24 +109,28 @@ STDAPI CreateCordbObject(int iDebuggerVersion, IUnknown ** ppCordb)
return E_INVALIDARG;
}
- return Cordb::CreateObject((CorDebugInterfaceVersion)iDebuggerVersion, IID_ICorDebug, (void **) ppCordb);
+ return Cordb::CreateObject(
+ (CorDebugInterfaceVersion)iDebuggerVersion, ProcessDescriptor::UNINITIALIZED_PID, /*lpApplicationGroupId*/ NULL, IID_ICorDebug, (void **) ppCordb);
}
//
// Public API.
-// Telesto Creation path - only way to debug multi-instance.
-// This supercedes code:CreateCordbObject
+// Telesto Creation path with Mac sandbox support - only way to debug a sandboxed application on Mac.
+// This supercedes code:CoreCLRCreateCordbObject
//
// Arguments:
// iDebuggerVersion - version of ICorDebug interfaces that the debugger is requesting
// pid - pid of debuggee that we're attaching to.
+// lpApplicationGroupId - A string representing the application group ID of a sandboxed
+// process running in Mac. Pass NULL if the process is not
+// running in a sandbox and other platforms.
// hmodTargetCLR - module handle to clr in target pid that we're attaching to.
// ppCordb - (out) the resulting ICorDebug object.
//
// Notes:
// It's inconsistent that this takes a (handle, pid) but hands back an ICorDebug instead of an ICorDebugProcess.
// Callers will need to call *ppCordb->DebugActiveProcess(pid).
-STDAPI CoreCLRCreateCordbObject(int iDebuggerVersion, DWORD pid, HMODULE hmodTargetCLR, IUnknown ** ppCordb)
+STDAPI CoreCLRCreateCordbObjectEx(int iDebuggerVersion, DWORD pid, LPCWSTR lpApplicationGroupId, HMODULE hmodTargetCLR, IUnknown ** ppCordb)
{
if (ppCordb == NULL)
{
@@ -145,10 +146,8 @@ STDAPI CoreCLRCreateCordbObject(int iDebuggerVersion, DWORD pid, HMODULE hmodTar
// Create the ICorDebug object
//
RSExtSmartPtr<ICorDebug> pCordb;
- Cordb::CreateObject((CorDebugInterfaceVersion)iDebuggerVersion, IID_ICorDebug, (void **) &pCordb);
+ Cordb::CreateObject((CorDebugInterfaceVersion)iDebuggerVersion, pid, lpApplicationGroupId, IID_ICorDebug, (void **) &pCordb);
- // @dbgtodo - we should stash the pid and validate that it's the same pid we're attaching to in ICorDebug::DebugActiveProcess.
-
//
// Associate it with the target instance
//
@@ -167,6 +166,25 @@ STDAPI CoreCLRCreateCordbObject(int iDebuggerVersion, DWORD pid, HMODULE hmodTar
return hr;
}
+//
+// Public API.
+// Telesto Creation path - only way to debug multi-instance.
+// This supercedes code:CreateCordbObject
+//
+// Arguments:
+// iDebuggerVersion - version of ICorDebug interfaces that the debugger is requesting
+// pid - pid of debuggee that we're attaching to.
+// hmodTargetCLR - module handle to clr in target pid that we're attaching to.
+// ppCordb - (out) the resulting ICorDebug object.
+//
+// Notes:
+// It's inconsistent that this takes a (handle, pid) but hands back an ICorDebug instead of an ICorDebugProcess.
+// Callers will need to call *ppCordb->DebugActiveProcess(pid).
+STDAPI CoreCLRCreateCordbObject(int iDebuggerVersion, DWORD pid, HMODULE hmodTargetCLR, IUnknown ** ppCordb)
+{
+ return CoreCLRCreateCordbObjectEx(iDebuggerVersion, pid, NULL, hmodTargetCLR, ppCordb);
+}
+
diff --git a/src/debug/di/dbgtransportmanager.cpp b/src/debug/di/dbgtransportmanager.cpp
index 8c1079dc33..b897547057 100644
--- a/src/debug/di/dbgtransportmanager.cpp
+++ b/src/debug/di/dbgtransportmanager.cpp
@@ -47,12 +47,13 @@ void DbgTransportTarget::Shutdown()
// Given a PID attempt to find or create a DbgTransportSession instance to manage a connection to a runtime in
// that process. Returns E_UNEXPECTED if the process can't be found. Also returns a handle that can be waited
// on for process termination.
-HRESULT DbgTransportTarget::GetTransportForProcess(DWORD dwPID,
- DbgTransportSession **ppTransport,
- HANDLE *phProcessHandle)
+HRESULT DbgTransportTarget::GetTransportForProcess(const ProcessDescriptor *pProcessDescriptor,
+ DbgTransportSession **ppTransport,
+ HANDLE *phProcessHandle)
{
RSLockHolder lock(&m_sLock);
HRESULT hr = S_OK;
+ DWORD dwPID = pProcessDescriptor->m_Pid;
ProcessEntry *entry = LocateProcessByPID(dwPID);
@@ -78,7 +79,7 @@ HRESULT DbgTransportTarget::GetTransportForProcess(DWORD dwPID
}
// Initialize it (this immediately starts the remote connection process).
- hr = transport->Init(dwPID, hProcess);
+ hr = transport->Init(*pProcessDescriptor, hProcess);
if (FAILED(hr))
{
transport->Shutdown();
diff --git a/src/debug/di/dbgtransportmanager.h b/src/debug/di/dbgtransportmanager.h
index 3a8013eae8..e1aeaa4623 100644
--- a/src/debug/di/dbgtransportmanager.h
+++ b/src/debug/di/dbgtransportmanager.h
@@ -20,13 +20,16 @@
// Usual lifecycle looks like this:
// Debug a new process:
// * CreateProcess(&pid)
-// * GetTransportForProcess(pid, &transport)
+// * On Mac, Optionally obtain an application group ID from a user
+// * Create a ProcessDescriptor pd
+// * GetTransportForProcess(&pd, &transport)
// * ReleaseTransport(transport)
// * KillProcess(pid)
// Attach to an existing process:
-// * Obtain pid from a user
-// * GetTransportForProcess(pid, &transport)
+// * Obtain pid (and optionally application group ID on Mac) from a user
+// * Create a ProcessDescriptor pd
+// * GetTransportForProcess(&pd, &transport)
// * ReleaseTransport(transport)
class DbgTransportTarget
@@ -37,7 +40,7 @@ public:
// Given a PID attempt to find or create a DbgTransportSession instance to manage a connection to a
// runtime in that process. Returns E_UNEXPECTED if the process can't be found. Also returns a handle that
// can be waited on for process termination.
- HRESULT GetTransportForProcess(DWORD dwPID, DbgTransportSession **ppTransport, HANDLE *phProcessHandle);
+ HRESULT GetTransportForProcess(const ProcessDescriptor *pProcessDescriptor, DbgTransportSession **ppTransport, HANDLE *phProcessHandle);
// Give back a previously acquired transport (if nobody else is using the transport it will close down the
// connection at this point).
diff --git a/src/debug/di/dbgtransportpipeline.cpp b/src/debug/di/dbgtransportpipeline.cpp
index 88f6220c8e..645cf41987 100644
--- a/src/debug/di/dbgtransportpipeline.cpp
+++ b/src/debug/di/dbgtransportpipeline.cpp
@@ -91,7 +91,7 @@ public:
LPPROCESS_INFORMATION lpProcessInformation);
// Attach
- virtual HRESULT DebugActiveProcess(MachineInfo machineInfo, DWORD processId);
+ virtual HRESULT DebugActiveProcess(MachineInfo machineInfo, const ProcessDescriptor& processDescriptor);
// Detach
virtual HRESULT DebugActiveProcessStop(DWORD processId);
@@ -224,8 +224,10 @@ HRESULT DbgTransportPipeline::CreateProcessUnderDebugger(
if (SUCCEEDED(hr))
{
+ ProcessDescriptor processDescriptor = ProcessDescriptor::Create(lpProcessInformation->dwProcessId, NULL);
+
// Establish a connection to the actual runtime to be debugged.
- hr = m_pProxy->GetTransportForProcess(lpProcessInformation->dwProcessId,
+ hr = m_pProxy->GetTransportForProcess(&processDescriptor,
&m_pTransport,
&m_hProcess);
if (SUCCEEDED(hr))
@@ -283,7 +285,7 @@ HRESULT DbgTransportPipeline::CreateProcessUnderDebugger(
}
// Attach the debugger to this process.
-HRESULT DbgTransportPipeline::DebugActiveProcess(MachineInfo machineInfo, DWORD processId)
+HRESULT DbgTransportPipeline::DebugActiveProcess(MachineInfo machineInfo, const ProcessDescriptor& processDescriptor)
{
// INativeEventPipeline has a 1:1 relationship with CordbProcess.
_ASSERTE(!IsTransportRunning());
@@ -293,7 +295,7 @@ HRESULT DbgTransportPipeline::DebugActiveProcess(MachineInfo machineInfo, DWORD
m_pProxy = g_pDbgTransportTarget;
// Establish a connection to the actual runtime to be debugged.
- hr = m_pProxy->GetTransportForProcess(processId, &m_pTransport, &m_hProcess);
+ hr = m_pProxy->GetTransportForProcess(&processDescriptor, &m_pTransport, &m_hProcess);
if (SUCCEEDED(hr))
{
// TODO: Pass this timeout as a parameter all the way from debugger
@@ -313,7 +315,7 @@ HRESULT DbgTransportPipeline::DebugActiveProcess(MachineInfo machineInfo, DWORD
if (SUCCEEDED(hr))
{
- m_dwProcessId = processId;
+ m_dwProcessId = processDescriptor.m_Pid;
m_fRunning = TRUE;
}
else
diff --git a/src/debug/di/eventchannel.h b/src/debug/di/eventchannel.h
index 5a4ff23ea8..1739d7568e 100644
--- a/src/debug/di/eventchannel.h
+++ b/src/debug/di/eventchannel.h
@@ -257,7 +257,7 @@ public:
HRESULT NewEventChannelForThisPlatform(CORDB_ADDRESS pLeftSideDCB,
ICorDebugMutableDataTarget * pMutableDataTarget,
- DWORD dwProcessId,
+ const ProcessDescriptor * pProcessDescriptor,
MachineInfo machineInfo,
IEventChannel ** ppEventChannel);
diff --git a/src/debug/di/eventredirectionpipeline.cpp b/src/debug/di/eventredirectionpipeline.cpp
index 23405d643a..46c4997530 100644
--- a/src/debug/di/eventredirectionpipeline.cpp
+++ b/src/debug/di/eventredirectionpipeline.cpp
@@ -293,13 +293,13 @@ HRESULT EventRedirectionPipeline::CreateProcessUnderDebugger(
// Attach
-HRESULT EventRedirectionPipeline::DebugActiveProcess(MachineInfo machineInfo, DWORD processId)
+HRESULT EventRedirectionPipeline::DebugActiveProcess(MachineInfo machineInfo, const ProcessDescriptor& processDescriptor)
{
- m_dwProcessId = processId;
+ m_dwProcessId = processDescriptor.m_Pid;
// Use redirected pipeline
// Spin up debugger to attach to target.
- return AttachDebuggerToTarget(m_AttachParams.Value(), processId);
+ return AttachDebuggerToTarget(m_AttachParams.Value(), processDescriptor.m_Pid);
}
// Detach
diff --git a/src/debug/di/eventredirectionpipeline.h b/src/debug/di/eventredirectionpipeline.h
index 87549c1150..0da16175ca 100644
--- a/src/debug/di/eventredirectionpipeline.h
+++ b/src/debug/di/eventredirectionpipeline.h
@@ -59,7 +59,7 @@ public:
LPPROCESS_INFORMATION lpProcessInformation);
// Attach
- virtual HRESULT DebugActiveProcess(MachineInfo machineInfo, DWORD processId);
+ virtual HRESULT DebugActiveProcess(MachineInfo machineInfo, const ProcessDescriptor& processDescriptor);
// Detach
virtual HRESULT DebugActiveProcessStop(DWORD processId);
diff --git a/src/debug/di/localeventchannel.cpp b/src/debug/di/localeventchannel.cpp
index f31c46f7bb..e89affaf57 100644
--- a/src/debug/di/localeventchannel.cpp
+++ b/src/debug/di/localeventchannel.cpp
@@ -115,7 +115,7 @@ private:
// Allocate and return an old-style event channel object for this target platform.
HRESULT NewEventChannelForThisPlatform(CORDB_ADDRESS pLeftSideDCB,
ICorDebugMutableDataTarget * pMutableDataTarget,
- DWORD dwProcessId,
+ const ProcessDescriptor * pProcessDescriptor,
MachineInfo machineInfo,
IEventChannel ** ppEventChannel)
{
diff --git a/src/debug/di/nativepipeline.h b/src/debug/di/nativepipeline.h
index 9611d84404..5d22de9ed8 100644
--- a/src/debug/di/nativepipeline.h
+++ b/src/debug/di/nativepipeline.h
@@ -67,7 +67,7 @@ public:
LPPROCESS_INFORMATION lpProcessInformation) = 0;
// Attach
- virtual HRESULT DebugActiveProcess(MachineInfo machineInfo, DWORD processId) = 0;
+ virtual HRESULT DebugActiveProcess(MachineInfo machineInfo, const ProcessDescriptor& processDescriptor) = 0;
// Detach
virtual HRESULT DebugActiveProcessStop(DWORD processId) =0;
diff --git a/src/debug/di/process.cpp b/src/debug/di/process.cpp
index 01b474bde6..2343122317 100644
--- a/src/debug/di/process.cpp
+++ b/src/debug/di/process.cpp
@@ -100,12 +100,13 @@ STDAPI OpenVirtualProcessImpl(
// - there is no w32et thread (all threads are effectively an event thread)
// - the stop state is 'live', which corresponds to CordbProcess not knowing what
// its stop state really is (because that is now controlled by the shim).
+ ProcessDescriptor pd = ProcessDescriptor::CreateUninitialized();
IfFailThrow(CordbProcess::OpenVirtualProcess(
clrInstanceId,
pDataTarget, // takes a reference
hDacModule,
NULL, // Cordb
- (DWORD) 0, // 0 for V3 cases (pShim == NULL).
+ &pd, // 0 for V3 cases (pShim == NULL).
NULL, // no Shim in V3 cases
&pProcess));
@@ -820,7 +821,7 @@ HRESULT CordbProcess::OpenVirtualProcess(
IUnknown * pDataTarget,
HMODULE hDacModule,
Cordb* pCordb,
- DWORD dwProcessID,
+ const ProcessDescriptor * pProcessDescriptor,
ShimProcess * pShim,
CordbProcess ** ppProcess)
{
@@ -849,7 +850,7 @@ HRESULT CordbProcess::OpenVirtualProcess(
HRESULT hr = S_OK;
RSUnsafeExternalSmartPtr<CordbProcess> pProcess;
- pProcess.Assign(new (nothrow) CordbProcess(clrInstanceId, pDataTarget, hDacModule, pCordb, dwProcessID, pShim));
+ pProcess.Assign(new (nothrow) CordbProcess(clrInstanceId, pDataTarget, hDacModule, pCordb, pProcessDescriptor, pShim));
if (pProcess == NULL)
{
@@ -916,12 +917,13 @@ CordbProcess::CordbProcess(ULONG64 clrInstanceId,
IUnknown * pDataTarget,
HMODULE hDacModule,
Cordb * pCordb,
- DWORD dwProcessID,
+ const ProcessDescriptor * pProcessDescriptor,
ShimProcess * pShim)
- : CordbBase(NULL, dwProcessID, enumCordbProcess),
+ : CordbBase(NULL, pProcessDescriptor->m_Pid, enumCordbProcess),
m_fDoDelayedManagedAttached(false),
m_cordb(pCordb),
m_handle(NULL),
+ m_processDescriptor(*pProcessDescriptor),
m_detached(false),
m_uninitializedStop(false),
m_exiting(false),
@@ -1194,7 +1196,7 @@ HRESULT ShimProcess::CreateProcess(
HRESULT ShimProcess::DebugActiveProcess(
Cordb * pCordb,
ICorDebugRemoteTarget * pRemoteTarget,
- DWORD dwProcessID,
+ const ProcessDescriptor * pProcessDescriptor,
BOOL fWin32Attach
)
{
@@ -1216,7 +1218,7 @@ HRESULT ShimProcess::DebugActiveProcess(
// If this succeeds, new CordbProcess will add a ref to the ShimProcess
hr = pShim->GetWin32EventThread()->SendDebugActiveProcessEvent(pShim->GetMachineInfo(),
- dwProcessID,
+ pProcessDescriptor,
fWin32Attach == TRUE,
NULL);
IfFailThrow(hr);
@@ -3318,22 +3320,22 @@ HRESULT CordbProcess::GetID(DWORD *pdwProcessId)
*pdwProcessId = 0;
ThrowHR(E_NOTIMPL);
}
- *pdwProcessId = GetPid();
+ *pdwProcessId = GetProcessDescriptor()->m_Pid;
}
EX_CATCH_HRESULT(hr);
return hr;
}
-// Helper to get PID internally. We know we'll always succeed.
+// Helper to get process descriptor internally. We know we'll always succeed.
// This is more convient for internal callers since they can just use it as an expression
// without having to check HRESULTS.
-DWORD CordbProcess::GetPid()
+const ProcessDescriptor* CordbProcess::GetProcessDescriptor()
{
// This shouldn't be used in V3 paths, in which case it's set to 0. Only the shim should be
// calling this. Assert to catch anybody else.
- _ASSERTE(m_id != 0);
+ _ASSERTE(m_processDescriptor.IsInitialized());
- return (DWORD) m_id;
+ return &m_processDescriptor;
}
@@ -7517,7 +7519,7 @@ void CordbProcess::GetEventBlock(BOOL * pfBlockExists)
IfFailThrow(NewEventChannelForThisPlatform(pLeftSideDCB,
m_pMutableDataTarget,
- GetPid(),
+ GetProcessDescriptor(),
m_pShim->GetMachineInfo(),
&m_pEventChannel));
_ASSERTE(m_pEventChannel != NULL);
@@ -13809,9 +13811,10 @@ void CordbWin32EventThread::CreateProcess()
{
// Process ID is filled in after process is succesfully created.
DWORD dwProcessId = m_actionData.createData.lpProcessInformation->dwProcessId;
+ ProcessDescriptor pd = ProcessDescriptor::FromPid(dwProcessId);
RSUnsafeExternalSmartPtr<CordbProcess> pProcess;
- hr = m_pShim->InitializeDataTarget(dwProcessId);
+ hr = m_pShim->InitializeDataTarget(&pd);
if (SUCCEEDED(hr))
{
@@ -13819,7 +13822,7 @@ void CordbWin32EventThread::CreateProcess()
// OpenVirtualProcess. This will then connect to the first CLR
// loaded.
const ULONG64 cFirstClrLoaded = 0;
- hr = CordbProcess::OpenVirtualProcess(cFirstClrLoaded, m_pShim->GetDataTarget(), NULL, m_cordb, dwProcessId, m_pShim, &pProcess);
+ hr = CordbProcess::OpenVirtualProcess(cFirstClrLoaded, m_pShim->GetDataTarget(), NULL, m_cordb, &pd, m_pShim, &pProcess);
}
// Shouldn't happen on a create, only an attach
@@ -13866,7 +13869,7 @@ void CordbWin32EventThread::CreateProcess()
//
HRESULT CordbWin32EventThread::SendDebugActiveProcessEvent(
MachineInfo machineInfo,
- DWORD pid,
+ const ProcessDescriptor *pProcessDescriptor,
bool fWin32Attach,
CordbProcess *pProcess)
{
@@ -13875,7 +13878,7 @@ HRESULT CordbWin32EventThread::SendDebugActiveProcessEvent(
LockSendToWin32EventThreadMutex();
m_actionData.attachData.machineInfo = machineInfo;
- m_actionData.attachData.processId = pid;
+ m_actionData.attachData.processDescriptor = *pProcessDescriptor;
#if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
m_actionData.attachData.fWin32Attach = fWin32Attach;
#endif
@@ -14004,17 +14007,16 @@ void CordbWin32EventThread::AttachProcess()
HRESULT hr = S_OK;
- DWORD dwProcessId = m_actionData.attachData.processId;
+ ProcessDescriptor processDescriptor = m_actionData.attachData.processDescriptor;
bool fNativeAttachSucceeded = false;
-
// Always do OS attach to the target.
// By this point, the pid should be valid (because OpenProcess above), pending some race where the process just exited.
// The OS will enforce that only 1 debugger is attached.
// Common failure paths here would be: access denied, double-attach
{
hr = m_pNativePipeline->DebugActiveProcess(m_actionData.attachData.machineInfo,
- dwProcessId);
+ processDescriptor);
if (FAILED(hr))
{
goto LExit;
@@ -14023,7 +14025,7 @@ void CordbWin32EventThread::AttachProcess()
}
- hr = m_pShim->InitializeDataTarget(m_actionData.attachData.processId);
+ hr = m_pShim->InitializeDataTarget(&processDescriptor);
if (FAILED(hr))
{
goto LExit;
@@ -14034,7 +14036,7 @@ void CordbWin32EventThread::AttachProcess()
// loaded.
{
const ULONG64 cFirstClrLoaded = 0;
- hr = CordbProcess::OpenVirtualProcess(cFirstClrLoaded, m_pShim->GetDataTarget(), NULL, m_cordb, dwProcessId, m_pShim, &pProcess);
+ hr = CordbProcess::OpenVirtualProcess(cFirstClrLoaded, m_pShim->GetDataTarget(), NULL, m_cordb, &processDescriptor, m_pShim, &pProcess);
if (FAILED(hr))
{
goto LExit;
@@ -14081,7 +14083,7 @@ LExit:
// If we succeed to do a native-attach, but then failed elsewhere, try to native-detach.
if (fNativeAttachSucceeded)
{
- m_pNativePipeline->DebugActiveProcessStop(dwProcessId);
+ m_pNativePipeline->DebugActiveProcessStop(processDescriptor.m_Pid);
}
if (pProcess != NULL)
@@ -14509,7 +14511,7 @@ void CordbWin32EventThread::ExitProcess(bool fDetach)
// Eventually, the Debugger owns the detach pipeline, so this won't be necessary.
if (fDetach && (m_pProcess != NULL))
{
- HRESULT hr = m_pNativePipeline->DebugActiveProcessStop(m_pProcess->GetPid());
+ HRESULT hr = m_pNativePipeline->DebugActiveProcessStop(m_pProcess->GetProcessDescriptor()->m_Pid);
// We don't expect detach to fail (we check earlier for common conditions that
// may cause it to fail)
diff --git a/src/debug/di/remoteeventchannel.cpp b/src/debug/di/remoteeventchannel.cpp
index fc1d57a60f..ab810008a3 100644
--- a/src/debug/di/remoteeventchannel.cpp
+++ b/src/debug/di/remoteeventchannel.cpp
@@ -90,7 +90,7 @@ private:
// Allocate and return an old-style event channel object for this target platform.
HRESULT NewEventChannelForThisPlatform(CORDB_ADDRESS pLeftSideDCB,
ICorDebugMutableDataTarget * pMutableDataTarget,
- DWORD dwProcessId,
+ const ProcessDescriptor * pProcessDescriptor,
MachineInfo machineInfo,
IEventChannel ** ppEventChannel)
{
@@ -105,7 +105,7 @@ HRESULT NewEventChannelForThisPlatform(CORDB_ADDRESS pLeftSideDCB,
DbgTransportTarget * pProxy = g_pDbgTransportTarget;
DbgTransportSession * pTransport = NULL;
- hr = pProxy->GetTransportForProcess(dwProcessId, &pTransport, &hDummy);
+ hr = pProxy->GetTransportForProcess(pProcessDescriptor, &pTransport, &hDummy);
if (FAILED(hr))
{
goto Label_Exit;
diff --git a/src/debug/di/rsmain.cpp b/src/debug/di/rsmain.cpp
index 750cb1d8ee..f2f9b794c1 100644
--- a/src/debug/di/rsmain.cpp
+++ b/src/debug/di/rsmain.cpp
@@ -957,13 +957,17 @@ namespace
/* ------------------------------------------------------------------------- *
* Cordb class
* ------------------------------------------------------------------------- */
-
-
Cordb::Cordb(CorDebugInterfaceVersion iDebuggerVersion)
+ : Cordb(iDebuggerVersion, ProcessDescriptor::CreateUninitialized())
+{
+}
+
+Cordb::Cordb(CorDebugInterfaceVersion iDebuggerVersion, const ProcessDescriptor& pd)
: CordbBase(NULL, 0, enumCordb),
m_processes(11),
m_initialized(false),
- m_debuggerSpecifiedVersion(iDebuggerVersion)
+ m_debuggerSpecifiedVersion(iDebuggerVersion),
+ m_pd(pd)
#ifdef FEATURE_CORESYSTEM
,
m_targetCLR(0)
@@ -980,6 +984,10 @@ Cordb::Cordb(CorDebugInterfaceVersion iDebuggerVersion)
Cordb::~Cordb()
{
LOG((LF_CORDB, LL_INFO10, "C::~C Terminating Cordb object.\n"));
+ if (m_pd.m_ApplicationGroupId != NULL)
+ {
+ delete [] m_pd.m_ApplicationGroupId;
+ }
g_pRSDebuggingInfo->m_Cordb = NULL;
}
@@ -1819,6 +1827,12 @@ HRESULT Cordb::DebugActiveProcessCommon(ICorDebugRemoteTarget * pRemoteTarget,
ThrowHR(E_FAIL);
}
+ // Verify that given process ID, matches the process ID for which the object was created
+ if (m_pd.IsInitialized() && m_pd.m_Pid != dwProcessId)
+ {
+ ThrowHR(E_INVALIDARG);
+ }
+
// See the comment in Cordb::CreateProcess
_ASSERTE(CorDebugInvalidVersion != m_debuggerSpecifiedVersion);
@@ -1845,7 +1859,7 @@ HRESULT Cordb::DebugActiveProcessCommon(ICorDebugRemoteTarget * pRemoteTarget,
hr = ShimProcess::DebugActiveProcess(
this,
pRemoteTarget,
- dwProcessId,
+ &m_pd,
fWin32Attach == TRUE);
// If that worked, then there will be a process object...
@@ -2065,7 +2079,7 @@ void Cordb::EnsureCanLaunchOrAttach(BOOL fWin32DebuggingEnabled)
HRESULT Cordb::CreateObjectV1(REFIID id, void **object)
{
- return CreateObject(CorDebugVersion_1_0, id, object);
+ return CreateObject(CorDebugVersion_1_0, ProcessDescriptor::UNINITIALIZED_PID, NULL, id, object);
}
#if defined(FEATURE_DBGIPC_TRANSPORT_DI)
@@ -2073,21 +2087,52 @@ HRESULT Cordb::CreateObjectV1(REFIID id, void **object)
// same debug engine version as V2, though this may change in the future.
HRESULT Cordb::CreateObjectTelesto(REFIID id, void ** pObject)
{
- return CreateObject(CorDebugVersion_2_0, id, pObject);
+ return CreateObject(CorDebugVersion_2_0, ProcessDescriptor::UNINITIALIZED_PID, NULL, id, pObject);
}
#endif // FEATURE_DBGIPC_TRANSPORT_DI
// Static
// Used to create an instance for a ClassFactory (thus an external ref).
-HRESULT Cordb::CreateObject(CorDebugInterfaceVersion iDebuggerVersion, REFIID id, void **object)
+HRESULT Cordb::CreateObject(CorDebugInterfaceVersion iDebuggerVersion, DWORD pid, LPCWSTR lpApplicationGroupId, REFIID id, void **object)
{
if (id != IID_IUnknown && id != IID_ICorDebug)
return (E_NOINTERFACE);
- Cordb *db = new (nothrow) Cordb(iDebuggerVersion);
+ LPSTR applicationGroupId = NULL;
+ if (lpApplicationGroupId != NULL)
+ {
+ // Get length of target string
+ int cbMultiByte = WideCharToMultiByte(CP_ACP, 0, lpApplicationGroupId, -1, NULL, 0, NULL, NULL);
+ if (cbMultiByte == 0)
+ {
+ return E_FAIL;
+ }
+
+ applicationGroupId = new (nothrow) CHAR[cbMultiByte];
+ if (applicationGroupId == NULL)
+ {
+ return (E_OUTOFMEMORY);
+ }
+
+ /* Convert to ASCII */
+ cbMultiByte = WideCharToMultiByte(CP_ACP, 0, lpApplicationGroupId, -1, applicationGroupId, cbMultiByte, NULL, NULL);
+ if (cbMultiByte == 0)
+ {
+ return E_FAIL;
+ }
+ }
+
+ ProcessDescriptor pd = ProcessDescriptor::Create(pid, applicationGroupId);
+
+ Cordb *db = new (nothrow) Cordb(iDebuggerVersion, pd);
if (db == NULL)
+ {
+ if (applicationGroupId != NULL)
+ delete [] applicationGroupId;
+
return (E_OUTOFMEMORY);
+ }
*object = static_cast<ICorDebug*> (db);
db->ExternalAddRef();
diff --git a/src/debug/di/rspriv.h b/src/debug/di/rspriv.h
index 8b388ee684..fef79d80ca 100644
--- a/src/debug/di/rspriv.h
+++ b/src/debug/di/rspriv.h
@@ -44,6 +44,7 @@
struct MachineInfo;
+#include "processdescriptor.h"
#include "nativepipeline.h"
#include "stringcopyholder.h"
@@ -2226,7 +2227,7 @@ public:
#if defined(FEATURE_DBGIPC_TRANSPORT_DI)
static COM_METHOD CreateObjectTelesto(REFIID id, void ** pObject);
#endif // FEATURE_DBGIPC_TRANSPORT_DI
- static COM_METHOD CreateObject(CorDebugInterfaceVersion iDebuggerVersion, REFIID id, void **object);
+ static COM_METHOD CreateObject(CorDebugInterfaceVersion iDebuggerVersion, DWORD pid, LPCWSTR lpApplicationGroupId, REFIID id, void **object);
//-----------------------------------------------------------
// ICorDebugRemote
@@ -2297,6 +2298,9 @@ public:
CordbAppDomain *appDomain,
DebuggerIPCEvent* event);
+private:
+ Cordb(CorDebugInterfaceVersion iDebuggerVersion, const ProcessDescriptor& pd);
+
//-----------------------------------------------------------
// Data members
//-----------------------------------------------------------
@@ -2332,6 +2336,9 @@ private:
// This is the version of the ICorDebug APIs that the debugger believes it's consuming.
CorDebugInterfaceVersion m_debuggerSpecifiedVersion;
+ // Store information about the process to be debugged
+ ProcessDescriptor m_pd;
+
//Note - this code could be useful outside coresystem, but keeping the change localized
// because we are late in the win8 release
#ifdef FEATURE_CORESYSTEM
@@ -2804,8 +2811,8 @@ void DeleteIPCEventHelper(DebuggerIPCEvent *pDel);
class IProcessShimHooks
{
public:
- // Get the OS Process ID of the target.
- virtual DWORD GetPid() = 0;
+ // Get the OS Process descriptor of the target.
+ virtual const ProcessDescriptor* GetProcessDescriptor() = 0;
// Request a synchronization for attach.
// This essentially just sends an AsyncBreak to the left-side. Once the target is
@@ -2932,7 +2939,7 @@ class CordbProcess :
#endif
{
// Ctor is private. Use OpenVirtualProcess instead.
- CordbProcess(ULONG64 clrInstanceId, IUnknown * pDataTarget, HMODULE hDacModule, Cordb * pCordb, DWORD dwProcessID, ShimProcess * pShim);
+ CordbProcess(ULONG64 clrInstanceId, IUnknown * pDataTarget, HMODULE hDacModule, Cordb * pCordb, const ProcessDescriptor * pProcessDescriptor, ShimProcess * pShim);
public:
@@ -2952,7 +2959,7 @@ public:
IUnknown * pDataTarget,
HMODULE hDacModule,
Cordb * pCordb,
- DWORD dwProcessID,
+ const ProcessDescriptor * pProcessDescriptor,
ShimProcess * pShim,
CordbProcess ** ppProcess);
@@ -3266,8 +3273,8 @@ public:
bool IsThreadSuspendedOrHijacked(ICorDebugThread * pICorDebugThread);
- // Helper to get PID internally.
- DWORD GetPid();
+ // Helper to get ProcessDescriptor internally.
+ const ProcessDescriptor* GetProcessDescriptor();
HRESULT GetRuntimeOffsets();
@@ -3708,6 +3715,9 @@ private:
// wait on for process termination.
HANDLE m_handle;
+ // Process descriptor - holds PID and App group ID for Mac debugging
+ ProcessDescriptor m_processDescriptor;
+
public:
// Wrapper to get the OS process handle. This is unsafe because it breaks the data-target abstraction.
// The only things that need this should be calls to DuplicateHandle, and some shimming work.
@@ -10084,7 +10094,7 @@ public:
CorDebugCreateProcessFlags corDebugFlags);
HRESULT SendDebugActiveProcessEvent(MachineInfo machineInfo,
- DWORD pid,
+ const ProcessDescriptor *pProcessDescriptor,
bool fWin32Attach,
CordbProcess *pProcess);
@@ -10183,12 +10193,12 @@ private:
struct
{
- MachineInfo machineInfo;
- DWORD processId;
+ MachineInfo machineInfo;
+ ProcessDescriptor processDescriptor;
#if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
- bool fWin32Attach;
+ bool fWin32Attach;
#endif
- CordbProcess *pProcess;
+ CordbProcess *pProcess;
// Wrapper to determine if we're interop-debugging.
bool IsInteropDebugging()
@@ -10715,7 +10725,7 @@ private:
class CorpubProcess : public CordbCommonBase, public ICorPublishProcess
{
public:
- CorpubProcess(DWORD dwProcessId,
+ CorpubProcess(const ProcessDescriptor * pProcessDescriptor,
bool fManaged,
HANDLE hProcess,
HANDLE hMutex,
@@ -10774,7 +10784,7 @@ public:
bool IsExited();
public:
- DWORD m_dwProcessId;
+ ProcessDescriptor m_processDescriptor;
private:
bool m_fIsManaged;
diff --git a/src/debug/di/shimdatatarget.h b/src/debug/di/shimdatatarget.h
index adcbae8056..09e199d98e 100644
--- a/src/debug/di/shimdatatarget.h
+++ b/src/debug/di/shimdatatarget.h
@@ -126,7 +126,7 @@ protected:
//
HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
- DWORD processId,
+ const ProcessDescriptor * pProcessDescriptor,
ShimDataTarget ** ppDataTarget);
#endif // SHIMDATATARGET_H_
diff --git a/src/debug/di/shimlocaldatatarget.cpp b/src/debug/di/shimlocaldatatarget.cpp
index 36ea611af2..5057f46291 100644
--- a/src/debug/di/shimlocaldatatarget.cpp
+++ b/src/debug/di/shimlocaldatatarget.cpp
@@ -208,7 +208,7 @@ void ShimLocalDataTarget::Dispose()
//
HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
- DWORD processId,
+ const ProcessDescriptor * pProcessDescriptor,
ShimDataTarget ** ppDataTarget)
{
HRESULT hr = S_OK;
@@ -226,7 +226,7 @@ HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
PROCESS_VM_WRITE |
SYNCHRONIZE,
FALSE,
- processId);
+ pProcessDescriptor->m_Pid);
if (hProcess == NULL)
{
@@ -247,7 +247,7 @@ HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
{
goto Label_Exit;
}
- pLocalDataTarget = new (nothrow) ShimLocalDataTarget(processId, hProcess);
+ pLocalDataTarget = new (nothrow) ShimLocalDataTarget(pProcessDescriptor->m_Pid, hProcess);
if (pLocalDataTarget == NULL)
{
hr = E_OUTOFMEMORY;
diff --git a/src/debug/di/shimpriv.h b/src/debug/di/shimpriv.h
index 4c9eb7ab86..279feb978d 100644
--- a/src/debug/di/shimpriv.h
+++ b/src/debug/di/shimpriv.h
@@ -358,7 +358,7 @@ public:
// 3. Create OS-debugging pipeline. This establishes the physical OS process and gets us a pid/handle
// 4. pShim->InitializeDataTarget - this creates a reader/writer abstraction around the OS process.
// 5. pShim->SetProcess() - this connects the Shim to the ICDProcess object.
- HRESULT InitializeDataTarget(DWORD processId);
+ HRESULT InitializeDataTarget(const ProcessDescriptor * pProcessDescriptor);
void SetProcess(ICorDebugProcess * pProcess);
//-----------------------------------------------------------
@@ -384,7 +384,7 @@ public:
static HRESULT DebugActiveProcess(
Cordb * pCordb,
ICorDebugRemoteTarget * pRemoteTarget,
- DWORD pid,
+ const ProcessDescriptor * pProcessDescriptor,
BOOL win32Attach
);
diff --git a/src/debug/di/shimprocess.cpp b/src/debug/di/shimprocess.cpp
index 684173abca..b45bbe4ff4 100644
--- a/src/debug/di/shimprocess.cpp
+++ b/src/debug/di/shimprocess.cpp
@@ -132,7 +132,7 @@ void ShimProcess::SetProcess(ICorDebugProcess * pProcess)
if (pProcess != NULL)
{
// Verify that DataTarget + new process have the same pid?
- _ASSERTE(m_pProcess->GetPid() == m_pLiveDataTarget->GetPid());
+ _ASSERTE(m_pProcess->GetProcessDescriptor()->m_Pid == m_pLiveDataTarget->GetPid());
}
}
@@ -152,12 +152,12 @@ void ShimProcess::SetProcess(ICorDebugProcess * pProcess)
// Notes:
// Only call this once, during the initialization dance.
//
-HRESULT ShimProcess::InitializeDataTarget(DWORD processId)
+HRESULT ShimProcess::InitializeDataTarget(const ProcessDescriptor * pProcessDescriptor)
{
_ASSERTE(m_pLiveDataTarget == NULL);
- HRESULT hr = BuildPlatformSpecificDataTarget(GetMachineInfo(), processId, &m_pLiveDataTarget);
+ HRESULT hr = BuildPlatformSpecificDataTarget(GetMachineInfo(), pProcessDescriptor, &m_pLiveDataTarget);
if (FAILED(hr))
{
_ASSERTE(m_pLiveDataTarget == NULL);
diff --git a/src/debug/di/shimremotedatatarget.cpp b/src/debug/di/shimremotedatatarget.cpp
index f971b0d65a..7e6b8375ee 100644
--- a/src/debug/di/shimremotedatatarget.cpp
+++ b/src/debug/di/shimremotedatatarget.cpp
@@ -154,7 +154,7 @@ void ShimRemoteDataTarget::Dispose()
//
HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
- DWORD processId,
+ const ProcessDescriptor * pProcessDescriptor,
ShimDataTarget ** ppDataTarget)
{
HandleHolder hDummy;
@@ -164,7 +164,7 @@ HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
DbgTransportTarget * pProxy = g_pDbgTransportTarget;
DbgTransportSession * pTransport = NULL;
- hr = pProxy->GetTransportForProcess(processId, &pTransport, &hDummy);
+ hr = pProxy->GetTransportForProcess(pProcessDescriptor, &pTransport, &hDummy);
if (FAILED(hr))
{
goto Label_Exit;
@@ -176,7 +176,7 @@ HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
goto Label_Exit;
}
- pRemoteDataTarget = new (nothrow) ShimRemoteDataTarget(processId, pProxy, pTransport);
+ pRemoteDataTarget = new (nothrow) ShimRemoteDataTarget(pProcessDescriptor->m_Pid, pProxy, pTransport);
if (pRemoteDataTarget == NULL)
{
hr = E_OUTOFMEMORY;
diff --git a/src/debug/di/windowspipeline.cpp b/src/debug/di/windowspipeline.cpp
index c3050e3290..6e58f0be15 100644
--- a/src/debug/di/windowspipeline.cpp
+++ b/src/debug/di/windowspipeline.cpp
@@ -74,7 +74,7 @@ public:
LPPROCESS_INFORMATION lpProcessInformation);
// Attach
- virtual HRESULT DebugActiveProcess(MachineInfo machineInfo, DWORD processId);
+ virtual HRESULT DebugActiveProcess(MachineInfo machineInfo, const ProcessDescriptor& processDescriptor);
// Detach
virtual HRESULT DebugActiveProcessStop(DWORD processId);
@@ -205,15 +205,15 @@ HRESULT WindowsNativePipeline::CreateProcessUnderDebugger(
}
// Attach the debugger to this process.
-HRESULT WindowsNativePipeline::DebugActiveProcess(MachineInfo machineInfo, DWORD processId)
+HRESULT WindowsNativePipeline::DebugActiveProcess(MachineInfo machineInfo, const ProcessDescriptor& processDescriptor)
{
HRESULT hr = E_FAIL;
- BOOL ret = ::DebugActiveProcess(processId);
+ BOOL ret = ::DebugActiveProcess(processDescriptor.m_Pid);
if (ret)
{
hr = S_OK;
- m_dwProcessId = processId;
+ m_dwProcessId = processDescriptor.m_Pid;
UpdateDebugSetProcessKillOnExit();
}
else
@@ -233,7 +233,7 @@ HRESULT WindowsNativePipeline::DebugActiveProcess(MachineInfo machineInfo, DWORD
// attached. But I think it's better to only return the specific error code if we know for sure
// the case is true.
BOOL fIsDebuggerPresent = FALSE;
- if (SUCCEEDED(IsRemoteDebuggerPresent(processId, &fIsDebuggerPresent)))
+ if (SUCCEEDED(IsRemoteDebuggerPresent(processDescriptor.m_Pid, &fIsDebuggerPresent)))
{
if (fIsDebuggerPresent)
{
diff --git a/src/debug/inc/dbgtransportsession.h b/src/debug/inc/dbgtransportsession.h
index 5187202753..390226781f 100644
--- a/src/debug/inc/dbgtransportsession.h
+++ b/src/debug/inc/dbgtransportsession.h
@@ -318,7 +318,7 @@ public:
// requires the addresses of a couple of runtime data structures to service certain debugger requests that
// may be delivered once the session is established.
#ifdef RIGHT_SIDE_COMPILE
- HRESULT Init(DWORD pid, HANDLE hProcessExited);
+ HRESULT Init(const ProcessDescriptor& pd, HANDLE hProcessExited);
#else
HRESULT Init(DebuggerIPCControlBlock * pDCB, AppDomainEnumerationIPCBlock * pADB);
#endif // RIGHT_SIDE_COMPILE
@@ -717,11 +717,11 @@ private:
#ifdef RIGHT_SIDE_COMPILE
// On the RS the transport thread needs to know the IP address and port number to Connect() to.
- DWORD m_pid; // Id of a process we're talking to.
+ ProcessDescriptor m_pd; // Descriptor of a process we're talking to.
- HANDLE m_hProcessExited; // event which will be signaled when the debuggee is terminated
+ HANDLE m_hProcessExited; // event which will be signaled when the debuggee is terminated
- bool m_fDebuggerAttached;
+ bool m_fDebuggerAttached;
#endif
// Debugger event handling. To improve performance we allow the debugger to send as many events as it
diff --git a/src/debug/inc/processdescriptor.h b/src/debug/inc/processdescriptor.h
new file mode 100644
index 0000000000..89840b26a8
--- /dev/null
+++ b/src/debug/inc/processdescriptor.h
@@ -0,0 +1,38 @@
+// 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.
+//*****************************************************************************
+
+#ifndef _PROCESSCONTEXT_H
+#define _PROCESSCONTEXT_H
+
+struct ProcessDescriptor
+{
+ const static DWORD UNINITIALIZED_PID = 0;
+
+ static ProcessDescriptor Create(DWORD pid, LPCSTR applicationGroupId)
+ {
+ ProcessDescriptor pd;
+ pd.m_Pid = pid;
+ pd.m_ApplicationGroupId = applicationGroupId;
+
+ return pd;
+ }
+
+ static ProcessDescriptor FromCurrentProcess();
+ static ProcessDescriptor FromPid(DWORD pid)
+ {
+ return Create(pid, nullptr);
+ }
+ static ProcessDescriptor CreateUninitialized()
+ {
+ return Create(UNINITIALIZED_PID, nullptr);
+ }
+
+ bool IsInitialized() const { return m_Pid != UNINITIALIZED_PID; }
+
+ DWORD m_Pid;
+ LPCSTR m_ApplicationGroupId;
+};
+
+#endif // _PROCESSCONTEXT_H \ No newline at end of file
diff --git a/src/debug/inc/twowaypipe.h b/src/debug/inc/twowaypipe.h
index 6bc0f9f39e..250e40fcb8 100644
--- a/src/debug/inc/twowaypipe.h
+++ b/src/debug/inc/twowaypipe.h
@@ -6,6 +6,8 @@
#ifndef TwoWayPipe_H
#define TwoWayPipe_H
+#include "processdescriptor.h"
+
#ifdef FEATURE_PAL
#define INVALID_PIPE -1
#else
@@ -43,14 +45,14 @@ public:
}
// Creates a server side of the pipe.
- // Id is used to create pipes names and uniquely identify the pipe on the machine.
+ // pd is used to create pipes names and uniquely identify the pipe on the machine.
// true - success, false - failure (use GetLastError() for more details)
- bool CreateServer(DWORD id);
+ bool CreateServer(const ProcessDescriptor& pd);
// Connects to a previously opened server side of the pipe.
- // Id is used to locate the pipe on the machine.
+ // pd is used to locate the pipe on the machine.
// true - success, false - failure (use GetLastError() for more details)
- bool Connect(DWORD id);
+ bool Connect(const ProcessDescriptor& pd);
// Waits for incoming client connections, assumes GetState() == Created
// true - success, false - failure (use GetLastError() for more details)
@@ -83,7 +85,6 @@ private:
#ifdef FEATURE_PAL
- int m_id; // id that was passed to CreateServer() or Connect()
int m_inboundPipe, m_outboundPipe; // two one sided pipes used for communication
char m_inPipeName[MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH]; // filename of the inbound pipe
char m_outPipeName[MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH]; // filename of the outbound pipe
diff --git a/src/debug/shared/dbgtransportsession.cpp b/src/debug/shared/dbgtransportsession.cpp
index f526f91a81..3c0eadb81c 100644
--- a/src/debug/shared/dbgtransportsession.cpp
+++ b/src/debug/shared/dbgtransportsession.cpp
@@ -73,7 +73,7 @@ DbgTransportSession::~DbgTransportSession()
// addresses of a couple of runtime data structures to service certain debugger requests that may be delivered
// once the session is established.
#ifdef RIGHT_SIDE_COMPILE
-HRESULT DbgTransportSession::Init(DWORD pid, HANDLE hProcessExited)
+HRESULT DbgTransportSession::Init(const ProcessDescriptor& pd, HANDLE hProcessExited)
#else // RIGHT_SIDE_COMPILE
HRESULT DbgTransportSession::Init(DebuggerIPCControlBlock *pDCB, AppDomainEnumerationIPCBlock *pADB)
#endif // RIGHT_SIDE_COMPILE
@@ -104,7 +104,7 @@ HRESULT DbgTransportSession::Init(DebuggerIPCControlBlock *pDCB, AppDomainEnumer
#ifdef RIGHT_SIDE_COMPILE
- m_pid = pid;
+ m_pd = pd;
if (!DuplicateHandle(GetCurrentProcess(),
hProcessExited,
@@ -131,8 +131,8 @@ HRESULT DbgTransportSession::Init(DebuggerIPCControlBlock *pDCB, AppDomainEnumer
if (m_hSessionOpenEvent == NULL)
return E_OUTOFMEMORY;
#else // RIGHT_SIDE_COMPILE
- DWORD pid = GetCurrentProcessId();
- if (!m_pipe.CreateServer(pid)) {
+ ProcessDescriptor pd = ProcessDescriptor::FromCurrentProcess();
+ if (!m_pipe.CreateServer(pd)) {
return E_OUTOFMEMORY;
}
#endif // RIGHT_SIDE_COMPILE
@@ -1289,7 +1289,7 @@ void DbgTransportSession::TransportWorker()
eStatus = SCS_NetworkFailure;
else
{
- if (m_pipe.Connect(m_pid))
+ if (m_pipe.Connect(m_pd))
{
eStatus = SCS_Success;
}
@@ -1315,8 +1315,8 @@ void DbgTransportSession::TransportWorker()
eStatus = SCS_NetworkFailure;
else
{
- DWORD pid = GetCurrentProcessId();
- if ((m_pipe.GetState() == TwoWayPipe::Created || m_pipe.CreateServer(pid)) &&
+ ProcessDescriptor pd = ProcessDescriptor::FromCurrentProcess();
+ if ((m_pipe.GetState() == TwoWayPipe::Created || m_pipe.CreateServer(pd)) &&
m_pipe.WaitForConnection())
{
eStatus = SCS_Success;
diff --git a/src/dlls/dbgshim/dbgshim.cpp b/src/dlls/dbgshim/dbgshim.cpp
index 1e5c876888..020dbdc564 100644
--- a/src/dlls/dbgshim/dbgshim.cpp
+++ b/src/dlls/dbgshim/dbgshim.cpp
@@ -194,11 +194,61 @@ GetContinueStartupEvent(
// Functions that we'll look for in the loaded Mscordbi module.
typedef HRESULT (STDAPICALLTYPE *FPCoreCLRCreateCordbObject)(
- int iDebuggerVersion,
- DWORD pid,
- HMODULE hmodTargetCLR,
+ int iDebuggerVersion,
+ DWORD pid,
+ HMODULE hmodTargetCLR,
+ IUnknown **ppCordb);
+
+typedef HRESULT (STDAPICALLTYPE *FPCoreCLRCreateCordbObjectEx)(
+ int iDebuggerVersion,
+ DWORD pid,
+ LPCWSTR lpApplicationGroupId,
+ HMODULE hmodTargetCLR,
IUnknown **ppCordb);
+HRESULT CreateCoreDbgWithSandboxSupport(
+ HMODULE hCLRModule, HMODULE hDBIModule, DWORD processId, LPCWSTR lpApplicationGroupId, int iDebuggerVersion, IUnknown **ppCordb)
+{
+ FPCoreCLRCreateCordbObjectEx fpCreate =
+ (FPCoreCLRCreateCordbObjectEx)GetProcAddress(hDBIModule, "CoreCLRCreateCordbObjectEx");
+ if (fpCreate == NULL)
+ {
+ return CORDBG_E_INCOMPATIBLE_PROTOCOL;
+ }
+
+ return fpCreate(iDebuggerVersion, processId, lpApplicationGroupId, hCLRModule, ppCordb);
+}
+
+HRESULT CreateCoreDbgWithoutSandboxSupport(
+ HMODULE hCLRModule, HMODULE hDBIModule, DWORD processId, int iDebuggerVersion, IUnknown **ppCordb)
+{
+ FPCoreCLRCreateCordbObject fpCreate =
+ (FPCoreCLRCreateCordbObject)GetProcAddress(hDBIModule, "CoreCLRCreateCordbObject");
+ if (fpCreate == NULL)
+ {
+ return CORDBG_E_INCOMPATIBLE_PROTOCOL;
+ }
+
+ return fpCreate(iDebuggerVersion, processId, hCLRModule, ppCordb);
+}
+
+HRESULT CreateCoreDbg(
+ HMODULE hCLRModule, HMODULE hDBIModule, DWORD processId, LPCWSTR lpApplicationGroupId, int iDebuggerVersion, IUnknown **ppCordb)
+{
+ HRESULT hr = S_OK;
+
+ if (lpApplicationGroupId != NULL)
+ {
+ hr = CreateCoreDbgWithSandboxSupport(hCLRModule, hDBIModule, processId, lpApplicationGroupId, iDebuggerVersion, ppCordb);
+ }
+ else
+ {
+ hr = CreateCoreDbgWithoutSandboxSupport(hCLRModule, hDBIModule, processId, iDebuggerVersion, ppCordb);
+ }
+
+ return hr;
+}
+
//
// Helper class for RegisterForRuntimeStartup
//
@@ -210,6 +260,7 @@ class RuntimeStartupHelper
PVOID m_parameter;
#ifdef FEATURE_PAL
PVOID m_unregisterToken;
+ LPWSTR m_applicationGroupId;
#else
bool m_canceled;
HANDLE m_startupEvent;
@@ -224,7 +275,8 @@ public:
m_callback(pfnCallback),
m_parameter(parameter),
#ifdef FEATURE_PAL
- m_unregisterToken(NULL)
+ m_unregisterToken(NULL),
+ m_applicationGroupId(NULL)
#else
m_canceled(false),
m_startupEvent(NULL),
@@ -236,7 +288,12 @@ public:
~RuntimeStartupHelper()
{
-#ifndef FEATURE_PAL
+#ifdef FEATURE_PAL
+ if (m_applicationGroupId != NULL)
+ {
+ delete m_applicationGroupId;
+ }
+#else // FEATURE_PAL
if (m_startupEvent != NULL)
{
CloseHandle(m_startupEvent);
@@ -266,9 +323,20 @@ public:
#ifdef FEATURE_PAL
- HRESULT Register()
+ HRESULT Register(LPCWSTR lpApplicationGroupId)
{
- DWORD pe = PAL_RegisterForRuntimeStartup(m_processId, RuntimeStartupHandler, this, &m_unregisterToken);
+ if (lpApplicationGroupId != NULL)
+ {
+ int size = wcslen(lpApplicationGroupId) + 1;
+ m_applicationGroupId = new (nothrow) WCHAR[size];
+ if (m_applicationGroupId == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+ wcscpy_s(m_applicationGroupId, size, lpApplicationGroupId);
+ }
+
+ DWORD pe = PAL_RegisterForRuntimeStartup(m_processId, m_applicationGroupId, RuntimeStartupHandler, this, &m_unregisterToken);
if (pe != NO_ERROR)
{
return HRESULT_FROM_WIN32(pe);
@@ -297,7 +365,6 @@ public:
PAL_CPP_TRY
{
- FPCoreCLRCreateCordbObject fpCreate = NULL;
char dbiPath[MAX_LONGPATH];
char *pszLast = strrchr(pszModulePath, DIRECTORY_SEPARATOR_CHAR_A);
@@ -318,14 +385,7 @@ public:
goto exit;
}
- fpCreate = (FPCoreCLRCreateCordbObject)GetProcAddress(hMod, "CoreCLRCreateCordbObject");
- if (fpCreate == NULL)
- {
- hr = CORDBG_E_INCOMPATIBLE_PROTOCOL;
- goto exit;
- }
-
- HRESULT hr = fpCreate(CorDebugVersion_2_0, m_processId, hModule, &pCordb);
+ HRESULT hr = CreateCoreDbg(hModule, hMod, m_processId, m_applicationGroupId, CorDebugVersion_2_0, &pCordb);
_ASSERTE((pCordb == NULL) == FAILED(hr));
if (FAILED(hr))
{
@@ -358,7 +418,7 @@ public:
#else // FEATURE_PAL
- HRESULT Register()
+ HRESULT Register(LPCWSTR lpApplicationGroupId)
{
HRESULT hr = GetStartupNotificationEvent(m_processId, &m_startupEvent);
if (FAILED(hr))
@@ -623,7 +683,28 @@ StartupHelperThread(LPVOID p)
//-----------------------------------------------------------------------------
// Public API.
//
-// RegisterForRuntimeStartup -- executes the callback when the coreclr runtime
+// RegisterForRuntimeStartup -- Refer to RegisterForRuntimeStartupEx.
+// This method calls RegisterForRuntimeStartupEx with null application group ID value
+//
+// dwProcessId -- process id of the target process
+// pfnCallback -- invoked when coreclr runtime starts
+// parameter -- data to pass to callback
+// ppUnregisterToken -- pointer to put the UnregisterForRuntimeStartup token.
+//
+//-----------------------------------------------------------------------------
+HRESULT
+RegisterForRuntimeStartup(
+ __in DWORD dwProcessId,
+ __in PSTARTUP_CALLBACK pfnCallback,
+ __in PVOID parameter,
+ __out PVOID *ppUnregisterToken)
+{
+ return RegisterForRuntimeStartupEx(dwProcessId, NULL, pfnCallback, parameter, ppUnregisterToken);
+}
+//-----------------------------------------------------------------------------
+// Public API.
+//
+// RegisterForRuntimeStartupEx -- executes the callback when the coreclr runtime
// starts in the specified process. The callback is passed the proper ICorDebug
// instance for the version of the runtime or an error if something fails. This
// API works for launch and attach (and even the attach scenario if the runtime
@@ -643,14 +724,18 @@ StartupHelperThread(LPVOID p)
// supported.
//
// dwProcessId -- process id of the target process
+// lpApplicationGroupId - A string representing the application group ID of a sandboxed
+// process running in Mac. Pass NULL if the process is not
+// running in a sandbox and other platforms.
// pfnCallback -- invoked when coreclr runtime starts
// parameter -- data to pass to callback
// ppUnregisterToken -- pointer to put the UnregisterForRuntimeStartup token.
//
//-----------------------------------------------------------------------------
HRESULT
-RegisterForRuntimeStartup(
+RegisterForRuntimeStartupEx(
__in DWORD dwProcessId,
+ __in LPCWSTR lpApplicationGroupId,
__in PSTARTUP_CALLBACK pfnCallback,
__in PVOID parameter,
__out PVOID *ppUnregisterToken)
@@ -671,7 +756,7 @@ RegisterForRuntimeStartup(
}
else
{
- hr = helper->Register();
+ hr = helper->Register(lpApplicationGroupId);
if (FAILED(hr))
{
helper->Release();
@@ -1628,6 +1713,35 @@ CreateDebuggingInterfaceFromVersionEx(
__in LPCWSTR szDebuggeeVersion,
__out IUnknown ** ppCordb)
{
+ return CreateDebuggingInterfaceFromVersion2(iDebuggerVersion, szDebuggeeVersion, NULL, ppCordb);
+}
+
+//-----------------------------------------------------------------------------
+// Public API.
+// Given a version string, create the matching mscordbi.dll for it.
+// Create a managed debugging interface for the specified version.
+//
+// Parameters:
+// iDebuggerVersion - the version of interface the debugger (eg, Cordbg) expects.
+// szDebuggeeVersion - the version of the debuggee. This will map to a version of mscordbi.dll
+// lpApplicationGroupId - A string representing the application group ID of a sandboxed
+// process running in Mac. Pass NULL if the process is not
+// running in a sandbox and other platforms.
+// ppCordb - the outparameter used to return the debugging interface object.
+//
+// Return:
+// S_OK on success. *ppCordb will be non-null.
+// CORDBG_E_INCOMPATIBLE_PROTOCOL - if the proper DBI is not available. This can be a very common error if
+// the right debug pack is not installed.
+// else Error. (*ppCordb will be null)
+//-----------------------------------------------------------------------------
+HRESULT
+CreateDebuggingInterfaceFromVersion2(
+ __in int iDebuggerVersion,
+ __in LPCWSTR szDebuggeeVersion,
+ __in LPCWSTR szApplicationGroupId,
+ __out IUnknown ** ppCordb)
+{
PUBLIC_CONTRACT;
HRESULT hrIgnore = S_OK; // ignored HResult
@@ -1707,17 +1821,8 @@ CreateDebuggingInterfaceFromVersionEx(
//
// Step 3: Now that module is loaded, instantiate an ICorDebug.
- //
- fpCreate2 = (FPCoreCLRCreateCordbObject)GetProcAddress(hMod, "CoreCLRCreateCordbObject");
- if (fpCreate2 == NULL)
- {
- // New-style creation API didn't exist - this DBI must be the wrong version, for the Mix07 protocol
- hr = CORDBG_E_INCOMPATIBLE_PROTOCOL;
- goto Exit;
- }
-
- // Invoke to instantiate an ICorDebug. This export was introduced after the Mix'07 release.
- hr = fpCreate2(iDebuggerVersion, pidDebuggee, hmodTargetCLR, &pCordb);
+ //
+ hr = CreateCoreDbg(hmodTargetCLR, hMod, pidDebuggee, szApplicationGroupId, iDebuggerVersion, &pCordb);
_ASSERTE((pCordb == NULL) == FAILED(hr));
Exit:
diff --git a/src/dlls/dbgshim/dbgshim.h b/src/dlls/dbgshim/dbgshim.h
index 777c706ade..018058bbe0 100644
--- a/src/dlls/dbgshim/dbgshim.h
+++ b/src/dlls/dbgshim/dbgshim.h
@@ -35,6 +35,14 @@ RegisterForRuntimeStartup(
__out PVOID *ppUnregisterToken);
EXTERN_C HRESULT
+RegisterForRuntimeStartupEx(
+ __in DWORD dwProcessId,
+ __in LPCWSTR szApplicationGroupId,
+ __in PSTARTUP_CALLBACK pfnCallback,
+ __in PVOID parameter,
+ __out PVOID *ppUnregisterToken);
+
+EXTERN_C HRESULT
UnregisterForRuntimeStartup(
__in PVOID pUnregisterToken);
@@ -70,6 +78,13 @@ CreateDebuggingInterfaceFromVersionEx(
__out IUnknown ** ppCordb);
EXTERN_C HRESULT
+CreateDebuggingInterfaceFromVersion2(
+ __in int iDebuggerVersion,
+ __in LPCWSTR szDebuggeeVersion,
+ __in LPCWSTR szApplicationGroupId,
+ __out IUnknown ** ppCordb);
+
+EXTERN_C HRESULT
CreateDebuggingInterfaceFromVersion(
__in LPCWSTR szDebuggeeVersion,
__out IUnknown ** ppCordb);
diff --git a/src/dlls/dbgshim/dbgshim.ntdef b/src/dlls/dbgshim/dbgshim.ntdef
index 6915beebf9..1376cbcfe8 100644
--- a/src/dlls/dbgshim/dbgshim.ntdef
+++ b/src/dlls/dbgshim/dbgshim.ntdef
@@ -7,6 +7,7 @@ EXPORTS
ResumeProcess
CloseResumeHandle
RegisterForRuntimeStartup
+ RegisterForRuntimeStartupEx
UnregisterForRuntimeStartup
GetStartupNotificationEvent
EnumerateCLRs
@@ -14,4 +15,5 @@ EXPORTS
CreateVersionStringFromModule
CreateDebuggingInterfaceFromVersion
CreateDebuggingInterfaceFromVersionEx
+ CreateDebuggingInterfaceFromVersion2
CLRCreateInstance
diff --git a/src/dlls/dbgshim/dbgshim_unixexports.src b/src/dlls/dbgshim/dbgshim_unixexports.src
index b1cc36bc2f..013b739e6a 100644
--- a/src/dlls/dbgshim/dbgshim_unixexports.src
+++ b/src/dlls/dbgshim/dbgshim_unixexports.src
@@ -6,6 +6,7 @@ CreateProcessForLaunch
ResumeProcess
CloseResumeHandle
RegisterForRuntimeStartup
+RegisterForRuntimeStartupEx
UnregisterForRuntimeStartup
GetStartupNotificationEvent
EnumerateCLRs
@@ -13,4 +14,5 @@ CloseCLREnumeration
CreateVersionStringFromModule
CreateDebuggingInterfaceFromVersion
CreateDebuggingInterfaceFromVersionEx
+CreateDebuggingInterfaceFromVersion2
CLRCreateInstance
diff --git a/src/dlls/mscordbi/mscordbi.src b/src/dlls/mscordbi/mscordbi.src
index 0e14701243..9c3f928310 100644
--- a/src/dlls/mscordbi/mscordbi.src
+++ b/src/dlls/mscordbi/mscordbi.src
@@ -20,6 +20,7 @@ EXPORTS
OpenVirtualProcess2
CoreCLRCreateCordbObject private
+ CoreCLRCreateCordbObjectEx private
#if defined(FEATURE_DBGIPC_TRANSPORT_DI)
DllGetClassObject private
diff --git a/src/dlls/mscordbi/mscordbi_unixexports.src b/src/dlls/mscordbi/mscordbi_unixexports.src
index 88fa9cdab1..aeb92368a0 100644
--- a/src/dlls/mscordbi/mscordbi_unixexports.src
+++ b/src/dlls/mscordbi/mscordbi_unixexports.src
@@ -8,6 +8,7 @@ DllGetClassObject
; CoreClr API
CoreCLRCreateCordbObject
+CoreCLRCreateCordbObjectEx
; Out-of-proc creation path from the shim - ICLRDebugging
OpenVirtualProcessImpl
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h
index db2ce0d4fa..bb5e05f359 100644
--- a/src/pal/inc/pal.h
+++ b/src/pal/inc/pal.h
@@ -433,6 +433,7 @@ DWORD
PALAPI
PAL_RegisterForRuntimeStartup(
IN DWORD dwProcessId,
+ IN LPCWSTR lpApplicationGroupId,
IN PPAL_STARTUP_CALLBACK pfnCallback,
IN PVOID parameter,
OUT PVOID *ppUnregisterToken);
@@ -453,7 +454,7 @@ PALIMPORT
LPCSTR
PALAPI
PAL_GetApplicationGroupId();
-#endif // __APPLE__
+#endif
static const int MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH = MAX_PATH;
@@ -463,6 +464,7 @@ PALAPI
PAL_GetTransportPipeName(
OUT char *name,
IN DWORD id,
+ IN const char *applicationGroupId,
IN const char *suffix);
PALIMPORT
diff --git a/src/pal/src/include/pal/stackstring.hpp b/src/pal/src/include/pal/stackstring.hpp
index 89fcd009b2..133ec4a05e 100644
--- a/src/pal/src/include/pal/stackstring.hpp
+++ b/src/pal/src/include/pal/stackstring.hpp
@@ -109,7 +109,7 @@ private:
public:
StackString()
- : m_buffer(m_innerBuffer), m_size(0), m_count(0)
+ : m_buffer(m_innerBuffer), m_size(STACKCOUNT+1), m_count(0)
{
}
@@ -237,6 +237,7 @@ public:
m_count = 0;
NullTerminate();
}
+
~StackString()
{
DeleteBuffer();
@@ -247,8 +248,8 @@ public:
typedef StackString<32, CHAR> PathCharString;
typedef StackString<32, WCHAR> PathWCharString;
#else
-typedef StackString<260, CHAR> PathCharString;
-typedef StackString<260, WCHAR> PathWCharString;
+typedef StackString<MAX_PATH, CHAR> PathCharString;
+typedef StackString<MAX_PATH, WCHAR> PathWCharString;
#endif
#endif
diff --git a/src/pal/src/thread/process.cpp b/src/pal/src/thread/process.cpp
index 4358ca7cec..a964ee8829 100644
--- a/src/pal/src/thread/process.cpp
+++ b/src/pal/src/thread/process.cpp
@@ -81,6 +81,7 @@ SET_DEFAULT_DEBUG_CHANNEL(PROCESS); // some headers have code with asserts, so d
#ifdef __APPLE__
#include <sys/sysctl.h>
+#include <sys/posix_sem.h>
#endif
#ifdef __NetBSD__
@@ -195,10 +196,14 @@ PathCharString* gSharedFilesPath = nullptr;
// MacOSX 10.11: 31 -- Core 1.0 RC2 compatibility
#if defined(__NetBSD__)
#define CLR_SEM_MAX_NAMELEN 15
+#elif defined(__APPLE__)
+#define CLR_SEM_MAX_NAMELEN PSEMNAMLEN
#else
#define CLR_SEM_MAX_NAMELEN (NAME_MAX - 4)
#endif
+static_assert_no_msg(CLR_SEM_MAX_NAMELEN <= MAX_PATH);
+
// Function to call during PAL/process shutdown/abort
Volatile<PSHUTDOWN_CALLBACK> g_shutdownCallback = nullptr;
@@ -224,6 +229,31 @@ enum FILETYPE
FILE_DIR /*Directory*/
};
+#pragma pack(push,1)
+// When creating the semaphore name on Mac running in a sandbox, We reference this structure as a byte array
+// in order to encode its data into a string. Its important to make sure there is no padding between the fields
+// and also at the end of the buffer. Hence, this structure is defined inside a pack(1)
+struct UnambiguousProcessDescriptor
+{
+ UnambiguousProcessDescriptor()
+ {
+ }
+
+ UnambiguousProcessDescriptor(DWORD processId, UINT64 disambiguationKey)
+ {
+ Init(processId, disambiguationKey);
+ }
+
+ void Init(DWORD processId, UINT64 disambiguationKey)
+ {
+ m_processId = processId;
+ m_disambiguationKey = disambiguationKey;
+ }
+ UINT64 m_disambiguationKey;
+ DWORD m_processId;
+};
+#pragma pack(pop)
+
static
DWORD
PALAPI
@@ -243,6 +273,14 @@ PROCGetProcessStatus(
PROCESS_STATE *pps,
DWORD *pdwExitCode);
+static
+void
+CreateSemaphoreName(
+ char semName[CLR_SEM_MAX_NAMELEN],
+ LPCSTR semaphoreName,
+ const UnambiguousProcessDescriptor& unambiguousProcessDescriptor,
+ LPCSTR applicationGroupId);
+
static BOOL getFileName(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, PathCharString& lpFileName);
static char ** buildArgv(LPCWSTR lpCommandLine, PathCharString& lpAppPath, UINT *pnArg, BOOL prependLoader);
static BOOL getPath(PathCharString& lpFileName, PathCharString& lpPathFileName);
@@ -1520,13 +1558,14 @@ static bool IsCoreClrModule(const char* pModulePath)
// NetBSD limits semaphore names to 15 characters, including null (at least up to 7.99.25).
// Keep 31 length for Core 1.0 RC2 compatibility
#if defined(__NetBSD__)
-static const char* RuntimeStartupSemaphoreName = "/clrst%08llx";
-static const char* RuntimeContinueSemaphoreName = "/clrco%08llx";
+static const char* RuntimeSemaphoreNameFormat = "/clr%s%08llx";
#else
-static const char* RuntimeStartupSemaphoreName = "/clrst%08x%016llx";
-static const char* RuntimeContinueSemaphoreName = "/clrco%08x%016llx";
+static const char* RuntimeSemaphoreNameFormat = "/clr%s%08x%016llx";
#endif
+static const char* RuntimeStartupSemaphoreName = "st";
+static const char* RuntimeContinueSemaphoreName = "co";
+
#if defined(__NetBSD__)
static uint64_t HashSemaphoreName(uint64_t a, uint64_t b)
{
@@ -1547,6 +1586,11 @@ class PAL_RuntimeStartupHelper
DWORD m_threadId;
HANDLE m_threadHandle;
DWORD m_processId;
+#ifdef __APPLE__
+ char m_applicationGroupId[MAX_APPLICATION_GROUP_ID_LENGTH+1];
+#endif // __APPLE__
+ char m_startupSemName[CLR_SEM_MAX_NAMELEN];
+ char m_continueSemName[CLR_SEM_MAX_NAMELEN];
// A value that, used in conjunction with the process ID, uniquely identifies a process.
// See the format we use for debugger semaphore names for why this is necessary.
@@ -1559,6 +1603,15 @@ class PAL_RuntimeStartupHelper
// registered (m_callback) returns.
sem_t *m_continueSem;
+ LPCSTR GetApplicationGroupId() const
+ {
+#ifdef __APPLE__
+ return m_applicationGroupId[0] == '\0' ? nullptr : m_applicationGroupId;
+#else // __APPLE__
+ return nullptr;
+#endif // __APPLE__
+ }
+
public:
PAL_RuntimeStartupHelper(DWORD dwProcessId, PPAL_STARTUP_CALLBACK pfnCallback, PVOID parameter) :
m_ref(1),
@@ -1577,28 +1630,14 @@ public:
{
if (m_startupSem != SEM_FAILED)
{
- char startupSemName[CLR_SEM_MAX_NAMELEN];
- sprintf_s(startupSemName,
- sizeof(startupSemName),
- RuntimeStartupSemaphoreName,
- HashSemaphoreName(m_processId,
- m_processIdDisambiguationKey));
-
sem_close(m_startupSem);
- sem_unlink(startupSemName);
+ sem_unlink(m_startupSemName);
}
if (m_continueSem != SEM_FAILED)
{
- char continueSemName[CLR_SEM_MAX_NAMELEN];
- sprintf_s(continueSemName,
- sizeof(continueSemName),
- RuntimeContinueSemaphoreName,
- HashSemaphoreName(m_processId,
- m_processIdDisambiguationKey));
-
sem_close(m_continueSem);
- sem_unlink(continueSemName);
+ sem_unlink(m_continueSemName);
}
if (m_threadHandle != NULL)
@@ -1654,39 +1693,54 @@ public:
return pe;
}
- PAL_ERROR Register()
+ PAL_ERROR Register(LPCWSTR lpApplicationGroupId)
{
CPalThread *pThread = InternalGetCurrentThread();
- char startupSemName[CLR_SEM_MAX_NAMELEN];
- char continueSemName[CLR_SEM_MAX_NAMELEN];
PAL_ERROR pe = NO_ERROR;
+ BOOL ret;
+ UnambiguousProcessDescriptor unambiguousProcessDescriptor;
+
+#ifdef __APPLE__
+ if (lpApplicationGroupId != NULL)
+ {
+ /* Convert to ASCII */
+ int applicationGroupIdLength = WideCharToMultiByte(CP_ACP, 0, lpApplicationGroupId, -1, m_applicationGroupId, sizeof(m_applicationGroupId), NULL, NULL);
+ if (applicationGroupIdLength == 0)
+ {
+ pe = GetLastError();
+ TRACE("applicationGroupId: Failed to convert to multibyte string (%u)\n", pe);
+ if (pe == ERROR_INSUFFICIENT_BUFFER)
+ {
+ pe = ERROR_BAD_LENGTH;
+ }
+ goto exit;
+ }
+ }
+ else
+ {
+ // Indicate that group ID is not being used
+ m_applicationGroupId[0] = '\0';
+ }
+#endif // __APPLE__
// See semaphore name format for details about this value. We store it so that
// it can be used by the cleanup code that removes the semaphore with sem_unlink.
- BOOL ret = GetProcessIdDisambiguationKey(m_processId, &m_processIdDisambiguationKey);
+ ret = GetProcessIdDisambiguationKey(m_processId, &m_processIdDisambiguationKey);
// If GetProcessIdDisambiguationKey failed for some reason, it should set the value
// to 0. We expect that anyone else opening the semaphore name will also fail and thus
// will also try to use 0 as the value.
_ASSERTE(ret == TRUE || m_processIdDisambiguationKey == 0);
- sprintf_s(startupSemName,
- sizeof(startupSemName),
- RuntimeStartupSemaphoreName,
- HashSemaphoreName(m_processId,
- m_processIdDisambiguationKey));
-
- sprintf_s(continueSemName,
- sizeof(continueSemName),
- RuntimeContinueSemaphoreName,
- HashSemaphoreName(m_processId,
- m_processIdDisambiguationKey));
+ unambiguousProcessDescriptor.Init(m_processId, m_processIdDisambiguationKey);
+ CreateSemaphoreName(m_startupSemName, RuntimeStartupSemaphoreName, unambiguousProcessDescriptor, GetApplicationGroupId());
+ CreateSemaphoreName(m_continueSemName, RuntimeContinueSemaphoreName, unambiguousProcessDescriptor, GetApplicationGroupId());
- TRACE("PAL_RuntimeStartupHelper.Register creating startup '%s' continue '%s'\n", startupSemName, continueSemName);
+ TRACE("PAL_RuntimeStartupHelper.Register creating startup '%s' continue '%s'\n", m_startupSemName, m_continueSemName);
// Create the continue semaphore first so we don't race with PAL_NotifyRuntimeStarted. This open will fail if another
// debugger is trying to attach to this process because the name will already exist.
- m_continueSem = sem_open(continueSemName, O_CREAT | O_EXCL, S_IRWXU, 0);
+ m_continueSem = sem_open(m_continueSemName, O_CREAT | O_EXCL, S_IRWXU, 0);
if (m_continueSem == SEM_FAILED)
{
TRACE("sem_open(continue) failed: errno is %d (%s)\n", errno, strerror(errno));
@@ -1695,7 +1749,7 @@ public:
}
// Create the debuggee startup semaphore so the runtime (debuggee) knows to wait for a debugger connection.
- m_startupSem = sem_open(startupSemName, O_CREAT | O_EXCL, S_IRWXU, 0);
+ m_startupSem = sem_open(m_startupSemName, O_CREAT | O_EXCL, S_IRWXU, 0);
if (m_startupSem == SEM_FAILED)
{
TRACE("sem_open(startup) failed: errno is %d (%s)\n", errno, strerror(errno));
@@ -1771,7 +1825,7 @@ public:
{
char pipeName[MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH];
- PAL_GetTransportPipeName(pipeName, m_processId, "in");
+ PAL_GetTransportPipeName(pipeName, m_processId, GetApplicationGroupId(), "in");
struct stat buf;
if (stat(pipeName, &buf) == 0)
@@ -1886,6 +1940,9 @@ StartupHelperThread(LPVOID p)
Parameters:
dwProcessId - process id of runtime process
+ lpApplicationGroupId - A string representing the application group ID of a sandboxed
+ process running in Mac. Pass NULL if the process is not
+ running in a sandbox and other platforms.
pfnCallback - function to callback for coreclr module found
parameter - data to pass to callback
ppUnregisterToken - pointer to put PAL_UnregisterForRuntimeStartup token.
@@ -1906,6 +1963,7 @@ DWORD
PALAPI
PAL_RegisterForRuntimeStartup(
IN DWORD dwProcessId,
+ IN LPCWSTR lpApplicationGroupId,
IN PPAL_STARTUP_CALLBACK pfnCallback,
IN PVOID parameter,
OUT PVOID *ppUnregisterToken)
@@ -1917,7 +1975,7 @@ PAL_RegisterForRuntimeStartup(
// Create the debuggee startup semaphore so the runtime (debuggee) knows to wait for
// a debugger connection.
- PAL_ERROR pe = helper->Register();
+ PAL_ERROR pe = helper->Register(lpApplicationGroupId);
if (NO_ERROR != pe)
{
helper->Release();
@@ -1985,8 +2043,15 @@ PAL_NotifyRuntimeStarted()
// will also try to use 0 as the value.
_ASSERTE(ret == TRUE || processIdDisambiguationKey == 0);
- sprintf_s(startupSemName, sizeof(startupSemName), RuntimeStartupSemaphoreName, HashSemaphoreName(gPID, processIdDisambiguationKey));
- sprintf_s(continueSemName, sizeof(continueSemName), RuntimeContinueSemaphoreName, HashSemaphoreName(gPID, processIdDisambiguationKey));
+ UnambiguousProcessDescriptor unambiguousProcessDescriptor(gPID, processIdDisambiguationKey);
+ LPCSTR applicationGroupId =
+#ifdef __APPLE__
+ PAL_GetApplicationGroupId();
+#else
+ nullptr;
+#endif
+ CreateSemaphoreName(startupSemName, RuntimeStartupSemaphoreName, unambiguousProcessDescriptor, applicationGroupId);
+ CreateSemaphoreName(continueSemName, RuntimeContinueSemaphoreName, unambiguousProcessDescriptor, applicationGroupId);
TRACE("PAL_NotifyRuntimeStarted opening continue '%s' startup '%s'\n", continueSemName, startupSemName);
@@ -2041,7 +2106,78 @@ PAL_GetApplicationGroupId()
{
return gApplicationGroupId;
}
-#endif // __APPLE__
+
+// We use 7bits from each byte, so this computes the extra size we need to encode a given byte count
+constexpr int GetExtraEncodedAreaSize(UINT rawByteCount)
+{
+ return (rawByteCount+6)/7;
+}
+const int SEMAPHORE_ENCODED_NAME_EXTRA_LENGTH = GetExtraEncodedAreaSize(sizeof(UnambiguousProcessDescriptor));
+const int SEMAPHORE_ENCODED_NAME_LENGTH =
+ sizeof(UnambiguousProcessDescriptor) + /* For process ID + disambiguationKey */
+ SEMAPHORE_ENCODED_NAME_EXTRA_LENGTH; /* For base 255 extra encoding space */
+
+static_assert_no_msg(MAX_APPLICATION_GROUP_ID_LENGTH
+ + 1 /* For / */
+ + 2 /* For ST/CO name prefix */
+ + SEMAPHORE_ENCODED_NAME_LENGTH /* For encoded name string */
+ + 1 /* For null terminator */
+ <= CLR_SEM_MAX_NAMELEN);
+
+// In Apple we are limited by the length of the semaphore name. However, the characters which can be used in the
+// name can be anything between 1 and 255 (since 0 will terminate the string). Thus, we encode each byte b in
+// unambiguousProcessDescriptor as b ? b : 1, and mark an additional bit indicating if b is 0 or not. We use 7 bits
+// out of each extra byte so 1 bit will always be '1'. This will ensure that our extra bytes are never 0 which are
+// invalid characters. Thus we need an extra byte for each 7 input bytes. Hence, only extra 2 bytes for the name string.
+void EncodeSemaphoreName(char *encodedSemName, const UnambiguousProcessDescriptor& unambiguousProcessDescriptor)
+{
+ const unsigned char *buffer = (const unsigned char *)&unambiguousProcessDescriptor;
+ char *extraEncodingBits = encodedSemName + sizeof(UnambiguousProcessDescriptor);
+
+ // Reset the extra encoding bit area
+ for (int i=0; i<SEMAPHORE_ENCODED_NAME_EXTRA_LENGTH; i++)
+ {
+ extraEncodingBits[i] = 0x80;
+ }
+
+ // Encode each byte in unambiguousProcessDescriptor
+ for (int i=0; i<sizeof(UnambiguousProcessDescriptor); i++)
+ {
+ unsigned char b = buffer[i];
+ encodedSemName[i] = b ? b : 1;
+ extraEncodingBits[i/7] |= (b ? 0 : 1) << (i%7);
+ }
+}
+#endif
+
+void CreateSemaphoreName(char semName[CLR_SEM_MAX_NAMELEN], LPCSTR semaphoreName, const UnambiguousProcessDescriptor& unambiguousProcessDescriptor, LPCSTR applicationGroupId)
+{
+ int length = 0;
+
+#ifdef __APPLE__
+ if (applicationGroupId != nullptr)
+ {
+ // We assume here that applicationGroupId has been already tested for length and is less than MAX_APPLICATION_GROUP_ID_LENGTH
+ length = sprintf_s(semName, CLR_SEM_MAX_NAMELEN, "%s/%s", applicationGroupId, semaphoreName);
+ _ASSERTE(length > 0 && length < CLR_SEM_MAX_NAMELEN);
+
+ EncodeSemaphoreName(semName+length, unambiguousProcessDescriptor);
+ length += SEMAPHORE_ENCODED_NAME_LENGTH;
+ semName[length] = 0;
+ }
+ else
+#endif // __APPLE__
+ {
+ length = sprintf_s(
+ semName,
+ CLR_SEM_MAX_NAMELEN,
+ RuntimeSemaphoreNameFormat,
+ semaphoreName,
+ HashSemaphoreName(unambiguousProcessDescriptor.m_processId, unambiguousProcessDescriptor.m_disambiguationKey));
+ }
+
+ _ASSERTE(length > 0 && length < CLR_SEM_MAX_NAMELEN );
+}
/*++
Function:
@@ -2188,33 +2324,70 @@ PALAPI
PAL_GetTransportPipeName(
OUT char *name,
IN DWORD id,
+ IN const char *applicationGroupId,
IN const char *suffix)
{
*name = '\0';
DWORD dwRetVal = 0;
UINT64 disambiguationKey = 0;
- char formatBuffer[MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH];
+ PathCharString formatBufferString;
BOOL ret = GetProcessIdDisambiguationKey(id, &disambiguationKey);
+ char *formatBuffer = formatBufferString.OpenStringBuffer(MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH-1);
+ if (formatBuffer == nullptr)
+ {
+ ERROR("Out Of Memory");
+ return;
+ }
// If GetProcessIdDisambiguationKey failed for some reason, it should set the value
// to 0. We expect that anyone else making the pipe name will also fail and thus will
// also try to use 0 as the value.
_ASSERTE(ret == TRUE || disambiguationKey == 0);
-
- // Get a temp file location
- dwRetVal = ::GetTempPathA(MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH, formatBuffer);
- if (dwRetVal == 0)
+#ifdef __APPLE__
+ if (nullptr != applicationGroupId)
{
- ERROR("GetTempPath failed (0x%08x)", ::GetLastError());
- return;
+ // Verify the length of the application group ID
+ int applicationGroupIdLength = strlen(applicationGroupId);
+ if (applicationGroupIdLength > MAX_APPLICATION_GROUP_ID_LENGTH)
+ {
+ ERROR("The length of applicationGroupId is larger than MAX_APPLICATION_GROUP_ID_LENGTH");
+ return;
+ }
+
+ // In sandbox, all IPC files (locks, pipes) should be written to the application group
+ // container. The path returned by GetTempPathA will be unique for each process and cannot
+ // be used for IPC between two different processes
+ if (!GetApplicationContainerFolder(formatBufferString, applicationGroupId, applicationGroupIdLength))
+ {
+ ERROR("Out Of Memory");
+ return;
+ }
+
+ // Verify the size of the path won't exceed maximum allowed size
+ if (formatBufferString.GetCount() >= MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH)
+ {
+ ERROR("GetApplicationContainerFolder returned a path that was larger than MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH");
+ return;
+ }
}
- if (dwRetVal > MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH)
+ else
+#endif // __APPLE__
{
- ERROR("GetTempPath returned a path that was larger than MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH");
- return;
+ // Get a temp file location
+ dwRetVal = ::GetTempPathA(MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH, formatBuffer);
+ if (dwRetVal == 0)
+ {
+ ERROR("GetTempPath failed (0x%08x)", ::GetLastError());
+ return;
+ }
+ if (dwRetVal > MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH)
+ {
+ ERROR("GetTempPath returned a path that was larger than MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH");
+ return;
+ }
}
- if (strncat_s(formatBuffer, _countof(formatBuffer), PipeNameFormat, strlen(PipeNameFormat)) == STRUNCATE)
+ if (strncat_s(formatBuffer, MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH, PipeNameFormat, strlen(PipeNameFormat)) == STRUNCATE)
{
ERROR("TransportPipeName was larger than MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH");
return;