Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions docs/design/datacontracts/Debugger.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ This contract is for reading debugger state from the target process, including i
## APIs of contract

```csharp
record struct DebuggerData(uint DefinesBitField, uint MDStructuresVersion);
record struct DebuggerData(bool IsLeftSideInitialized, uint DefinesBitField, uint MDStructuresVersion);
```

```csharp
bool TryGetDebuggerData(out DebuggerData data);
int GetAttachStateFlags();
void MarkDebuggerAttachPending();
void MarkDebuggerAttached(bool fAttached);
bool MetadataUpdatesApplied();
void RequestSyncAtEvent();
void SetSendExceptionsOutsideOfJMC(bool sendExceptionsOutsideOfJMC);
Expand All @@ -26,6 +28,7 @@ The contract depends on the following globals
| --- | --- | --- |
| `Debugger` | TargetPointer | Address of the pointer to the Debugger instance (`&g_pDebugger`) |
| `CLRJitAttachState` | TargetPointer | Pointer to the CLR JIT attach state flags |
Comment thread
rcj1 marked this conversation as resolved.
| `CORDebuggerControlFlags` | TargetPointer | Pointer to `g_CORDebuggerControlFlags` |
Comment thread
rcj1 marked this conversation as resolved.
| `MetadataUpdatesApplied` | TargetPointer | Pointer to the g_metadataUpdatesApplied flag |

The contract additionally depends on these data descriptors
Expand All @@ -42,6 +45,13 @@ The contract additionally depends on these data descriptors
| `DebuggerRCThread` | `DCB` | Pointer to `DebuggerIPCControlBlock` |

```csharp

private enum DebuggerControlFlag_1 : uint
{
PendingAttach = 0x0100,
Attached = 0x0200,
}

bool TryGetDebuggerData(out DebuggerData data)
{
data = default;
Expand All @@ -53,10 +63,9 @@ bool TryGetDebuggerData(out DebuggerData data)
TargetPointer debuggerPtr = target.ReadPointer(debuggerPtrPtr);
if (debuggerPtr == TargetPointer.Null)
return false;
int leftSideInitialized = target.Read<int>(debuggerPtr + /* Debugger::LeftSideInitialized offset */);
if (leftSideInitialized == 0)
return false;
bool leftSideInitialized = target.Read<int>(debuggerPtr + /* Debugger::LeftSideInitialized offset */) != 0;
data = new DebuggerData(
IsLeftSideInitialized: leftSideInitialized,
DefinesBitField: target.Read<uint>(debuggerPtr + /* Debugger::Defines offset */),
MDStructuresVersion: target.Read<uint>(debuggerPtr + /* Debugger::MDStructuresVersion offset */));
return true;
Expand All @@ -68,6 +77,17 @@ int GetAttachStateFlags()
return (int)target.Read<uint>(addr);
}

void MarkDebuggerAttachPending()
{
/* OR global "CORDebuggerControlFlags" with PendingAttach flag */;
}

void MarkDebuggerAttached(bool fAttached)
{
// if fAttached is true, OR global "CORDebuggerControlFlags" with Attached flag
// otherwise clear both Attached and PendingAttach flags
}

