Repository navigation
Conversation
Mirror native CrawlFrame::GetExactGenericArgsToken for capital-F transition frames. Use the receiver's MethodTable for a this-derived context (except on x64, where native does not recover it). For an instantiation argument, read the MethodParam/TypeParam slot from the ExternalMethodFrame, PrestubMethodFrame or CallCountingHelperFrame GCRefMap before falling back to the signature-based layout, so a ReadyToRun target with unloaded signature types still yields the token. StubDispatchFrame keeps using the signature, as native does. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Azure Pipelines: Successfully started running 5 pipeline(s). 11 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Hmm. If there are no consequences of a bug does it need squishing? @max-charlamb @rcj1 |
|
I'm still digging a bit |
…stub dispatch Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Dug in: there are no consequences today. Native DacDbi never fills This PR only brings the cDAC Note This comment was drafted with GitHub Copilot. |
Follow-up to #136667, as requested in #136667 (comment): the cDAC should keep working when ReadyToRun call targets have not loaded their signature types.
Background
#135805 lets a ReadyToRun call target that has an import or exact-entry GCRefMap skip loading its signature value types. #136667 changed native
TransitionFrame::GetParamTypeArgto find the generic-context argument through the frame's GCRefMap. TheArgIteratorpath needs the return type, which may not be loaded.The cDAC's
IStackWalk.GetExactGenericArgsTokenreturnedTargetPointer.Nullfor every non-frameless frame. NativeCrawlFrame::GetExactGenericArgsTokenreturns a token for transition frames.Change
For a capital-F transition frame (
Frame/SkippedFramestate),GetExactGenericArgsTokennow follows nativeCrawlFrame::GetExactGenericArgsToken:ThisPtrcontext: reads the receiver from the transition block's first argument slot and returns itsMethodTable. It returnsNullon x64, where nativeCrawlFrame::GetThisPointerdoes not recover a transition frame's receiver.InstArgMethodDesc/InstArgMethodTablecontext: reads theMethodParam/TypeParamslot from the frame's GCRefMap without inspecting the signature:ExternalMethodFrameusesFindGCRefMapon itsIndirection.PrestubMethodFrameandCallCountingHelperFrameuse the same method-entry map resolution as GC scanning.CallingConvention.TryComputeArgGCRefMapBlob. It returnsNullinstead of throwing when the target lacks the signature layout.StubDispatchFrame: uses only the signature path, as native does, because dispatch maps omit the instantiation argument.The logic lives in
FrameHelpers, alongside the other per-frame helpers. GcScanner's transition-block slot-address helpers moved there too, so both callers share them.docs/design/datacontracts/StackWalk.mdreplaces the note that explicitFramedMethodFramerecovery was out of scope with a description of the algorithm.GC scanning already had parity:
GcScanneruses the frame's GCRefMap before the signature for these frame types. It is unchanged apart from the helper move.Current reach: no DAC-shaped API exposes this, natively or in the cDAC. Native
CrawlFrame::GetExactGenericArgsTokenhandles transition frames, but its DAC callers don't pass them a transition frame:kManagedStackFrame. It reports transition frames askExplicitFrame/cStubFrameinternal frames, which carry no token. The cDACDacDbiImplmatches this.IXCLRDataFrame2::GetExactGenericArgsToken, which dump enumeration uses, reads theTYPECTXT_ILNUMvariable from JIT debug info rather than callingCrawlFrame. The cDACClrDataFramestill returnsE_NOTIMPL.The in-process debugger (
debug/ee/frameinfo.cpp) does callCrawlFrame::GetExactGenericArgsTokenon transition frames, and #136667 already covers it. This change makes the cDACIStackWalkcontract matchCrawlFrame. That keeps the contract correct in this restricted ReadyToRun scenario for any cDAC consumer that later surfaces transition frames, but it does not change current DAC-visible behavior.Validation
./dotnet.sh build /t:Build;Test src/native/managed/cdac/tests/UnitTests/Microsoft.Diagnostics.DataContractReader.Tests.csproj -c Release -p:RuntimeConfiguration=Checked -p:LibrariesConfiguration=Release: passed, 3938 total, 0 failed (osx-arm64). The run includes 33 newStackWalkTestscases:StubDispatchFrameignoring its map and resolving itsMethodDescfrom the representative MethodTable;Nullwhen neither source has the token, the method isn't shared, or the frame has noMethodDesc;this-derived context on x86 versus x64;FirstGCRefMapSlot(X8) differs from the argument registers;CreateStackWalkreachingIStackWalk.GetExactGenericArgsTokenthrough a Frame-state handle: a transition frame returns its token, anInlinedCallFramereturnsNull.StackWalk_1's Frame routing removed, only the stack-walk transition-frame case fails.Note
This PR description and the code changes were generated with GitHub Copilot.