Skip to content

Add TraverseEHInfo cDAC API#125198

Open
rcj1 wants to merge 10 commits intodotnet:mainfrom
rcj1:TraverseEhInfo
Open

Add TraverseEHInfo cDAC API#125198
rcj1 wants to merge 10 commits intodotnet:mainfrom
rcj1:TraverseEhInfo

Conversation

@rcj1
Copy link
Contributor

@rcj1 rcj1 commented Mar 5, 2026

No description provided.

Copilot AI review requested due to automatic review settings March 5, 2026 00:42
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.

Copilot AI review requested due to automatic review settings March 5, 2026 17:44
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 5 comments.

Copilot AI review requested due to automatic review settings March 6, 2026 18:28
@rcj1 rcj1 removed the request for review from janvorli March 6, 2026 18:33
@rcj1 rcj1 marked this pull request as ready for review March 6, 2026 18:33
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.

DACEHInfo expectedEhClause = expected.Elements[(int)clauseIndex];
Debug.Assert(pEHInfo->clauseType == expectedEhClause.clauseType, $"cDAC: {expectedEhClause.clauseType}, DAC: {pEHInfo->clauseType}");
Debug.Assert(pEHInfo->filterOffset == expectedEhClause.filterOffset, $"cDAC: {expectedEhClause.filterOffset:x}, DAC: {pEHInfo->filterOffset:x}");
Debug.Assert(pEHInfo->isCatchAllHandler == expectedEhClause.isCatchAllHandler, $"cDAC: {expectedEhClause.isCatchAllHandler}, DAC: {pEHInfo->isCatchAllHandler}");
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DEBUG cross-validation callback asserts isCatchAllHandler matches the legacy DAC output, but the legacy implementation sets this field using (&EHClause.TypeHandle == mdTypeRefNil) (see coreclr/debug/daccess/request.cpp), which will never be true in practice. As written, this can trigger Debug.Assert failures when enumerating a catch-all typed handler. Consider relaxing/removing this specific assertion (or otherwise matching legacy behavior) so DEBUG builds don't fail on valid inputs.

Suggested change
Debug.Assert(pEHInfo->isCatchAllHandler == expectedEhClause.isCatchAllHandler, $"cDAC: {expectedEhClause.isCatchAllHandler}, DAC: {pEHInfo->isCatchAllHandler}");
// The legacy DAC computes isCatchAllHandler using (&EHClause.TypeHandle == mdTypeRefNil),
// which will not be true for real catch-all typed handlers. Do not assert equality here to
// avoid spurious Debug.Assert failures when cross-validating against the legacy implementation.

Copilot uses AI. Check for mistakes.
@rcj1 rcj1 marked this pull request as draft March 9, 2026 03:31
Copilot AI review requested due to automatic review settings March 9, 2026 23:41
@rcj1 rcj1 marked this pull request as ready for review March 9, 2026 23:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 8 comments.

Comment on lines 4 to +6
using System;
using System.Collections;
using System.Collections.Generic;
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using System.Collections; appears unused in this file; removing it avoids unnecessary-usings style warnings (IDE0005) in the repo build.

Copilot uses AI. Check for mistakes.
Comment on lines +137 to +139
ExceptionClauseInfo filterClause = clauses.First(c => c.ClauseType == ExceptionClauseInfo.ExceptionClauseFlags.Filter);
Assert.NotNull(filterClause.FilterOffset);
}
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test only asserts that the filter clause has a non-null FilterOffset. Consider also asserting that filter clauses do not report ClassToken/ModuleAddr (since the union field is a filter offset, not a token) so the test would catch regressions in clause classification/mapping.

Copilot uses AI. Check for mistakes.
Comment on lines +424 to +426
else if (!IsFaultOrFinally(flags))
{
if (IsTypedHandler(flags))
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The !IsFaultOrFinally(flags) branch also runs for Filter clauses, which means filter clauses will incorrectly get ModuleAddr/ClassToken populated even though the union field is a filter offset. This later causes TraverseEHInfo to report a non-zero tokCatch for filter clauses and can mismatch legacy DAC behavior. Restrict this block to typed clauses only (and leave ClassToken/ModuleAddr null for filter clauses).

Copilot uses AI. Check for mistakes.
TargetPointer mtPtr = rts.GetMethodTable(mdHandle);
TypeHandle th = rts.GetTypeHandle(mtPtr);
moduleAddr = rts.GetModule(th);
classToken = entry.ClassToken;
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

classToken = entry.ClassToken; uses the union field for all non-fault/finally clauses, but for Filter clauses this value is a filter offset rather than a metadata token. Ensure ClassToken is only set for typed clauses (and preferably only when HasCachedTypeHandle is false).

Copilot uses AI. Check for mistakes.
Comment on lines +420 to +423
if (HasCachedTypeHandle(entry))
{
typeHandle = ((EEExceptionClause)entry).TypeHandle;
}
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HasCachedTypeHandle(entry) can be true for any IExceptionClauseData; if this ever occurs for an R2R clause, the cast to EEExceptionClause will throw. Consider guarding this with !isR2R (or otherwise ensuring the flag cannot be set for R2R clauses) before casting.

Copilot uses AI. Check for mistakes.
Comment on lines +430 to +434
TargetPointer methodDescPtr = ((IExecutionManager)this).GetMethodDesc(codeInfoHandle);
IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem;
MethodDescHandle mdHandle = rts.GetMethodDescHandle(methodDescPtr);
TargetPointer mtPtr = rts.GetMethodTable(mdHandle);
TypeHandle th = rts.GetTypeHandle(mtPtr);
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RuntimeTypeSystem lookups for MethodDesc -> Module are repeated for every clause in the loop. Since the module is per-method (not per-clause), consider hoisting the method/module resolution outside the clause iteration (or caching it the first time it is needed) to avoid unnecessary contract calls and target reads.

Copilot uses AI. Check for mistakes.
@rcj1
Copy link
Contributor Author

rcj1 commented Mar 9, 2026

@janvorli

// The last entry in the lookup table (end-1) points to a sentinel entry.

@janvorli
Copy link
Member

janvorli commented Mar 9, 2026

@rcj1 ah, sorry, I have not realized that's the R2R case.

Copy link
Member

@noahfalk noahfalk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. It would probably be good for someone maintaining the EH typesystem/R2R code (@janvorli or @davidwrighton maybe?) to confirm the contract surface area we are binding to looks good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants