-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[cDAC] Implement GCCover portion of SOSDacImpl::GetMethodDescData #110322
base: main
Are you sure you want to change the base?
Conversation
7a104d0
to
3cf533a
Compare
e5799e7
to
5e9c139
Compare
// In certain minidumps, we won't save the gccover information. | ||
// (it would be unwise to do so, it is heavy and not a customer scenario). | ||
Target.TypeInfo gcCoverageInfo = _target.GetTypeInfo(DataType.GCCoverageInfo); | ||
data->GCStressCodeCopy = gcCoverAddr.Value.Value + (ulong)gcCoverageInfo.Fields["SavedCode"].Offset; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like having the inline string here, but I wasn't sure where to store this field.
{ | ||
IGCCover IContractFactory<IGCCover>.CreateContract(Target target, int version) | ||
{ | ||
return version switch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like how you went for the switch
despite only having an if/else
condition to have it ready for the likely new versions in the future 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't really take credit for this. Aleksey used this factory pattern in the other contracts a few months ago. I do agree its a good approach. 😄
...managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/GCCover_1.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Adds
IGCCover
contract to get access to gc coverage field from native code version.
- While this isn't strictly necessary, the API could live on the CodeVersions contract, I thought it made more sense to keep them logically separated.
This seems to be in an in-between state now, since there is a GCCover
contract that gives the separation from the CodeVersions
contract, but the RuntimeTypeSystem
now also deals with GC coverage info.
I think we should either:
- Add a
GCCover
contract that handles getting GC coverage info from a native code version and from a method desc- I think this would be the logical separation that you mentioned
- Add methods to the
CodeVersions
andRuntimeTypeSystem
contracts for getting GC coverage info (no newGCCover
contract)- Since we don't expect the question of 'is GC cover enabled' to be a scenario for a consumer, so it may make sense to have GC coverage info at a lower level instead of elevated to its own contract
4fc1b6f
to
635a966
Compare
internal static Target CreateTarget( | ||
MockTarget.Architecture arch, | ||
MockCodeVersions builder, | ||
Mock<IRuntimeTypeSystem> mockRuntimeTypeSystem) | ||
{ | ||
TestPlaceholderTarget target = new TestPlaceholderTarget( | ||
arch, | ||
builder.Builder.GetReadContext().ReadFromTarget, | ||
builder.Types); | ||
|
||
IContractFactory<ICodeVersions> cvfactory = new CodeVersionsFactory(); | ||
ContractRegistry reg = Mock.Of<ContractRegistry>( | ||
c => c.CodeVersions == cvfactory.CreateContract(target, 1) | ||
&& c.RuntimeTypeSystem == mockRuntimeTypeSystem.Object); | ||
target.SetContracts(reg); | ||
return target; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previous CodeVersion tests use custom "mock" classes. Now that we have Moq
integrated, I used it to create the new GCStressCodeCopy tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for this change, but might be nice to switch the previous/existing tests to this as well.
I agree with this assessment. I ended up going with the second option, moving the API to I think having a separate GCCover contract which handles the method desc and code version node fetching would be confusing as it directly depends on two underlying areas which should be accessed through their respective contracts. |
``` | ||
|
||
1. If `codeVersionHandle` is synthetic, use the `IRuntimeTypeSystem` to find the GCStressCodeCopy. | ||
2. If `codeVersionHandle` is explicit, read the `NativeCodeVersionNode` for the `GCCoverageInfo` pointer. This value is nullable as it only exists in some builds. If the value doesn't exist or is a nullptr, return `TargetPointer.Null`. Otherwise return the `SavedCode` pointer from the `GCCoverageInfo` struct. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2. If `codeVersionHandle` is explicit, read the `NativeCodeVersionNode` for the `GCCoverageInfo` pointer. This value is nullable as it only exists in some builds. If the value doesn't exist or is a nullptr, return `TargetPointer.Null`. Otherwise return the `SavedCode` pointer from the `GCCoverageInfo` struct. | |
2. If `codeVersionHandle` is explicit, read the `NativeCodeVersionNode` for the `GCCoverageInfo` pointer. This value only exists in some builds. If the value doesn't exist or is a nullptr, return `TargetPointer.Null`. Otherwise return the `SavedCode` pointer from the `GCCoverageInfo` struct. |
internal static Target CreateTarget( | ||
MockTarget.Architecture arch, | ||
MockCodeVersions builder, | ||
Mock<IRuntimeTypeSystem> mockRuntimeTypeSystem) | ||
{ | ||
TestPlaceholderTarget target = new TestPlaceholderTarget( | ||
arch, | ||
builder.Builder.GetReadContext().ReadFromTarget, | ||
builder.Types); | ||
|
||
IContractFactory<ICodeVersions> cvfactory = new CodeVersionsFactory(); | ||
ContractRegistry reg = Mock.Of<ContractRegistry>( | ||
c => c.CodeVersions == cvfactory.CreateContract(target, 1) | ||
&& c.RuntimeTypeSystem == mockRuntimeTypeSystem.Object); | ||
target.SetContracts(reg); | ||
return target; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for this change, but might be nice to switch the previous/existing tests to this as well.
@@ -40,6 +40,9 @@ public virtual bool CodeVersionManagerSupportsMethod(TargetPointer methodDesc); | |||
|
|||
// Return the instruction pointer corresponding to the start of the given native code version | |||
public virtual TargetCodePointer GetNativeCode(NativeCodeVersionHandle codeVersionHandle); | |||
|
|||
// Gets the GCStressCodeCopy pointer if available, otherwise returns TargetPointer.Null | |||
public virtual TargetPointer GetGCStressCodeCopy(NativeCodeVersionHandle codeVersionHandle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to refer to it as 'GCCoverage' or 'GCStress'? I kind of think of GC coverage as the more basic feature/info that GC stress uses. I don't feel too strongly either way.
Contributes to #109426
Changes
ICodeVersions
contractIRuntimeTypeSystem
contractWorklog
GCCoverageInfo
fields$env:DOTNET_GCStress=4
. This seems to make normal breakpoints not work, but throws an exception on every inserted GC breakpoint. I configured WinDBG to break on these exceptions (sxe c0000096
) and used!ip2md <ip>
to query the md which contains gccoverage info.