Skip to content

Commit e733c2f

Browse files
authored
[cdac] Implement ISOSDacInterface2::GetObjectExceptionData (#104343)
- Make cDac implement `ISOSDacInterface2` - Add `Exception` (managed type) to data descriptor - Add `GetExceptionData` to `Exception` contract which gets all the data that SOS-DAC API uses
1 parent 5795e8c commit e733c2f

File tree

12 files changed

+218
-17
lines changed

12 files changed

+218
-17
lines changed

docs/design/datacontracts/Exception.md

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,53 @@ This contract is for getting information about exceptions in the process.
44

55
## APIs of contract
66

7+
```csharp
8+
record struct ExceptionData(
9+
TargetPointer Message,
10+
TargetPointer InnerException,
11+
TargetPointer StackTrace,
12+
TargetPointer WatsonBuckets,
13+
TargetPointer StackTraceString,
14+
TargetPointer RemoteStackTraceString,
15+
int HResult,
16+
int XCode);
17+
```
18+
719
``` csharp
8-
TargetPointer GetExceptionInfo(TargetPointer exception, out TargetPointer nextNestedException);
20+
TargetPointer GetNestedExceptionInfo(TargetPointer exceptionInfoAddr, out TargetPointer nextNestedExceptionInfo);
21+
ExceptionData GetExceptionData(TargetPointer exceptionAddr)
922
```
1023

1124
## Version 1
1225

1326
Data descriptors used:
1427
- `ExceptionInfo`
28+
- `Exception`
1529

1630
``` csharp
17-
TargetPointer GetExceptionInfo(TargetPointer exception, out TargetPointer nextNestedException)
31+
TargetPointer GetNestedExceptionInfo(TargetPointer exceptionInfoAddr, out TargetPointer nextNestedExceptionInfo)
1832
{
19-
if (exception == TargetPointer.Null)
33+
if (exceptionInfo == TargetPointer.Null)
2034
throw new InvalidArgumentException();
2135

22-
nextNestedException = target.ReadPointer(address + /* ExceptionInfo::PreviousNestedInfo offset*/);
23-
TargetPointer thrownObjHandle = target.ReadPointer(address + /* ExceptionInfo::ThrownObject offset */);
36+
nextNestedException = target.ReadPointer(exceptionInfo + /* ExceptionInfo::PreviousNestedInfo offset*/);
37+
TargetPointer thrownObjHandle = target.ReadPointer(exceptionInfo + /* ExceptionInfo::ThrownObject offset */);
2438
return = thrownObjHandle != TargetPointer.Null
2539
? target.ReadPointer(thrownObjHandle)
2640
: TargetPointer.Null;
2741
}
42+
43+
ExceptionData GetExceptionData(TargetPointer exceptionAddr)
44+
{
45+
return new ExceptionData(
46+
target.ReadPointer(exceptionAddr + /* Exception::Message offset */),
47+
target.ReadPointer(exceptionAddr + /* Exception::InnerException offset */),
48+
target.ReadPointer(exceptionAddr + /* Exception::StackTrace offset */),
49+
target.ReadPointer(exceptionAddr + /* Exception::WatsonBuckets offset */),
50+
target.ReadPointer(exceptionAddr + /* Exception::StackTraceString offset */),
51+
target.ReadPointer(exceptionAddr + /* Exception::RemoteStackTraceString offset */),
52+
target.Read<int>(exceptionAddr + /* Exception::HResult offset */),
53+
target.Read<int>(exceptionAddr + /* Exception::XCode offset */),
54+
);
55+
}
2856
```

src/coreclr/debug/daccess/daccess.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5512,6 +5512,7 @@ ClrDataAccess::Initialize(void)
55125512
// Get SOS interfaces from the cDAC if available.
55135513
IUnknown* unk = m_cdac.SosInterface();
55145514
(void)unk->QueryInterface(__uuidof(ISOSDacInterface), (void**)&m_cdacSos);
5515+
(void)unk->QueryInterface(__uuidof(ISOSDacInterface2), (void**)&m_cdacSos2);
55155516
(void)unk->QueryInterface(__uuidof(ISOSDacInterface9), (void**)&m_cdacSos9);
55165517
}
55175518
}