bool MetadataUpdatesApplied()
{
if (target.TryReadGlobalPointer("MetadataUpdatesApplied", out TargetPointer addr))
Expand Down
8 changes: 1 addition & 7 deletions src/coreclr/debug/di/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ bool IsLegalFatalError(HRESULT hr)
{
return
(hr == CORDBG_E_INCOMPATIBLE_PROTOCOL) ||
(hr == CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS) ||
(hr == CORDBG_E_INCOMPATIBLE_PLATFORMS) ||
(hr == CORDBG_E_MISMATCHED_CORWKS_AND_DACWKS_DLLS) ||
// This should only happen in the case of a security attack on us.
Expand Down Expand Up @@ -7465,11 +7464,6 @@ void CordbProcess::VerifyControlBlock()
ThrowHR(CORDBG_E_INCOMPATIBLE_PROTOCOL);
#endif

if (GetDCB()->m_bHostingInFiber)
{
ThrowHR(CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS);
}

_ASSERTE(!GetDCB()->m_rightSideShouldCreateHelperThread);
} // CordbProcess::VerifyControlBlock
Comment thread
rcj1 marked this conversation as resolved.

Expand Down Expand Up @@ -8377,7 +8371,7 @@ void CordbProcess::UnrecoverableError(HRESULT errorHR,

CONSISTENCY_CHECK_MSGF(IsLegalFatalError(errorHR), ("Unrecoverable internal error: hr=0x%08x!", errorHR));

if (!IsLegalFatalError(errorHR) || (errorHR != CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS))
if (!IsLegalFatalError(errorHR))
{
// This will throw everything into a Zombie state. The ATT_ macros will check this and fail immediately.
m_unrecoverableError = true;
Expand Down
9 changes: 0 additions & 9 deletions src/coreclr/debug/ee/rcthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,6 @@ HRESULT DebuggerIPCControlBlock::Init(
#else
m_checkedBuild = false;
#endif
m_bHostingInFiber = false;

// Are we in fiber mode? In Whidbey, we do not support launch a fiber mode process
// nor do we support attach to a fiber mode process.
//
if (g_CORDebuggerControlFlags & DBCF_FIBERMODE)
{
m_bHostingInFiber = true;
}

#if !defined(FEATURE_DBGIPC_TRANSPORT_VM)
// Copy RSEA and RSER into the control block.
Expand Down
10 changes: 2 additions & 8 deletions src/coreclr/debug/inc/dbgipcevents.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,7 @@ struct MSLAYOUT DebuggerIPCControlBlock

// This next stuff fits in a DWORD.
bool m_checkedBuild; // CLR build type for the Left Side.
// using the first padding byte to indicate if hosted in fiber mode.
// We actually just need one bit. So if needed, can turn this to a bit.
// BYTE padding1;
bool m_bHostingInFiber;
BYTE padding1;
BYTE padding2;
BYTE padding3;
Comment thread
rcj1 marked this conversation as resolved.

Expand Down Expand Up @@ -303,10 +300,7 @@ struct MSLAYOUT DebuggerIPCControlBlockTransport

// This next stuff fits in a DWORD.
bool m_checkedBuild; // CLR build type for the Left Side.
// using the first padding byte to indicate if hosted in fiber mode.
// We actually just need one bit. So if needed, can turn this to a bit.
// BYTE padding1;
bool m_bHostingInFiber;
BYTE padding1;
BYTE padding2;
BYTE padding3;

Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/debug/shared/dbgtransportsession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,6 @@ void MarshalDCBTransportToDCB(DebuggerIPCControlBlockTransport* pIn, DebuggerIPC
pOut->m_verMajor = pIn->m_verMajor;
pOut->m_verMinor = pIn->m_verMinor;
pOut->m_checkedBuild = pIn->m_checkedBuild;
Comment thread
rcj1 marked this conversation as resolved.
pOut->m_bHostingInFiber = pIn->m_bHostingInFiber;
pOut->padding2 = pIn->padding2;
pOut->padding3 = pIn->padding3;

Expand Down Expand Up @@ -448,7 +447,6 @@ void MarshalDCBToDCBTransport(DebuggerIPCControlBlock* pIn, DebuggerIPCControlBl
pOut->m_verMajor = pIn->m_verMajor;
pOut->m_verMinor = pIn->m_verMinor;
pOut->m_checkedBuild = pIn->m_checkedBuild;
pOut->m_bHostingInFiber = pIn->m_bHostingInFiber;
pOut->padding2 = pIn->padding2;
pOut->padding3 = pIn->padding3;

Expand Down
12 changes: 2 additions & 10 deletions src/coreclr/inc/cordbpriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,8 @@ enum DebuggerLaunchSetting
enum DebuggerControlFlag
{
DBCF_NORMAL_OPERATION = 0x0000,

DBCF_USER_MASK = 0x00FF,
DBCF_GENERATE_DEBUG_CODE = 0x0001,
DBCF_PROFILER_ENABLED = 0x0020,
// DBCF_ACTIVATE_REMOTE_DEBUGGING = 0x0040, Deprecated. DO NOT USE

DBCF_INTERNAL_MASK = 0xFF00,
DBCF_PENDING_ATTACH = 0x0100,
DBCF_ATTACHED = 0x0200,
DBCF_FIBERMODE = 0x0400
DBCF_PENDING_ATTACH = 0x0100, // [cDAC] [Debugger] : Contract depends on this value.
DBCF_ATTACHED = 0x0200, // [cDAC] [Debugger] : Contract depends on this value.
};

//
Expand Down
6 changes: 0 additions & 6 deletions src/coreclr/inc/corerror.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1797,12 +1797,6 @@
<Comment> Trying to shutdown out of order. </Comment>
</HRESULT>

<HRESULT NumericValue="0x80131c16">
<SymbolicName>CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS</SymbolicName>
<Message>"Debugging fiber mode managed process is not supported."</Message>
<Comment> For Whidbey, we don't support debugging fiber mode managed process </Comment>
</HRESULT>

<HRESULT NumericValue="0x80131c17">
<SymbolicName>CORDBG_E_MUST_BE_IN_CREATE_PROCESS</SymbolicName>
<Message>"Must be in context of CreateProcess callback to perform requested operation."</Message>
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/pal/prebuilt/corerror/mscorurt.rc
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ BEGIN
MSG_FOR_URT_HR(CORDBG_E_CANNOT_BE_ON_ATTACH) "Requested operation cannot be performed during an attach operation."
MSG_FOR_URT_HR(CORDBG_E_NGEN_NOT_SUPPORTED) "NGEN is not supported."
MSG_FOR_URT_HR(CORDBG_E_ILLEGAL_SHUTDOWN_ORDER) "Trying to shutdown out of order."
MSG_FOR_URT_HR(CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS) "Debugging fiber mode managed process is not supported."
MSG_FOR_URT_HR(CORDBG_E_MUST_BE_IN_CREATE_PROCESS) "Must be in context of CreateProcess callback to perform requested operation."
MSG_FOR_URT_HR(CORDBG_E_DETACH_FAILED_OUTSTANDING_EVALS) "All outstanding func-evals have not completed, detaching is not allowed at this time."
MSG_FOR_URT_HR(CORDBG_E_DETACH_FAILED_OUTSTANDING_STEPPERS) "All outstanding steppers have not been closed, detaching is not allowed at this time."
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/pal/prebuilt/inc/corerror.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,6 @@
#define CORDBG_E_CANNOT_BE_ON_ATTACH EMAKEHR(0x1c13)
#define CORDBG_E_NGEN_NOT_SUPPORTED EMAKEHR(0x1c14)
#define CORDBG_E_ILLEGAL_SHUTDOWN_ORDER EMAKEHR(0x1c15)
#define CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS EMAKEHR(0x1c16)
#define CORDBG_E_MUST_BE_IN_CREATE_PROCESS EMAKEHR(0x1c17)
#define CORDBG_E_DETACH_FAILED_OUTSTANDING_EVALS EMAKEHR(0x1c18)
#define CORDBG_E_DETACH_FAILED_OUTSTANDING_STEPPERS EMAKEHR(0x1c19)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1348,6 +1348,7 @@ CDAC_GLOBAL_POINTER(EEConfig, &::g_pConfig)
#if defined(DEBUGGING_SUPPORTED) && !defined(TARGET_WASM)
CDAC_GLOBAL_POINTER(Debugger, &::g_pDebugger)
CDAC_GLOBAL_POINTER(CLRJitAttachState, &::CLRJitAttachState)
CDAC_GLOBAL_POINTER(CORDebuggerControlFlags, &::g_CORDebuggerControlFlags)
#endif // DEBUGGING_SUPPORTED && !TARGET_WASM
#ifdef FEATURE_METADATA_UPDATER
CDAC_GLOBAL_POINTER(MetadataUpdatesApplied, &::g_metadataUpdatesApplied)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@

namespace Microsoft.Diagnostics.DataContractReader.Contracts;

public record struct DebuggerData(uint DefinesBitField, uint MDStructuresVersion);
public record struct DebuggerData(bool IsLeftSideInitialized, uint DefinesBitField, uint MDStructuresVersion);

public interface IDebugger : IContract
{
static string IContract.Name { get; } = nameof(Debugger);

bool TryGetDebuggerData(out DebuggerData data) => throw new NotImplementedException();
int GetAttachStateFlags() => throw new NotImplementedException();
void MarkDebuggerAttachPending() => throw new NotImplementedException();
void MarkDebuggerAttached(bool fAttached) => throw new NotImplementedException();
bool MetadataUpdatesApplied() => throw new NotImplementedException();
Comment thread
rcj1 marked this conversation as resolved.
void RequestSyncAtEvent() => throw new NotImplementedException();
void SetSendExceptionsOutsideOfJMC(bool sendExceptionsOutsideOfJMC) => throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public static class Globals
public const string GCThread = nameof(GCThread);
public const string Debugger = nameof(Debugger);
public const string CLRJitAttachState = nameof(CLRJitAttachState);
public const string CORDebuggerControlFlags = nameof(CORDebuggerControlFlags);
public const string MetadataUpdatesApplied = nameof(MetadataUpdatesApplied);
public const string EEConfig = nameof(EEConfig);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts;

internal readonly struct Debugger_1 : IDebugger
{
private enum DebuggerControlFlag_1 : uint
{
PendingAttach = 0x0100,
Attached = 0x0200,
}

private readonly Target _target;

internal Debugger_1(Target target)
Expand All @@ -31,10 +37,7 @@ bool IDebugger.TryGetDebuggerData(out DebuggerData data)
return false;

Data.Debugger debugger = _target.ProcessedData.GetOrAdd<Data.Debugger>(debuggerAddress);
if (debugger.LeftSideInitialized == 0)
return false;

data = new DebuggerData(debugger.Defines, debugger.MDStructuresVersion);
data = new DebuggerData(debugger.LeftSideInitialized != 0, debugger.Defines, debugger.MDStructuresVersion);
return true;
}

Expand All @@ -44,6 +47,27 @@ int IDebugger.GetAttachStateFlags()
return (int)_target.Read<uint>(addr.Value);
}

void IDebugger.MarkDebuggerAttachPending()
{
TargetPointer addr = _target.ReadGlobalPointer(Constants.Globals.CORDebuggerControlFlags);
uint currentFlags = _target.Read<uint>(addr.Value);
_target.Write<uint>(addr.Value, currentFlags | (uint)DebuggerControlFlag_1.PendingAttach);
}

void IDebugger.MarkDebuggerAttached(bool fAttached)
{
TargetPointer addr = _target.ReadGlobalPointer(Constants.Globals.CORDebuggerControlFlags);
Comment thread
rcj1 marked this conversation as resolved.
uint currentFlags = _target.Read<uint>(addr.Value);
if (fAttached)
{
_target.Write<uint>(addr.Value, currentFlags | (uint)DebuggerControlFlag_1.Attached);
}
else
{
_target.Write<uint>(addr.Value, currentFlags & ~((uint)DebuggerControlFlag_1.Attached | (uint)DebuggerControlFlag_1.PendingAttach));
}
Comment thread
rcj1 marked this conversation as resolved.
Comment thread
rcj1 marked this conversation as resolved.
}

bool IDebugger.MetadataUpdatesApplied()
{
if (_target.TryReadGlobalPointer(Constants.Globals.MetadataUpdatesApplied, out TargetPointer? addr))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public int IsLeftSideInitialized(Interop.BOOL* pResult)
int hr = HResults.S_OK;
try
{
*pResult = _target.Contracts.Debugger.TryGetDebuggerData(out _) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE;
*pResult = _target.Contracts.Debugger.TryGetDebuggerData(out Contracts.DebuggerData data) && data.IsLeftSideInitialized ? Interop.BOOL.TRUE : Interop.BOOL.FALSE;
}
catch (System.Exception ex)
{
Expand Down Expand Up @@ -283,10 +283,66 @@ public int SetSendExceptionsOutsideOfJMC(Interop.BOOL sendExceptionsOutsideOfJMC
}

public int MarkDebuggerAttachPending()
=> LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.MarkDebuggerAttachPending() : HResults.E_NOTIMPL;
{
int hr = HResults.S_OK;
try
{
Contracts.IDebugger debugger = _target.Contracts.Debugger;
if (debugger.TryGetDebuggerData(out _))
{
debugger.MarkDebuggerAttachPending();
}
else
{
throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_NOTREADY)!;
}
Comment thread
rcj1 marked this conversation as resolved.
}
catch (System.Exception ex)
{
hr = ex.HResult;
}

#if DEBUG
if (_legacy is not null)
{
int hrLocal = _legacy.MarkDebuggerAttachPending();
Debug.ValidateHResult(hr, hrLocal);
}
#endif

return hr;
}

public int MarkDebuggerAttached(Interop.BOOL fAttached)
=> LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.MarkDebuggerAttached(fAttached) : HResults.E_NOTIMPL;
{
int hr = HResults.S_OK;
try
{
Contracts.IDebugger debugger = _target.Contracts.Debugger;
if (debugger.TryGetDebuggerData(out _))
{
debugger.MarkDebuggerAttached(fAttached != Interop.BOOL.FALSE);
}
else if (fAttached != Interop.BOOL.FALSE)
{
throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_NOTREADY)!;
Comment thread
rcj1 marked this conversation as resolved.
}
}
Comment thread
rcj1 marked this conversation as resolved.
catch (System.Exception ex)
{
hr = ex.HResult;
}

#if DEBUG
if (_legacy is not null)
{
int hrLocal = _legacy.MarkDebuggerAttached(fAttached);
Debug.ValidateHResult(hr, hrLocal);
}
#endif

return hr;
}

public int Hijack(ulong vmThread, uint dwThreadId, nint pRecord, nint pOriginalContext, uint cbSizeContext, int reason, nint pUserData, ulong* pRemoteContextAddr)
=> LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.Hijack(vmThread, dwThreadId, pRecord, pOriginalContext, cbSizeContext, reason, pUserData, pRemoteContextAddr) : HResults.E_NOTIMPL;
Expand Down
Loading
Loading