WIP: Update SOS for unified ISOSDacInterface18 GCInfo API#5898
WIP: Update SOS for unified ISOSDacInterface18 GCInfo API#5898max-charlamb wants to merge 7 commits into
Conversation
Add gcinfoprovider.h/.cpp with GCInfoData struct that queries ISOSDacInterface18 for GC info header, interruptible ranges, slot lifetimes, and safe points. Both !GCInfo and !U -gcinfo try this path first, falling back to the legacy raw-blob + GcInfoDecoder/GcInfoDumper path for older runtimes. - Add ISOSDacInterface18 and supporting structs (SOSGCInfoHeader, SOSCodeRange, SOSGCSlotLifetime) to prebuilt sospriv headers - Add -legacy flag to !GCInfo for A/B comparison - DumpToOutput matches legacy format exactly: split display for interruptible (transitions) vs non-interruptible (safe points) - Sync gcinfodecoder.cpp, gcinfodumper.cpp, gcinfotypes.h from runtime to support .NET 11 GC info format Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| ISOSDacInterface18 * This, | ||
| CLRDATA_ADDRESS ip, | ||
| ULONG count, | ||
| unsigned int *offsets, |
There was a problem hiding this comment.
Should this be a long instead of unsigned int? Or raw addresses instead of offsets (ulong)? The offsets are from the start of the ip, but on some platforms functions have disconnected ranges, like funclets on arm64. I think currently (and probably for the forseeable future), these funclets always occur after the main function, and fairly close by (e.g. within 1 uint), but is this design future-proof?
While it may be overkill, I think if this were ulong *addresses instead of uint *offsets that would fully future-proof this no matter how to JIT is implemented in the future.
There was a problem hiding this comment.
The current GCInfo uses 32 bit offsets heavily, if this is an issue in the future, we can create a separate API.
leculver
left a comment
There was a problem hiding this comment.
This is a great start. I know it's a draft, but I had a few comments to help steer. Thanks!
74a13ca to
863d5c4
Compare
Add ISOSDacInterface18 consumption in !GCInfo command with fallback to the existing raw-bytes decoding path when the interface is not available (non-cDAC scenarios). The new path queries the cDAC for: - GC info header (code size, prolog, stack base, etc.) - Interruptible ranges - Safe points - Register lifetimes - Stack slot lifetimes Also adds a basic GCInfo verification to OtherCommands.script. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
863d5c4 to
491a060
Compare
…output - Replace SOSGCRegisterLifetime + SOSGCStackSlotLifetime with unified SOSGCSlotLifetime struct - Replace GetGCInfoRegisterLifetimes + GetGCInfoStackSlotLifetimes with single GetGCInfoSlotLifetimes - Remove ReturnKind from SOSGCInfoHeader (matches runtime change) - TryDumpGCInfoViaInterface18 now outputs legacy-compatible timeline format: header fields, untracked slots, then chronological interruptible/slot events - Update OtherCommands.script GCInfo verification to match timeline output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
491a060 to
26a0263
Compare
> [!NOTE] > This content was generated with AI assistance. ## ISOSDacInterface18 for GCInfo inspection APIs Add `ISOSDacInterface18` with 4 COM methods exposing GC info data through the cDAC for the SOS `!GCInfo` command: - `GetGCInfoHeader` -- header fields (version, code size, prolog, stack base register, GS cookie, PSP sym, generics context) - `GetGCInfoInterruptibleRanges` -- code regions where GC can interrupt execution - `GetGCInfoSafePoints` -- specific offsets with point-in-time GC slot liveness - `GetGCInfoSlotLifetimes` -- unified slot lifetime ranges (register + stack combined via `SOSGCSlotLifetime` with `IsRegister` discriminator) ### IGCInfo contract changes - Add `GetHeader`, `GetSafePoints`, `GetSlotLifetimes` to `IGCInfo`/`IGCInfoDecoder` - Consolidate `GetStackBaseRegister` and `GetSizeOfStackParameterArea` into `GCInfoHeader` (accessed via `GetHeader()`). These fields require the same decode depth (`DecodePoints.ReversePInvoke`) as the rest of the header, so there's no performance benefit to keeping them separate. - Keep `GetCodeLength` as a standalone method -- it only decodes to `DecodePoints.CodeLength`, which is significantly cheaper than the full header decode. Used on the hot path by `EEJitManager`/`InterpreterJitManager`/`ReadyToRunJitManager` for method size lookups. - Keep `GetCalleePoppedArgumentsSize` as a standalone method -- it returns 0 via a default interface method on non-x86 platforms without any decoding. Only x86 reads the `ArgCount` header field. - Eagerly decode safe points in `DecodeSafePoints`, stored denormalized - Single-pass chunk decoder for interruptible slot lifetimes (O(transitions), not O(codeLength)) - Safe-point-only methods emit `[safePointOffset, safePointOffset+1)` per live slot per safe point - Implement x86 GCInfo support (`GetHeader`/`GetSafePoints`/`GetSlotLifetimes`) - Add `GenericsContextKind.None` as default enum value - Fix `GSCookieValidRange` -- only set when GSCookie is present - Native DAC returns `E_NOINTERFACE` for `ISOSDacInterface18` (cDAC-only interface) ### Bug fix: ARM thumb bit in relative offset computation `EEJitManager.GetMethodInfo` and `InterpreterJitManager.GetMethodInfo` computed `relativeOffset` as `jittedCodeAddress.Value - codeStart.Value`. On ARM (Thumb-2), `TargetCodePointer.Value` includes the thumb bit (bit 0 = 1), but `codeStart` (a `TargetPointer` from the nibble map) does not. This produced a relative offset that was off by 1, causing `FindSafePoint` and `EnumerateLiveSlots` to look up the wrong offset. Fixed by stripping the thumb bit via `CodePointerUtils.AddressFromCodePointer` before computing the difference. `ReadyToRunJitManager` was already doing this correctly. ### Companion PR - dotnet/diagnostics#5898 -- SOS `!GCInfo` command updated to use `ISOSDacInterface18` with legacy-compatible timeline output format --------- Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3ebf2a2d-da27-41b5-9f45-4558240207ec
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3ebf2a2d-da27-41b5-9f45-4558240207ec
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3ebf2a2d-da27-41b5-9f45-4558240207ec
Note
This content was generated with AI assistance.
Update SOS !GCInfo command to use unified ISOSDacInterface18 API with timeline output format.
Depends on: dotnet/runtime#129761