Skip to content

Warn when Android full trimming strips the debug IDs needed for symbolication #5582

Description

@jamescrosswell

Problem

Android apps that trim their own assemblies (TrimMode=full, e.g. AndroidLinkMode=Full) get no symbolication for managed stack traces in Release builds, and nothing tells the user why.

In Release the Android SDK forces TrimmerRemoveSymbols=true in its _PrepareLinking target unless AndroidIncludeDebugSymbols=true (Microsoft.Android.Sdk.TypeMap.LlvmIr.targets; the same override has existed since .NET 6). With full trimming, ILLink rewrites the app's assemblies and drops their debug directory, so:

  • obj/.../linked/<App>.dll has an all-zero debug ID and no linked/*.pdb is produced
  • at runtime the SDK logs Skipping debug image for module '<App>.dll' because the Debug ID couldn't be determined
  • events have no debug_meta image for the app assembly, so frames can't be symbolicated even though the build uploaded PDBs

With the default TrimMode=partial, app assemblies are copied through untouched, keep their debug IDs, and symbolication works.

Found while verifying .NET 11 assembly store support end to end (#5577) with Sentry.Samples.Android, which sets AndroidLinkMode=full.

Workaround (verified)

Setting TrimmerRemoveSymbols=false as a normal csproj property (or -p:) does not work — _PrepareLinking overrides it. It has to be set after that target runs:

<Target Name="KeepTrimmerSymbols" AfterTargets="_PrepareLinking">
  <PropertyGroup>
    <TrimmerRemoveSymbols>false</TrimmerRemoveSymbols>
  </PropertyGroup>
</Target>

With that, and AndroidLinkMode=full unchanged, on net11.0-android37.0 / arm64: ILLink emits linked/*.pdb, the trimmed DLL and its PDB share a real debug ID, Sentry.targets already uploads linked/*.pdb, and the captured event carries the pe_dotnet debug image with a symbolicatable frame.

Caveats: _PrepareLinking is a private Android SDK target, so this could break in a future workload. AndroidIncludeDebugSymbols=true also keeps symbols but changes other Release behaviour (type map kind, CoreCLR native library exclusions, Mono debugger component), so it isn't a good general recommendation. The cost of keeping symbols in the APK is negligible — PDBs aren't packaged, only each assembly's debug directory is retained.

Proposal

We shouldn't flip the property for users (they may want symbols removed), but we should make the consequence visible:

  1. Build warning from Sentry.targets for Android apps when app assemblies are trimmed (TrimMode=full) and TrimmerRemoveSymbols is true at link time, explaining that managed stack traces won't symbolicate and pointing to the docs. It can't distinguish an intentional true from the Android SDK's forced value, so it should be informational and suppressible via NoWarn. Don't warn for TrimMode=partial.
  2. Troubleshooting docs: add an Android section to the .NET troubleshooting page (docs/platforms/dotnet/common/troubleshooting.mdx in sentry-docs), alongside the existing "Stack traces are not symbolicated on iOS, macOS and Mac Catalyst" section, covering the cause, the workaround above and its caveats. The "Missing or Unhelpful Stack Traces in AOT Compiled Apps" section is about the stack trace factory, which is a different cause.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions