Skip to content

Commit ea17bc5

Browse files
leculverCopilot
andauthored
cDac fixes: StressLog address and exceptions flowing out of NativeAOT (#128845)
Fix two simple cDac bugs: 1. StressLogs were passing &g_pStressLog, but the original dac actually hands out StressLog::theLog, so we get the wrong address on the consumer side. I chose to just export &StressLog::theLog, but I could wrap this as (&g_pStressLog) and dereference in cDac if there's a preference for that. 2. The entrypoint for clrmd had no try/catch. Since cDac is nativeAOT compiled throwing an exception past the boundary would hard crash the process. I converted it to E_FAIL for now. The diff shows a lot of changes, but it's just adding a try/catches to entrypoints, and argument validation per copilot review. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent aef0e2b commit ea17bc5

3 files changed

Lines changed: 141 additions & 84 deletions

File tree

src/coreclr/nativeaot/Runtime/datadescriptor/datadescriptor.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ CDAC_GLOBAL(ObjectToMethodTableUnmask, T_UINT8, 3)
154154

155155
// StressLog globals (no module table in NativeAOT)
156156
CDAC_GLOBAL(StressLogEnabled, T_UINT8, 1)
157-
CDAC_GLOBAL_POINTER(StressLog, &g_pStressLog)
157+
CDAC_GLOBAL_POINTER(StressLog, &StressLog::theLog)
158158
CDAC_GLOBAL(StressLogHasModuleTable, T_UINT8, 0)
159159
CDAC_GLOBAL(StressLogChunkSize, T_UINT32, STRESSLOG_CHUNK_SIZE)
160160
CDAC_GLOBAL(StressLogValidChunkSig, T_UINT32, 0xCFCFCFCF)

src/coreclr/vm/datadescriptor/datadescriptor.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1592,7 +1592,7 @@ CDAC_GLOBAL_POINTER(TlsIndexBase, &::_tls_index)
15921592
#endif // TARGET_WINDOWS
15931593
#ifdef STRESS_LOG
15941594
CDAC_GLOBAL(StressLogEnabled, T_UINT8, 1)
1595-
CDAC_GLOBAL_POINTER(StressLog, &g_pStressLog)
1595+
CDAC_GLOBAL_POINTER(StressLog, &StressLog::theLog)
15961596
CDAC_GLOBAL(StressLogHasModuleTable, T_UINT8, 1)
15971597
CDAC_GLOBAL(StressLogMaxModules, T_UINT64, cdac_offsets<StressLog>::MAX_MODULES)
15981598
CDAC_GLOBAL(StressLogChunkSize, T_UINT32, STRESSLOG_CHUNK_SIZE)

src/native/managed/cdac/mscordaccore_universal/Entrypoints.cs

Lines changed: 139 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -22,70 +22,90 @@ private static unsafe int Init(
2222
void* delegateContext,
2323
IntPtr* handle)
2424
{
25-
// Build the allocVirtual delegate if the caller provided a callback
26-
ContractDescriptorTarget.AllocVirtualDelegate allocDelegate = (ulong size, out ulong allocatedAddress) =>
25+
try
2726
{
28-
allocatedAddress = 0;
29-
return HResults.E_NOTIMPL;
30-
};
27+
if (handle == null)
28+
return HResults.E_INVALIDARG;
29+
*handle = IntPtr.Zero;
3130

32-
if (allocVirtual != null)
33-
{
34-
allocDelegate = (ulong size, out ulong allocatedAddress) =>
31+
// Build the allocVirtual delegate if the caller provided a callback
32+
ContractDescriptorTarget.AllocVirtualDelegate allocDelegate = (ulong size, out ulong allocatedAddress) =>
3533
{
36-
if (size > uint.MaxValue)
37-
{
38-
allocatedAddress = 0;
39-
return HResults.E_INVALIDARG;
40-
}
41-
42-
fixed (ulong* addrPtr = &allocatedAddress)
43-
{
44-
return allocVirtual((uint)size, addrPtr, delegateContext);
45-
}
34+
allocatedAddress = 0;
35+
return HResults.E_NOTIMPL;
4636
};
47-
}
4837

49-
// TODO: [cdac] Better error code/details
50-
if (!ContractDescriptorTarget.TryCreate(
51-
descriptor,
52-
(address, buffer) =>
38+
if (allocVirtual != null)
5339
{
54-
fixed (byte* bufferPtr = buffer)
40+
allocDelegate = (ulong size, out ulong allocatedAddress) =>
5541
{
56-
return readFromTarget(address, bufferPtr, (uint)buffer.Length, delegateContext);
57-
}
58-
},
59-
(address, buffer) =>
60-
{
61-
fixed (byte* bufferPtr = buffer)
42+
if (size > uint.MaxValue)
43+
{
44+
allocatedAddress = 0;
45+
return HResults.E_INVALIDARG;
46+
}
47+
48+
fixed (ulong* addrPtr = &allocatedAddress)
49+
{
50+
return allocVirtual((uint)size, addrPtr, delegateContext);
51+
}
52+
};
53+
}
54+
55+
// TODO: [cdac] Better error code/details
56+
if (!ContractDescriptorTarget.TryCreate(
57+
descriptor,
58+
(address, buffer) =>
6259
{
63-
return writeToTarget(address, bufferPtr, (uint)buffer.Length, delegateContext);
64-
}
65-
},
66-
(threadId, contextFlags, buffer) =>
67-
{
68-
fixed (byte* bufferPtr = buffer)
60+
fixed (byte* bufferPtr = buffer)
61+
{
62+
return readFromTarget(address, bufferPtr, (uint)buffer.Length, delegateContext);
63+
}
64+
},
65+
(address, buffer) =>
6966
{
70-
return readThreadContext(threadId, contextFlags, (uint)buffer.Length, bufferPtr, delegateContext);
71-
}
72-
},
73-
allocDelegate,
74-
[Contracts.CoreCLRContracts.Register],
75-
out ContractDescriptorTarget? target))
76-
return -1;
67+
fixed (byte* bufferPtr = buffer)
68+
{
69+
return writeToTarget(address, bufferPtr, (uint)buffer.Length, delegateContext);
70+
}
71+
},
72+
(threadId, contextFlags, buffer) =>
73+
{
74+
fixed (byte* bufferPtr = buffer)
75+
{
76+
return readThreadContext(threadId, contextFlags, (uint)buffer.Length, bufferPtr, delegateContext);
77+
}
78+
},
79+
allocDelegate,
80+
[Contracts.CoreCLRContracts.Register],
81+
out ContractDescriptorTarget? target))
82+
return -1;
7783