src/coreclr/debug/daccess/dacimpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,6 +1235,7 @@ class ClrDataAccess
12351235
HRESULT GetNestedExceptionDataImpl(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS *exceptionObject, CLRDATA_ADDRESS *nextNestedException);
12361236
HRESULT GetMethodTableDataImpl(CLRDATA_ADDRESS mt, struct DacpMethodTableData *data);
12371237
HRESULT GetMethodTableForEEClassImpl (CLRDATA_ADDRESS eeClassReallyMT, CLRDATA_ADDRESS *value);
1238+
HRESULT GetObjectExceptionDataImpl(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data);
12381239

12391240
BOOL IsExceptionFromManagedCode(EXCEPTION_RECORD * pExceptionRecord);
12401241
#ifndef TARGET_UNIX
@@ -1424,6 +1425,7 @@ class ClrDataAccess
14241425

14251426
CDAC m_cdac;
14261427
NonVMComHolder<ISOSDacInterface> m_cdacSos;
1428+
NonVMComHolder<ISOSDacInterface2> m_cdacSos2;
14271429
NonVMComHolder<ISOSDacInterface9> m_cdacSos9;
14281430

14291431
#ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS

src/coreclr/debug/daccess/request.cpp

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4647,8 +4647,42 @@ HRESULT ClrDataAccess::GetObjectExceptionData(CLRDATA_ADDRESS objAddr, struct Da
46474647

46484648
SOSDacEnter();
46494649

4650-
PTR_ExceptionObject pObj = dac_cast<PTR_ExceptionObject>(TO_TADDR(objAddr));
4650+
if (m_cdacSos2 != NULL)
4651+
{
4652+
hr = m_cdacSos2->GetObjectExceptionData(objAddr, data);
4653+
if (FAILED(hr))
4654+
{
4655+
hr = GetObjectExceptionDataImpl(objAddr, data);
4656+
}
4657+
#ifdef _DEBUG
4658+
else
4659+
{
4660+
DacpExceptionObjectData dataLocal;
4661+
HRESULT hrLocal = GetObjectExceptionDataImpl(objAddr, &dataLocal);
4662+
_ASSERTE(hr == hrLocal);
4663+
_ASSERTE(data->Message == dataLocal.Message);
4664+
_ASSERTE(data->InnerException == dataLocal.InnerException);
4665+
_ASSERTE(data->StackTrace == dataLocal.StackTrace);
4666+
_ASSERTE(data->WatsonBuckets == dataLocal.WatsonBuckets);
4667+
_ASSERTE(data->StackTraceString == dataLocal.StackTraceString);
4668+
_ASSERTE(data->RemoteStackTraceString == dataLocal.RemoteStackTraceString);
4669+
_ASSERTE(data->HResult == dataLocal.HResult);
4670+
_ASSERTE(data->XCode == dataLocal.XCode);
4671+
}
4672+
#endif
4673+
}
4674+
else
4675+
{
4676+
hr = GetObjectExceptionDataImpl(objAddr, data);
4677+
}
46514678

4679+
SOSDacLeave();
4680+
return hr;
4681+
}
4682+
4683+
HRESULT ClrDataAccess::GetObjectExceptionDataImpl(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data)
4684+
{
4685+
PTR_ExceptionObject pObj = dac_cast<PTR_ExceptionObject>(TO_TADDR(objAddr));
46524686
data->Message = TO_CDADDR(dac_cast<TADDR>(pObj->GetMessage()));
46534687
data->InnerException = TO_CDADDR(dac_cast<TADDR>(pObj->GetInnerException()));
46544688
data->StackTrace = TO_CDADDR(dac_cast<TADDR>(pObj->GetStackTraceArrayObject()));
@@ -4657,10 +4691,7 @@ HRESULT ClrDataAccess::GetObjectExceptionData(CLRDATA_ADDRESS objAddr, struct Da
46574691
data->RemoteStackTraceString = TO_CDADDR(dac_cast<TADDR>(pObj->GetRemoteStackTraceString()));
46584692
data->HResult = pObj->GetHResult();
46594693
data->XCode = pObj->GetXCode();
4660-
4661-
SOSDacLeave();
4662-
4663-
return hr;
4694+
return S_OK;
46644695
}
46654696

46664697
HRESULT ClrDataAccess::IsRCWDCOMProxy(CLRDATA_ADDRESS rcwAddr, BOOL* isDCOMProxy)

src/coreclr/debug/runtimeinfo/datadescriptor.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,21 @@ CDAC_TYPE_FIELD(GCAllocContext, /*pointer*/, Pointer, offsetof(gc_alloc_context,
141141
CDAC_TYPE_FIELD(GCAllocContext, /*pointer*/, Limit, offsetof(gc_alloc_context, alloc_limit))
142142
CDAC_TYPE_END(GCAllocContext)
143143

144+
// Exception
145+
146+
// Use exact managed type field names for the descriptor as field names often can't change due to binary serialization or implicit diagnostic contracts
147+
CDAC_TYPE_BEGIN(Exception)
148+
CDAC_TYPE_INDETERMINATE(Exception)
149+
CDAC_TYPE_FIELD(Exception, /*pointer*/, _message, cdac_offsets<ExceptionObject>::_message)
150+
CDAC_TYPE_FIELD(Exception, /*pointer*/, _innerException, cdac_offsets<ExceptionObject>::_innerException)
151+
CDAC_TYPE_FIELD(Exception, /*pointer*/, _stackTrace, cdac_offsets<ExceptionObject>::_stackTrace)
152+
CDAC_TYPE_FIELD(Exception, /*pointer*/, _watsonBuckets, cdac_offsets<ExceptionObject>::_watsonBuckets)
153+
CDAC_TYPE_FIELD(Exception, /*pointer*/, _stackTraceString, cdac_offsets<ExceptionObject>::_stackTraceString)
154+
CDAC_TYPE_FIELD(Exception, /*pointer*/, _remoteStackTraceString, cdac_offsets<ExceptionObject>::_remoteStackTraceString)
155+
CDAC_TYPE_FIELD(Exception, /*int32*/, _HResult, cdac_offsets<ExceptionObject>::_HResult)
156+
CDAC_TYPE_FIELD(Exception, /*int32*/, _xcode, cdac_offsets<ExceptionObject>::_xcode)
157+
CDAC_TYPE_END(Exception)
158+
144159
CDAC_TYPE_BEGIN(ExceptionInfo)
145160
CDAC_TYPE_INDETERMINATE(ExceptionInfo)
146161
#if FEATURE_EH_FUNCLETS
@@ -152,6 +167,7 @@ CDAC_TYPE_FIELD(PreviousNestedInfo, /*pointer*/, PreviousNestedInfo, offsetof(Ex
152167
#endif
153168
CDAC_TYPE_END(ExceptionInfo)
154169

170+
155171
CDAC_TYPE_BEGIN(GCHandle)
156172
CDAC_TYPE_SIZE(sizeof(OBJECTHANDLE))
157173
CDAC_TYPE_END(GCHandle)

src/coreclr/vm/object.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2115,7 +2115,7 @@ class LoaderAllocatorObject : public Object
21152115
INT32 GetSlotsUsed();
21162116
void SetSlotsUsed(INT32 newSlotsUsed);
21172117
#endif // DACCESS_COMPILE
2118-
2118+
21192119
void SetNativeLoaderAllocator(LoaderAllocator * pLoaderAllocator)
21202120
{
21212121
LIMITED_METHOD_CONTRACT;
@@ -2355,6 +2355,21 @@ class ExceptionObject : public Object
23552355
void* _xptrs;
23562356
INT32 _xcode;
23572357
INT32 _HResult;
2358+
2359+
template<typename T> friend struct ::cdac_offsets;
2360+
};
2361+
2362+
template<>
2363+
struct cdac_offsets<ExceptionObject>
2364+
{
2365+
static constexpr size_t _message = offsetof(ExceptionObject, _message);
2366+
static constexpr size_t _innerException = offsetof(ExceptionObject, _innerException);
2367+
static constexpr size_t _stackTrace = offsetof(ExceptionObject, _stackTrace);
2368+
static constexpr size_t _watsonBuckets = offsetof(ExceptionObject, _watsonBuckets);
2369+
static constexpr size_t _stackTraceString = offsetof(ExceptionObject, _stackTraceString);
2370+
static constexpr size_t _remoteStackTraceString = offsetof(ExceptionObject, _remoteStackTraceString);
2371+
static constexpr size_t _HResult = offsetof(ExceptionObject, _HResult);
2372+
static constexpr size_t _xcode = offsetof(ExceptionObject, _xcode);
23582373
};
23592374

23602375
// Defined in Contracts.cs

src/native/managed/cdacreader/src/Contracts/Exception.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@
55

66
namespace Microsoft.Diagnostics.DataContractReader.Contracts;
77

8+
internal record struct ExceptionData(
9+
TargetPointer Message,
10+
TargetPointer InnerException,
11+
TargetPointer StackTrace,
12+
TargetPointer WatsonBuckets,
13+
TargetPointer StackTraceString,
14+
TargetPointer RemoteStackTraceString,
15+
int HResult,
16+
int XCode);
17+
818
internal interface IException : IContract
919
{
1020
static string IContract.Name { get; } = nameof(Exception);
@@ -17,7 +27,8 @@ static IContract IContract.Create(Target target, int version)
1727
};
1828
}
1929

20-
public virtual TargetPointer GetExceptionInfo(TargetPointer exception, out TargetPointer nextNestedException) => throw new NotImplementedException();
30+
public virtual TargetPointer GetNestedExceptionInfo(TargetPointer exception, out TargetPointer nextNestedException) => throw new NotImplementedException();
31+
public virtual ExceptionData GetExceptionData(TargetPointer managedException) => throw new NotImplementedException();
2132
}
2233

2334
internal readonly struct Exception : IException

src/native/managed/cdacreader/src/Contracts/Exception_1.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,24 @@ internal Exception_1(Target target)
1414
_target = target;
1515
}
1616

17-
TargetPointer IException.GetExceptionInfo(TargetPointer exception, out TargetPointer nextNestedException)
17+
TargetPointer IException.GetNestedExceptionInfo(TargetPointer exceptionInfoAddr, out TargetPointer nextNestedExceptionInfo)
1818
{
19-
Data.ExceptionInfo exceptionInfo = _target.ProcessedData.GetOrAdd<Data.ExceptionInfo>(exception);
20-
nextNestedException = exceptionInfo.PreviousNestedInfo;
19+
Data.ExceptionInfo exceptionInfo = _target.ProcessedData.GetOrAdd<Data.ExceptionInfo>(exceptionInfoAddr);
20+
nextNestedExceptionInfo = exceptionInfo.PreviousNestedInfo;
2121
return exceptionInfo.ThrownObject.Object;
2222
}
23+
24+
ExceptionData IException.GetExceptionData(TargetPointer exceptionAddr)
25+
{
26+
Data.Exception exception = _target.ProcessedData.GetOrAdd<Data.Exception>(exceptionAddr);
27+
return new ExceptionData(
28+
exception.Message,
29+
exception.InnerException,
30+
exception.StackTrace,
31+
exception.WatsonBuckets,
32+
exception.StackTraceString,
33+
exception.RemoteStackTraceString,
34+
exception.HResult,
35+
exception.XCode);
36+
}
2337
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Microsoft.Diagnostics.DataContractReader.Data;
5+
6+
internal sealed class Exception : IData<Exception>
7+
{
8+
static Exception IData<Exception>.Create(Target target, TargetPointer address)
9+
=> new Exception(target, address);
10+
11+
public Exception(Target target, TargetPointer address)
12+
{
13+
Target.TypeInfo type = target.GetTypeInfo(DataType.Exception);
14+
15+
Message = target.ReadPointer(address + (ulong)type.Fields["_message"].Offset);
16+
InnerException = target.ReadPointer(address + (ulong)type.Fields["_innerException"].Offset);
17+
StackTrace = target.ReadPointer(address + (ulong)type.Fields["_stackTrace"].Offset);
18+
WatsonBuckets = target.ReadPointer(address + (ulong)type.Fields["_watsonBuckets"].Offset);
19+
StackTraceString = target.ReadPointer(address + (ulong)type.Fields["_stackTraceString"].Offset);
20+
RemoteStackTraceString = target.ReadPointer(address + (ulong)type.Fields["_remoteStackTraceString"].Offset);
21+
HResult = target.Read<int>(address + (ulong)type.Fields["_HResult"].Offset);
22+
XCode = target.Read<int>(address + (ulong)type.Fields["_xcode"].Offset);
23+
}
24+
25+
public TargetPointer Message { get; init; }
26+
public TargetPointer InnerException { get; init; }
27+
public TargetPointer StackTrace { get; init; }
28+
public TargetPointer WatsonBuckets { get; init; }
29+
public TargetPointer StackTraceString { get; init; }
30+
public TargetPointer RemoteStackTraceString { get; init; }
31+
public int HResult { get; init; }
32+
public int XCode { get; init; }
33+
}

src/native/managed/cdacreader/src/DataType.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public enum DataType
2323
Thread,
2424
ThreadStore,
2525
GCAllocContext,
26+
Exception,
2627
ExceptionInfo,
2728
RuntimeThreadLocals,
2829
Module,

0 commit comments

Comments
 (0)