Skip to content

[Diagnostics] InProc CrashReporter Generics Support#128936

Draft
mdh1418 wants to merge 1 commit into
dotnet:mainfrom
mdh1418:inproc_crashreport_generics
Draft

[Diagnostics] InProc CrashReporter Generics Support#128936
mdh1418 wants to merge 1 commit into
dotnet:mainfrom
mdh1418:inproc_crashreport_generics

Conversation

@mdh1418
Copy link
Copy Markdown
Member

@mdh1418 mdh1418 commented Jun 3, 2026

Emit generic instantiation arguments in the in-proc crash report

A generic method's instantiation (the actual type arguments, e.g. List.Add) is a runtime construct — it is not encoded in the MethodDef token or recoverable from the PDB off-device. So even with a perfect offline symbolicator, a crash report that carries only the token can never reconstruct which instantiation was on the stack. Capturing the instantiation has to happen on-device, at crash time.

This change captures each generic frame's instantiation in the crash handler and emits it both on the managed frame line and as an additive generic_args JSON field, keeping the report self-sufficient.

  • Walker capture — a new signal-safe builder (BuildGenericArgs / AppendTypeHandleName / AppendUtf8) formats the instantiation as <classArgs;methodArgs> into the existing fixed scratch buffer. It uses only no-allocation, bounds-guarded metadata reads, a recursion depth cap (4), and a ? sentinel for malformed/too-deep shapes.
  • Fidelity of the captured args: - Value-type args resolve exactly (each value-type instantiation maps to distinct generated native code), e.g. .
  • Reference-type args collapse to System.__Canon under shared generics — this is inherent to the runtime's shared-code model, not a limitation of the capture.
  • Emission — genericArgs is threaded through the frame-callback typedef and the report sinks; the console appends <…> to the managed frame line and the JSON adds a generic_args key. Both emission points are gated on a non-empty string, so non-generic frames are unaffected.

Safety

  • The instantiation is read from already-loaded metadata on the faulting thread using NOTHROW / GC_NOTRIGGER / CANNOT_TAKE_LOCK-compatible APIs; on any unexpected shape the builder degrades to ? rather than risking a nested fault.

Validation

  • build.cmd clr.runtime -os android -arch x64 -c Release — 0 warnings / 0 errors.
  • Exercised on the Android x64 emulator with generic frames; value-type instantiations render exactly and reference-type args show as System.__Canon.

Capture each generic frame's instantiation on-device and emit it as a
<classArgs;methodArgs> suffix on the managed frame line (and an additive
generic_args field in the JSON). The instantiation is a runtime construct
not encoded in the token/PDB, so it is recoverable only on-device; emitting
it into the console report keeps the log self-sufficient. Value-type args
resolve exactly (they map to distinct generated native code); reference-type
args collapse to System.__Canon under shared generics.

The walker builds the string into the existing fixed scratch buffer via
BuildGenericArgs / AppendTypeHandleName / AppendUtf8 using only no-allocation,
signal-safe metadata APIs, with bounds-guarded writes, a recursion depth cap,
and a '?' sentinel for malformed shapes. A const char* genericArgs is threaded
through the frame-callback typedef and the report sinks.

This is the standalone variant of the generics change, applied directly on
the verbose reporter so it can ship independently of the compaction work.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service
Copy link
Copy Markdown
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
Copy Markdown
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

This PR extends the CoreCLR in-proc crash reporting pipeline to capture and emit a managed frame’s runtime generic instantiation arguments, threading a preformatted "<classArgs;methodArgs>" suffix from the VM stack walker through the existing frame callback and into both the console output and the JSON crash report (generic_args).

Changes:

  • Add generic instantiation string building in the VM-side crash report stack walker and pass it through InProcCrashReportFrameCallback.
  • Extend the crash reporter’s console and JSON sinks to include the per-frame generic instantiation payload.
  • Add a new scratch buffer slot (genericArgs) to avoid allocations and keep work bounded in the crash/signal context.

Reviewed changes

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

File Description
src/coreclr/vm/crashreportstackwalker.cpp Builds per-frame generic instantiation text in a fixed scratch buffer and passes it to the frame callback.
src/coreclr/debug/crashreport/inproccrashreporter.h Extends the frame callback signature with a const char* genericArgs parameter and documents its format/semantics.
src/coreclr/debug/crashreport/inproccrashreporter.cpp Plumbs genericArgs into JSON (generic_args) and appends it to the console-managed frame line.

Comment on lines +148 to +153
if (th.IsArray())
{
AppendTypeHandleName(buffer, bufferSize, index, th.GetArrayElementTypeHandle(), depth + 1);
AppendUtf8(buffer, bufferSize, index, "[]");
return;
}
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.

2 participants