78-
GCHandle gcHandle = GCHandle.Alloc(target);
79-
*handle = GCHandle.ToIntPtr(gcHandle);
80-
return 0;
84+
GCHandle gcHandle = GCHandle.Alloc(target);
85+
*handle = GCHandle.ToIntPtr(gcHandle);
86+
return 0;
87+
}
88+
catch (Exception ex)
89+
{
90+
int hr = ex.HResult;
91+
return hr < 0 ? hr : HResults.E_FAIL;
92+
}
8193
}
8294

8395
[UnmanagedCallersOnly(EntryPoint = $"{CDAC}free")]
8496
private static unsafe int Free(IntPtr handle)
8597
{
86-
GCHandle h = GCHandle.FromIntPtr(handle);
87-
h.Free();
88-
return 0;
98+
try
99+
{
100+
GCHandle h = GCHandle.FromIntPtr(handle);
101+
h.Free();
102+
return 0;
103+
}
104+
catch (Exception ex)
105+
{
106+
int hr = ex.HResult;
107+
return hr < 0 ? hr : HResults.E_FAIL;
108+
}
89109
}
90110

91111
/// <summary>
@@ -98,17 +118,31 @@ private static unsafe int Free(IntPtr handle)
98118
[UnmanagedCallersOnly(EntryPoint = $"{CDAC}create_sos_interface")]
99119
private static unsafe int CreateSosInterface(IntPtr handle, IntPtr legacyImplPtr, nint* obj)
100120
{
101-
Target? target = GCHandle.FromIntPtr(handle).Target as Target;
102-
if (target == null)
103-
return -1;
121+
try
122+
{
123+
if (obj == null)
124+
return HResults.E_INVALIDARG;
125+
*obj = IntPtr.Zero;
104126

105-
object? legacyImpl = legacyImplPtr != IntPtr.Zero
106-
? ComInterfaceMarshaller<ISOSDacInterface>.ConvertToManaged((void*)legacyImplPtr)
107-
: null;
108-
Legacy.SOSDacImpl impl = new(target, legacyImpl);
109-
nint ptr = (nint)ComInterfaceMarshaller<ISOSDacInterface>.ConvertToUnmanaged(impl);
110-
*obj = ptr;
111-
return 0;
127+
Target? target = GCHandle.FromIntPtr(handle).Target as Target;
128+
if (target == null)
129+
return HResults.E_INVALIDARG;
130+
131+
object? legacyImpl = legacyImplPtr != IntPtr.Zero
132+
? ComInterfaceMarshaller<ISOSDacInterface>.ConvertToManaged((void*)legacyImplPtr)
133+
: null;
134+
Legacy.SOSDacImpl impl = new(target, legacyImpl);
135+
nint ptr = (nint)ComInterfaceMarshaller<ISOSDacInterface>.ConvertToUnmanaged(impl);
136+
*obj = ptr;
137+
return 0;
138+
}
139+
catch (Exception ex)
140+
{
141+
if (obj != null)
142+
*obj = IntPtr.Zero;
143+
int hr = ex.HResult;
144+
return hr < 0 ? hr : HResults.E_FAIL;
145+
}
112146
}
113147

