diff --git a/CHANGELOG.md b/CHANGELOG.md index cc97e73d36..907034381b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixes +- Fixed symbolication for net9.0-android applications in Release config ([#4221](https://github.com/getsentry/sentry-dotnet/pull/4221)) - Support Linux arm64 on Native AOT ([#3700](https://github.com/getsentry/sentry-dotnet/pull/3700)) - Revert W3C traceparent support ([#4204](https://github.com/getsentry/sentry-dotnet/pull/4204)) diff --git a/Directory.Build.props b/Directory.Build.props index 3b46556d67..0a58397ec2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 5.8.1 + 5.8.2-beta.1 13 true true diff --git a/src/Sentry.Android.AssemblyReader/V2/AndroidAssemblyDirectoryReaderV2.cs b/src/Sentry.Android.AssemblyReader/V2/AndroidAssemblyDirectoryReaderV2.cs index d89f81da79..7c92c70a26 100644 --- a/src/Sentry.Android.AssemblyReader/V2/AndroidAssemblyDirectoryReaderV2.cs +++ b/src/Sentry.Android.AssemblyReader/V2/AndroidAssemblyDirectoryReaderV2.cs @@ -12,9 +12,10 @@ public AndroidAssemblyDirectoryReaderV2(string apkPath, IList supportedA Logger = logger; foreach (var abi in supportedAbis) { + logger?.Invoke("Adding {0} to supported architectures for Directory Reader", abi); SupportedArchitectures.Add(abi.AbiToDeviceArchitecture()); } - _archiveAssemblyHelper = new ArchiveAssemblyHelper(apkPath, logger); + _archiveAssemblyHelper = new ArchiveAssemblyHelper(apkPath, logger, supportedAbis); } public PEReader? TryReadAssembly(string name) @@ -25,11 +26,13 @@ public AndroidAssemblyDirectoryReaderV2(string apkPath, IList supportedA var stream = File.OpenRead(name); return new PEReader(stream); } + Logger?.Invoke("File {0} does not exist in the APK", name); foreach (var arch in SupportedArchitectures) { if (_archiveAssemblyHelper.ReadEntry($"assemblies/{name}", arch) is not { } memStream) { + Logger?.Invoke("Couldn't find entry {0} in the APK for the {1} architecture", name, arch); continue; } @@ -56,8 +59,9 @@ internal class ArchiveAssemblyHelper private readonly string _archivePath; private readonly DebugLogger? _logger; + private readonly IList _supportedAbis; - public ArchiveAssemblyHelper(string archivePath, DebugLogger? logger) + public ArchiveAssemblyHelper(string archivePath, DebugLogger? logger, IList supportedAbis) { if (string.IsNullOrEmpty(archivePath)) { @@ -66,6 +70,7 @@ public ArchiveAssemblyHelper(string archivePath, DebugLogger? logger) _archivePath = archivePath; _logger = logger; + _supportedAbis = supportedAbis; } public MemoryStream? ReadEntry(string path, AndroidTargetArch arch = AndroidTargetArch.None, bool uncompressIfNecessary = false) @@ -137,23 +142,52 @@ public ArchiveAssemblyHelper(string archivePath, DebugLogger? logger) var potentialEntries = TransformArchiveAssemblyPath(path, arch); if (potentialEntries == null || potentialEntries.Count == 0) { + _logger?.Invoke("No potential entries for path '{0}' with arch '{1}'", path, arch); return null; } - using var zip = ZipFile.OpenRead(_archivePath); - foreach (var assemblyPath in potentialEntries) + // First we check the base.apk + if (ReadEntryFromApk(_archivePath) is { } baseEntry) { - if (zip.GetEntry(assemblyPath) is not { } entry) + _logger?.Invoke("Found entry '{0}' in base archive '{1}'", path, _archivePath); + return baseEntry; + } + + // Otherwise check in the device specific APKs + foreach (var supportedAbi in _supportedAbis) + { + var splitFilePath = _archivePath.GetArchivePathForAbi(supportedAbi, _logger); + if (!File.Exists(splitFilePath)) { - continue; + _logger?.Invoke("No split config detected at: '{0}'", splitFilePath); + } + else if (ReadEntryFromApk(splitFilePath) is { } splitEntry) + { + return splitEntry; } - - var ret = entry.Extract(); - ret.Flush(); - return ret; } + // Finally admit defeat return null; + + MemoryStream? ReadEntryFromApk(string archivePath) + { + using var zip = ZipFile.OpenRead(archivePath); + foreach (var assemblyPath in potentialEntries) + { + if (zip.GetEntry(assemblyPath) is not { } entry) + { + _logger?.Invoke("No entry found for path '{0}' in archive '{1}'", assemblyPath, archivePath); + continue; + } + + var ret = entry.Extract(); + ret.Flush(); + return ret; + } + + return null; + } } /// diff --git a/src/Sentry.Android.AssemblyReader/V2/AndroidAssemblyStoreReaderV2.cs b/src/Sentry.Android.AssemblyReader/V2/AndroidAssemblyStoreReaderV2.cs index 73b170a0c5..f88e0ca237 100644 --- a/src/Sentry.Android.AssemblyReader/V2/AndroidAssemblyStoreReaderV2.cs +++ b/src/Sentry.Android.AssemblyReader/V2/AndroidAssemblyStoreReaderV2.cs @@ -13,16 +13,35 @@ private AndroidAssemblyStoreReaderV2(IList explorers, Deb public static bool TryReadStore(string inputFile, IList supportedAbis, DebugLogger? logger, [NotNullWhen(true)] out AndroidAssemblyStoreReaderV2? reader) { + List supportedExplorers = []; + + // First we check the base.apk for an assembly store var (explorers, errorMessage) = AssemblyStoreExplorer.Open(inputFile, logger); - if (errorMessage != null) + if (explorers is null) { - logger?.Invoke(errorMessage); - reader = null; - return false; - } + logger?.Invoke("Unable to read store information for {0}: {1}", inputFile, errorMessage); - List supportedExplorers = []; - if (explorers is not null) + // Check for assembly stores in any device specific APKs + foreach (var supportedAbi in supportedAbis) + { + var splitFilePath = inputFile.GetArchivePathForAbi(supportedAbi, logger); + if (!File.Exists(splitFilePath)) + { + logger?.Invoke("No split config detected at: '{0}'", splitFilePath); + continue; + } + (explorers, errorMessage) = AssemblyStoreExplorer.Open(splitFilePath, logger); + if (explorers is not null) + { + supportedExplorers.AddRange(explorers); // If the error is null then this is not null + } + else + { + logger?.Invoke("Unable to read store information for {0}: {1}", splitFilePath, errorMessage); + } + } + } + else { foreach (var explorer in explorers) { diff --git a/src/Sentry.Android.AssemblyReader/V2/MonoAndroidHelper.Basic.cs b/src/Sentry.Android.AssemblyReader/V2/MonoAndroidHelper.Basic.cs index fda2ff8ad1..7836c6819f 100644 --- a/src/Sentry.Android.AssemblyReader/V2/MonoAndroidHelper.Basic.cs +++ b/src/Sentry.Android.AssemblyReader/V2/MonoAndroidHelper.Basic.cs @@ -89,4 +89,17 @@ public static string MakeZipArchivePath(string part1, ICollection? pathP public const string MANGLED_ASSEMBLY_REGULAR_ASSEMBLY_MARKER = "lib_"; public const string MANGLED_ASSEMBLY_SATELLITE_ASSEMBLY_MARKER = "lib-"; public const string SATELLITE_CULTURE_END_MARKER_CHAR = "_"; + + /// + /// When an AAB file is deployed, the APK is split into multiple APKs so our modules can end up in a companion + /// architecture specific APK like split_config.arm64_v8a.apk. This method returns the path to that split_config APK + /// if it exists... otherwise we just return the original archive path. + /// + internal static string GetArchivePathForAbi(this string archivePath, string abi, DebugLogger? logger) + { + var basePath = Path.GetDirectoryName(archivePath) ?? string.Empty; + var abiPart = abi.Replace("-", "_"); + var splitFilePath = Path.Combine(basePath, $"split_config.{abiPart}.apk"); + return splitFilePath; + } } diff --git a/src/Sentry/Internal/DebugStackTrace.cs b/src/Sentry/Internal/DebugStackTrace.cs index 81d1afea90..853d925699 100644 --- a/src/Sentry/Internal/DebugStackTrace.cs +++ b/src/Sentry/Internal/DebugStackTrace.cs @@ -249,6 +249,7 @@ private IEnumerable CreateFrames(StackTrace stackTrace, bool i return null; } + _options.LogDebug("Attempting to get debug image for native AOT Frame"); var imageAddress = stackFrame.GetNativeImageBase(); var frame = ParseNativeAOTToString(stackFrame.ToString()); frame.ImageAddress = imageAddress;