114148
/// <summary>
@@ -120,35 +154,45 @@ private static unsafe int CreateSosInterface(IntPtr handle, IntPtr legacyImplPtr
120154
[UnmanagedCallersOnly(EntryPoint = $"{CDAC}create_dacdbi_interface")]
121155
private static unsafe int CreateDacDbiInterface(IntPtr handle, IntPtr legacyImplPtr, nint* obj)
122156
{
123-
if (obj == null)
124-
return HResults.E_INVALIDARG;
125-
if (handle == IntPtr.Zero)
126-
{
127-
*obj = IntPtr.Zero;
128-
return HResults.E_NOTIMPL;
129-
}
130-
131-
Target? target = GCHandle.FromIntPtr(handle).Target as Target;
132-
if (target is null)
157+
try
133158
{
134-
*obj = IntPtr.Zero;
135-
return HResults.E_INVALIDARG;
136-
}
159+
if (obj == null)
160+
return HResults.E_INVALIDARG;
161+
if (handle == IntPtr.Zero)
162+
{
163+
*obj = IntPtr.Zero;
164+
return HResults.E_NOTIMPL;
165+
}
137166

138-
object? legacyObj = null;
139-
if (legacyImplPtr != IntPtr.Zero)
140-
{
141-
legacyObj = ComInterfaceMarshaller<IDacDbiInterface>.ConvertToManaged((void*)legacyImplPtr);
142-
if (legacyObj is not Legacy.IDacDbiInterface)
167+
Target? target = GCHandle.FromIntPtr(handle).Target as Target;
168+
if (target is null)
143169
{
144170
*obj = IntPtr.Zero;
145-
return HResults.COR_E_INVALIDCAST; // E_NOINTERFACE
171+
return HResults.E_INVALIDARG;
172+
}
173+
174+
object? legacyObj = null;
175+
if (legacyImplPtr != IntPtr.Zero)
176+
{
177+
legacyObj = ComInterfaceMarshaller<IDacDbiInterface>.ConvertToManaged((void*)legacyImplPtr);
178+
if (legacyObj is not Legacy.IDacDbiInterface)
179+
{
180+
*obj = IntPtr.Zero;
181+
return HResults.COR_E_INVALIDCAST; // E_NOINTERFACE
182+
}
146183
}
147-
}
148184

149-
Legacy.DacDbiImpl impl = new(target, legacyObj);
150-
*obj = (nint)ComInterfaceMarshaller<IDacDbiInterface>.ConvertToUnmanaged(impl);
151-
return HResults.S_OK;
185+
Legacy.DacDbiImpl impl = new(target, legacyObj);
186+
*obj = (nint)ComInterfaceMarshaller<IDacDbiInterface>.ConvertToUnmanaged(impl);
187+
return HResults.S_OK;
188+
}
189+
catch (Exception ex)
190+
{
191+
if (obj != null)
192+
*obj = IntPtr.Zero;
193+
int hr = ex.HResult;
194+
return hr < 0 ? hr : HResults.E_FAIL;
195+
}
152196
}
153197

154198
[UnmanagedCallersOnly(EntryPoint = "CLRDataCreateInstanceWithFallback")]
@@ -170,6 +214,19 @@ private static unsafe int CLRDataCreateInstanceImpl(Guid* pIID, IntPtr /*ICLRDat
170214
return HResults.E_INVALIDARG;
171215
*iface = null;
172216

217+
try
218+
{
219+
return CLRDataCreateInstanceCore(pIID, pLegacyTarget, pLegacyImpl, iface);
220+
}
221+
catch (Exception ex)
222+
{
223+
int hr = ex.HResult;
224+
return hr < 0 ? hr : HResults.E_FAIL;
225+
}
226+
}
227+
228+
private static unsafe int CLRDataCreateInstanceCore(Guid* pIID, IntPtr /*ICLRDataTarget*/ pLegacyTarget, IntPtr pLegacyImpl, void** iface)
229+
{
173230
object legacyTarget = ComInterfaceMarshaller<ICLRDataTarget>.ConvertToManaged((void*)pLegacyTarget)!;
174231
object? legacyImpl = pLegacyImpl != IntPtr.Zero ?
175232
ComInterfaceMarshaller<ISOSDacInterface>.ConvertToManaged((void*)pLegacyImpl) : null;

0 commit comments

Comments
 (0)