From ef1a7107a20f2769fdf9af2763850ad3bd0267d4 Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Tue, 21 Jan 2025 17:47:04 +0100 Subject: [PATCH 01/18] Add fetching debug images by addresses --- .../android/core/IDebugImagesLoader.java | 5 ++ .../android/core/NoOpDebugImagesLoader.java | 9 +++ .../android/core/SentryAndroidOptionsTest.kt | 2 + .../sentry/android/ndk/DebugImagesLoader.java | 74 ++++++++++++++++++- .../android/ndk/DebugImagesLoaderTest.java | 1 + .../android/ndk/DebugImagesLoaderTest.kt | 31 ++++++++ 6 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.java diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java b/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java index 902f7efc2b5..e2ea1300a4d 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java @@ -2,6 +2,8 @@ import io.sentry.protocol.DebugImage; import java.util.List; +import java.util.Set; + import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -11,5 +13,8 @@ public interface IDebugImagesLoader { @Nullable List loadDebugImages(); + @Nullable + Set loadDebugImagesForAddresses(Set addresses); + void clearDebugImages(); } diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java b/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java index 70451972a76..932c0721838 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java @@ -1,7 +1,11 @@ package io.sentry.android.core; import io.sentry.protocol.DebugImage; + +import java.util.Collections; import java.util.List; +import java.util.Set; + import org.jetbrains.annotations.Nullable; final class NoOpDebugImagesLoader implements IDebugImagesLoader { @@ -19,6 +23,11 @@ public static NoOpDebugImagesLoader getInstance() { return null; } + @Override + public @Nullable Set loadDebugImagesForAddresses(Set addresses) { + return null; + } + @Override public void clearDebugImages() {} } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt index efef393dc78..cda71fe5644 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt @@ -182,6 +182,8 @@ class SentryAndroidOptionsTest { private class CustomDebugImagesLoader : IDebugImagesLoader { override fun loadDebugImages(): List? = null + override fun loadDebugImagesForAddresses(addresses: Set?): Set? = null; + override fun clearDebugImages() {} } } diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index 1257325091a..5d73ac76db8 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -9,8 +9,12 @@ import io.sentry.protocol.DebugImage; import io.sentry.util.AutoClosableReentrantLock; import io.sentry.util.Objects; + import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.VisibleForTesting; @@ -27,7 +31,9 @@ public final class DebugImagesLoader implements IDebugImagesLoader { private static @Nullable List debugImages; - /** we need to lock it because it could be called from different threads */ + /** + * we need to lock it because it could be called from different threads + */ protected static final @NotNull AutoClosableReentrantLock debugImagesLock = new AutoClosableReentrantLock(); @@ -75,7 +81,71 @@ public DebugImagesLoader( return debugImages; } - /** Clears the caching of debug images on sentry-native and here. */ + /** + * Finds a debug image containing the given address using binary search. + * Requires the images to be sorted. + * + * @return The matching debug image or null if not found + */ + private @Nullable DebugImage findImageByAddress(long address, List images) { + int left = 0; + int right = images.size() - 1; + + while (left <= right) { + int mid = left + (right - left) / 2; + DebugImage image = images.get(mid); + + if (image.getImageAddr() == null || image.getImageSize() == null) { + return null; + } + + long imageStart = Long.parseLong(image.getImageAddr().replace("0x", ""), 16); + long imageEnd = imageStart + image.getImageSize(); + + if (address >= imageStart && address < imageEnd) { + return image; + } else if (address < imageStart) { + right = mid - 1; + } else { + left = mid + 1; + } + } + + return null; + } + + /** + * Loads debug images for the given set of addresses. + * @param addresses Set of memory addresses to find debug images for + * @return Set of debug images, or null if debug images couldn't be loaded + */ + public @Nullable Set loadDebugImagesForAddresses(@NotNull Set addresses) { + List allDebugImages = loadDebugImages(); + if (allDebugImages == null) { + return null; + } + + Set relevantImages = new LinkedHashSet<>(); + for (Long addr : addresses) { + relevantImages.add(findImageByAddress(addr, allDebugImages)); + } + + // Return null if no images were found + if (relevantImages.isEmpty()) { + options.getLogger().log( + SentryLevel.WARNING, + "No debug images found for any of the %d addresses.", + addresses.size() + ); + return null; + } + + return relevantImages; + } + + /** + * Clears the caching of debug images on sentry-native and here. + */ @Override public void clearDebugImages() { try (final @NotNull ISentryLifecycleToken ignored = debugImagesLock.acquire()) { diff --git a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.java b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.java new file mode 100644 index 00000000000..0519ecba6ea --- /dev/null +++ b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.java @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt index 927ce98c3bd..5804cd3a316 100644 --- a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt +++ b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt @@ -1,15 +1,19 @@ package io.sentry.android.ndk import io.sentry.android.core.SentryAndroidOptions +import io.sentry.ndk.DebugImage import io.sentry.ndk.NativeModuleListLoader +import org.junit.Assert.assertEquals import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import kotlin.test.Test +import kotlin.test.assertContains import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue + class DebugImagesLoaderTest { private class Fixture { val nativeLoader = mock() @@ -77,4 +81,31 @@ class DebugImagesLoaderTest { assertNull(sut.cachedDebugImages) } + + @Test + fun testFindImageByAddress() { + val sut = fixture.getSut() + + val image1 = DebugImage() + image1.imageAddr = "0x1000" + image1.imageSize = 0x1000L + + val image2 = DebugImage() + image2.imageAddr = "0x2000" + image2.imageSize = 0x1000L + + val image3 = DebugImage() + image3.imageAddr = "0x3000" + image3.imageSize = 0x1000L + + whenever(fixture.nativeLoader.loadModuleList()).thenReturn(arrayOf(image1, image2)) + + val result = sut.loadDebugImagesForAddresses( + setOf(0x1500L, 0x2500L) + )!!.toList() + + assertEquals(2, result.size) + assertEquals(image1.imageAddr, result[0].imageAddr) + assertEquals(image2.imageAddr, result[1].imageAddr) + } } From ce9ec53e475136e96398bb38b8b24ed62ad4e830 Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Tue, 21 Jan 2025 23:16:09 +0100 Subject: [PATCH 02/18] update test --- .../sentry/android/ndk/DebugImagesLoader.java | 5 +- .../android/ndk/DebugImagesLoaderTest.kt | 46 ++++++++++++++----- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index 5d73ac76db8..87b0547c947 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -127,7 +127,10 @@ public DebugImagesLoader( Set relevantImages = new LinkedHashSet<>(); for (Long addr : addresses) { - relevantImages.add(findImageByAddress(addr, allDebugImages)); + DebugImage image = findImageByAddress(addr, allDebugImages); + if (image != null) { + relevantImages.add(image); + } } // Return null if no images were found diff --git a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt index 5804cd3a316..5c73210d5cc 100644 --- a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt +++ b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt @@ -1,14 +1,12 @@ package io.sentry.android.ndk import io.sentry.android.core.SentryAndroidOptions -import io.sentry.ndk.DebugImage import io.sentry.ndk.NativeModuleListLoader import org.junit.Assert.assertEquals import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import kotlin.test.Test -import kotlin.test.assertContains import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue @@ -86,19 +84,22 @@ class DebugImagesLoaderTest { fun testFindImageByAddress() { val sut = fixture.getSut() - val image1 = DebugImage() - image1.imageAddr = "0x1000" - image1.imageSize = 0x1000L + val image1 = io.sentry.ndk.DebugImage().apply { + imageAddr = "0x1000" + imageSize = 0x1000L + } - val image2 = DebugImage() - image2.imageAddr = "0x2000" - image2.imageSize = 0x1000L + val image2 = io.sentry.ndk.DebugImage().apply { + imageAddr = "0x2000" + imageSize = 0x1000L + } - val image3 = DebugImage() - image3.imageAddr = "0x3000" - image3.imageSize = 0x1000L + val image3 = io.sentry.ndk.DebugImage().apply { + imageAddr = "0x3000" + imageSize = 0x1000L + } - whenever(fixture.nativeLoader.loadModuleList()).thenReturn(arrayOf(image1, image2)) + whenever(fixture.nativeLoader.loadModuleList()).thenReturn(arrayOf(image1, image2, image3)) val result = sut.loadDebugImagesForAddresses( setOf(0x1500L, 0x2500L) @@ -108,4 +109,25 @@ class DebugImagesLoaderTest { assertEquals(image1.imageAddr, result[0].imageAddr) assertEquals(image2.imageAddr, result[1].imageAddr) } + + @Test + fun testInvalidHexAddress() { + val sut = fixture.getSut() + val image1 = io.sentry.ndk.DebugImage().apply { + imageAddr = "0x1000" + imageSize = 0x1000L + } + + val image2 = io.sentry.ndk.DebugImage().apply { + imageAddr = "0x2000" + imageSize = 0x1000L + } + + whenever(fixture.nativeLoader.loadModuleList()).thenReturn(arrayOf(image1, image2)) + + val hexAddresses = setOf(-100, 0x1500L) + val result = sut.loadDebugImagesForAddresses(hexAddresses) + + assertEquals(1, result!!.size) + } } From 149d2e1f89911fec032adeb5dc0eac6ca1d8024a Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Tue, 21 Jan 2025 23:17:37 +0100 Subject: [PATCH 03/18] clean up --- .../sentry/android/ndk/DebugImagesLoader.java | 63 +++++++++---------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index 87b0547c947..8f8d0d2fedd 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -81,6 +81,37 @@ public DebugImagesLoader( return debugImages; } + /** + * Loads debug images for the given set of addresses. + * @param addresses Set of memory addresses to find debug images for + * @return Set of debug images, or null if debug images couldn't be loaded + */ + public @Nullable Set loadDebugImagesForAddresses(@NotNull Set addresses) { + List allDebugImages = loadDebugImages(); + if (allDebugImages == null) { + return null; + } + + Set relevantImages = new LinkedHashSet<>(); + for (Long address : addresses) { + DebugImage image = findImageByAddress(address, allDebugImages); + if (image != null) { + relevantImages.add(image); + } + } + + if (relevantImages.isEmpty()) { + options.getLogger().log( + SentryLevel.WARNING, + "No debug images found for any of the %d addresses.", + addresses.size() + ); + return null; + } + + return relevantImages; + } + /** * Finds a debug image containing the given address using binary search. * Requires the images to be sorted. @@ -114,38 +145,6 @@ public DebugImagesLoader( return null; } - /** - * Loads debug images for the given set of addresses. - * @param addresses Set of memory addresses to find debug images for - * @return Set of debug images, or null if debug images couldn't be loaded - */ - public @Nullable Set loadDebugImagesForAddresses(@NotNull Set addresses) { - List allDebugImages = loadDebugImages(); - if (allDebugImages == null) { - return null; - } - - Set relevantImages = new LinkedHashSet<>(); - for (Long addr : addresses) { - DebugImage image = findImageByAddress(addr, allDebugImages); - if (image != null) { - relevantImages.add(image); - } - } - - // Return null if no images were found - if (relevantImages.isEmpty()) { - options.getLogger().log( - SentryLevel.WARNING, - "No debug images found for any of the %d addresses.", - addresses.size() - ); - return null; - } - - return relevantImages; - } - /** * Clears the caching of debug images on sentry-native and here. */ From 31c8b800c1e0a6754018aa4b344cf501b1c4fc33 Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Tue, 21 Jan 2025 23:22:48 +0100 Subject: [PATCH 04/18] update test --- .../sentry/android/ndk/DebugImagesLoader.java | 4 +-- .../android/ndk/DebugImagesLoaderTest.kt | 28 +++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index 8f8d0d2fedd..bc2ce56f46a 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -93,8 +93,8 @@ public DebugImagesLoader( } Set relevantImages = new LinkedHashSet<>(); - for (Long address : addresses) { - DebugImage image = findImageByAddress(address, allDebugImages); + for (Long addr : addresses) { + DebugImage image = findImageByAddress(addr, allDebugImages); if (image != null) { relevantImages.add(image); } diff --git a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt index 5c73210d5cc..c9a9744a595 100644 --- a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt +++ b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt @@ -3,6 +3,7 @@ package io.sentry.android.ndk import io.sentry.android.core.SentryAndroidOptions import io.sentry.ndk.NativeModuleListLoader import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever @@ -81,7 +82,7 @@ class DebugImagesLoaderTest { } @Test - fun testFindImageByAddress() { + fun `find images by address`() { val sut = fixture.getSut() val image1 = io.sentry.ndk.DebugImage().apply { @@ -111,8 +112,9 @@ class DebugImagesLoaderTest { } @Test - fun testInvalidHexAddress() { + fun `find images with invalid addresses are not added to the result`() { val sut = fixture.getSut() + val image1 = io.sentry.ndk.DebugImage().apply { imageAddr = "0x1000" imageSize = 0x1000L @@ -130,4 +132,26 @@ class DebugImagesLoaderTest { assertEquals(1, result!!.size) } + + @Test + fun `find images by address returns null if result is empty`() { + val sut = fixture.getSut() + + val image1 = io.sentry.ndk.DebugImage().apply { + imageAddr = "0x1000" + imageSize = 0x1000L + } + + val image2 = io.sentry.ndk.DebugImage().apply { + imageAddr = "0x2000" + imageSize = 0x1000L + } + + whenever(fixture.nativeLoader.loadModuleList()).thenReturn(arrayOf(image1, image2)) + + val hexAddresses = setOf(-100, 0x10500L) + val result = sut.loadDebugImagesForAddresses(hexAddresses) + + assertNull(result) + } } From 4217ab55cfa5d8cb390dc8b5496ddd2b528feb52 Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Tue, 21 Jan 2025 23:41:27 +0100 Subject: [PATCH 05/18] update comments --- .../src/main/java/io/sentry/android/ndk/DebugImagesLoader.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index bc2ce56f46a..20ae51ac40a 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -145,9 +145,6 @@ public DebugImagesLoader( return null; } - /** - * Clears the caching of debug images on sentry-native and here. - */ @Override public void clearDebugImages() { try (final @NotNull ISentryLifecycleToken ignored = debugImagesLock.acquire()) { From a6ced7a7195129bf9cbca12b7eda99d0d8c21e4c Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Tue, 21 Jan 2025 23:42:09 +0100 Subject: [PATCH 06/18] remove file --- .../test/java/io/sentry/android/ndk/DebugImagesLoaderTest.java | 1 - 1 file changed, 1 deletion(-) delete mode 100644 sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.java diff --git a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.java b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.java deleted file mode 100644 index 0519ecba6ea..00000000000 --- a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.java +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 41f113e934b4c2c7439c39c25af5634cf42e358f Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Tue, 21 Jan 2025 23:43:04 +0100 Subject: [PATCH 07/18] fix imports --- .../test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt index c9a9744a595..45aa37c7a48 100644 --- a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt +++ b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt @@ -2,17 +2,15 @@ package io.sentry.android.ndk import io.sentry.android.core.SentryAndroidOptions import io.sentry.ndk.NativeModuleListLoader -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNull import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import kotlin.test.Test +import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue - class DebugImagesLoaderTest { private class Fixture { val nativeLoader = mock() From f4c12a44457cd180663ff04689fd7bf0df231e56 Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Tue, 21 Jan 2025 23:43:45 +0100 Subject: [PATCH 08/18] update docs --- .../src/main/java/io/sentry/android/ndk/DebugImagesLoader.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index 20ae51ac40a..8eccfabcd04 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -83,6 +83,7 @@ public DebugImagesLoader( /** * Loads debug images for the given set of addresses. + * * @param addresses Set of memory addresses to find debug images for * @return Set of debug images, or null if debug images couldn't be loaded */ From f7c5c2c3a76a8e32c89f5729d10b0e7b5648fb7d Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Tue, 21 Jan 2025 23:55:18 +0100 Subject: [PATCH 09/18] revert doc --- .../sentry/android/ndk/DebugImagesLoader.java | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index 8eccfabcd04..c6eac2fe626 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -31,9 +31,7 @@ public final class DebugImagesLoader implements IDebugImagesLoader { private static @Nullable List debugImages; - /** - * we need to lock it because it could be called from different threads - */ + /** we need to lock it because it could be called from different threads */ protected static final @NotNull AutoClosableReentrantLock debugImagesLock = new AutoClosableReentrantLock(); @@ -88,29 +86,31 @@ public DebugImagesLoader( * @return Set of debug images, or null if debug images couldn't be loaded */ public @Nullable Set loadDebugImagesForAddresses(@NotNull Set addresses) { - List allDebugImages = loadDebugImages(); - if (allDebugImages == null) { - return null; - } + try (final @NotNull ISentryLifecycleToken ignored = debugImagesLock.acquire()) { + List allDebugImages = loadDebugImages(); + if (allDebugImages == null) { + return null; + } - Set relevantImages = new LinkedHashSet<>(); - for (Long addr : addresses) { - DebugImage image = findImageByAddress(addr, allDebugImages); - if (image != null) { - relevantImages.add(image); + Set relevantImages = new LinkedHashSet<>(); + for (Long addr : addresses) { + DebugImage image = findImageByAddress(addr, allDebugImages); + if (image != null) { + relevantImages.add(image); + } } - } - if (relevantImages.isEmpty()) { - options.getLogger().log( - SentryLevel.WARNING, - "No debug images found for any of the %d addresses.", - addresses.size() - ); - return null; - } + if (relevantImages.isEmpty()) { + options.getLogger().log( + SentryLevel.WARNING, + "No debug images found for any of the %d addresses.", + addresses.size() + ); + return null; + } - return relevantImages; + return relevantImages; + } } /** From f5bd3685f338dd6015b4447b41f3aa0cc4bfe97f Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Tue, 21 Jan 2025 23:56:35 +0100 Subject: [PATCH 10/18] use hashset --- .../main/java/io/sentry/android/ndk/DebugImagesLoader.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index c6eac2fe626..180ff64a624 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -11,7 +11,7 @@ import io.sentry.util.Objects; import java.util.ArrayList; -import java.util.LinkedHashSet; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -92,7 +92,7 @@ public DebugImagesLoader( return null; } - Set relevantImages = new LinkedHashSet<>(); + Set relevantImages = new HashSet<>(); for (Long addr : addresses) { DebugImage image = findImageByAddress(addr, allDebugImages); if (image != null) { From 89b76c78f3df7caaec2a2e2cc0d3438856c667ef Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Tue, 21 Jan 2025 23:00:08 +0000 Subject: [PATCH 11/18] Format code --- .../sentry/android/core/IDebugImagesLoader.java | 1 - .../android/core/NoOpDebugImagesLoader.java | 3 --- .../android/core/SentryAndroidOptionsTest.kt | 2 +- .../sentry/android/ndk/DebugImagesLoader.java | 17 ++++++++--------- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java b/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java index e2ea1300a4d..541ed0f157f 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java @@ -3,7 +3,6 @@ import io.sentry.protocol.DebugImage; import java.util.List; import java.util.Set; - import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java b/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java index 932c0721838..660e2425956 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java @@ -1,11 +1,8 @@ package io.sentry.android.core; import io.sentry.protocol.DebugImage; - -import java.util.Collections; import java.util.List; import java.util.Set; - import org.jetbrains.annotations.Nullable; final class NoOpDebugImagesLoader implements IDebugImagesLoader { diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt index cda71fe5644..4f4a12924fc 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt @@ -182,7 +182,7 @@ class SentryAndroidOptionsTest { private class CustomDebugImagesLoader : IDebugImagesLoader { override fun loadDebugImages(): List? = null - override fun loadDebugImagesForAddresses(addresses: Set?): Set? = null; + override fun loadDebugImagesForAddresses(addresses: Set?): Set? = null override fun clearDebugImages() {} } diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index 180ff64a624..c241a008e85 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -9,12 +9,10 @@ import io.sentry.protocol.DebugImage; import io.sentry.util.AutoClosableReentrantLock; import io.sentry.util.Objects; - import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.VisibleForTesting; @@ -101,11 +99,12 @@ public DebugImagesLoader( } if (relevantImages.isEmpty()) { - options.getLogger().log( - SentryLevel.WARNING, - "No debug images found for any of the %d addresses.", - addresses.size() - ); + options + .getLogger() + .log( + SentryLevel.WARNING, + "No debug images found for any of the %d addresses.", + addresses.size()); return null; } @@ -114,8 +113,8 @@ public DebugImagesLoader( } /** - * Finds a debug image containing the given address using binary search. - * Requires the images to be sorted. + * Finds a debug image containing the given address using binary search. Requires the images to be + * sorted. * * @return The matching debug image or null if not found */ From 92b0e9f01c715941840d8c1ea65510025ddd7140 Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Wed, 22 Jan 2025 00:02:16 +0100 Subject: [PATCH 12/18] update naming --- .../java/io/sentry/android/ndk/DebugImagesLoader.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index c241a008e85..3362d1c99c2 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -90,15 +90,15 @@ public DebugImagesLoader( return null; } - Set relevantImages = new HashSet<>(); + Set referencedImages = new HashSet<>(); for (Long addr : addresses) { DebugImage image = findImageByAddress(addr, allDebugImages); if (image != null) { - relevantImages.add(image); + referencedImages.add(image); } } - if (relevantImages.isEmpty()) { + if (referencedImages.isEmpty()) { options .getLogger() .log( @@ -108,7 +108,7 @@ public DebugImagesLoader( return null; } - return relevantImages; + return referencedImages; } } From b160bfceef28eab9faa8e65cffadda913d02db19 Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Wed, 22 Jan 2025 00:08:39 +0100 Subject: [PATCH 13/18] apiDump --- sentry-android-core/api/sentry-android-core.api | 1 + sentry-android-ndk/api/sentry-android-ndk.api | 1 + 2 files changed, 2 insertions(+) diff --git a/sentry-android-core/api/sentry-android-core.api b/sentry-android-core/api/sentry-android-core.api index 3f34efa9d55..56ce87d1623 100644 --- a/sentry-android-core/api/sentry-android-core.api +++ b/sentry-android-core/api/sentry-android-core.api @@ -210,6 +210,7 @@ public abstract class io/sentry/android/core/EnvelopeFileObserverIntegration : i public abstract interface class io/sentry/android/core/IDebugImagesLoader { public abstract fun clearDebugImages ()V public abstract fun loadDebugImages ()Ljava/util/List; + public abstract fun loadDebugImagesForAddresses (Ljava/util/Set;)Ljava/util/Set; } public final class io/sentry/android/core/InternalSentrySdk { diff --git a/sentry-android-ndk/api/sentry-android-ndk.api b/sentry-android-ndk/api/sentry-android-ndk.api index 155a368b11e..eb5f48a9bd9 100644 --- a/sentry-android-ndk/api/sentry-android-ndk.api +++ b/sentry-android-ndk/api/sentry-android-ndk.api @@ -10,6 +10,7 @@ public final class io/sentry/android/ndk/DebugImagesLoader : io/sentry/android/c public fun (Lio/sentry/android/core/SentryAndroidOptions;Lio/sentry/ndk/NativeModuleListLoader;)V public fun clearDebugImages ()V public fun loadDebugImages ()Ljava/util/List; + public fun loadDebugImagesForAddresses (Ljava/util/Set;)Ljava/util/Set; } public final class io/sentry/android/ndk/NdkScopeObserver : io/sentry/ScopeObserverAdapter { From ba3e989e7ac91e049e7a5fc468c0c6b0eaa1ab3a Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Wed, 5 Feb 2025 11:03:33 +0100 Subject: [PATCH 14/18] Improve Nullability, consider case of null imageSize --- .../sentry/android/ndk/DebugImagesLoader.java | 78 +++++++++++-------- .../android/ndk/DebugImagesLoaderTest.kt | 41 ++++++++-- 2 files changed, 81 insertions(+), 38 deletions(-) diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index 3362d1c99c2..82bc7a3bd03 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -27,7 +27,7 @@ public final class DebugImagesLoader implements IDebugImagesLoader { private final @NotNull NativeModuleListLoader moduleListLoader; - private static @Nullable List debugImages; + private static volatile @Nullable List debugImages; /** we need to lock it because it could be called from different threads */ protected static final @NotNull AutoClosableReentrantLock debugImagesLock = @@ -81,23 +81,19 @@ public DebugImagesLoader( * Loads debug images for the given set of addresses. * * @param addresses Set of memory addresses to find debug images for - * @return Set of debug images, or null if debug images couldn't be loaded + * @return Set of matching debug images, or null if debug images couldn't be loaded */ - public @Nullable Set loadDebugImagesForAddresses(@NotNull Set addresses) { + public @Nullable Set loadDebugImagesForAddresses(final @NotNull Set addresses) { try (final @NotNull ISentryLifecycleToken ignored = debugImagesLock.acquire()) { - List allDebugImages = loadDebugImages(); + final @Nullable List allDebugImages = loadDebugImages(); if (allDebugImages == null) { return null; } - - Set referencedImages = new HashSet<>(); - for (Long addr : addresses) { - DebugImage image = findImageByAddress(addr, allDebugImages); - if (image != null) { - referencedImages.add(image); - } + if (addresses.isEmpty()) { + return null; } + final Set referencedImages = filterImagesByAddresses(allDebugImages, addresses); if (referencedImages.isEmpty()) { options .getLogger() @@ -118,31 +114,47 @@ public DebugImagesLoader( * * @return The matching debug image or null if not found */ - private @Nullable DebugImage findImageByAddress(long address, List images) { - int left = 0; - int right = images.size() - 1; - - while (left <= right) { - int mid = left + (right - left) / 2; - DebugImage image = images.get(mid); - - if (image.getImageAddr() == null || image.getImageSize() == null) { - return null; - } - - long imageStart = Long.parseLong(image.getImageAddr().replace("0x", ""), 16); - long imageEnd = imageStart + image.getImageSize(); - - if (address >= imageStart && address < imageEnd) { - return image; - } else if (address < imageStart) { - right = mid - 1; - } else { - left = mid + 1; + private @NotNull Set filterImagesByAddresses( + final @NotNull List images, final @NotNull Set addresses) { + final Set result = new HashSet<>(); + + for (int i = 0; i < images.size(); i++) { + final @NotNull DebugImage image = images.get(i); + final @Nullable DebugImage nextDebugImage = + (i + 1) < images.size() ? images.get(i + 1) : null; + final @Nullable String nextDebugImageAddress = + nextDebugImage != null ? nextDebugImage.getImageAddr() : null; + + for (final @NotNull Long address : addresses) { + final @Nullable String imageAddress = image.getImageAddr(); + + if (imageAddress != null) { + try { + final long imageStart = Long.parseLong(imageAddress.replace("0x", ""), 16); + final long imageEnd; + + final @Nullable Long imageSize = image.getImageSize(); + if (imageSize != null) { + imageEnd = imageStart + imageSize; + } else if (nextDebugImageAddress != null) { + imageEnd = Long.parseLong(nextDebugImageAddress.replace("0x", ""), 16); + } else { + imageEnd = Long.MAX_VALUE; + } + if (address >= imageStart && address < imageEnd) { + result.add(image); + // once image is added we can skip the remaining addresses and go straight to the next + // image + break; + } + } catch (NumberFormatException e) { + options.getLogger().log(SentryLevel.WARNING, e, "Failed to parse image address."); + } + } } } - return null; + return result; } @Override diff --git a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt index 45aa37c7a48..650a046d27f 100644 --- a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt +++ b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt @@ -17,11 +17,13 @@ class DebugImagesLoaderTest { val options = SentryAndroidOptions() fun getSut(): DebugImagesLoader { - return DebugImagesLoader(options, nativeLoader) + val loader = DebugImagesLoader(options, nativeLoader) + loader.clearDebugImages() + return loader } } - private val fixture = Fixture() + private var fixture = Fixture() @Test fun `get images returns image list`() { @@ -102,11 +104,12 @@ class DebugImagesLoaderTest { val result = sut.loadDebugImagesForAddresses( setOf(0x1500L, 0x2500L) - )!!.toList() + ) + assertNotNull(result) assertEquals(2, result.size) - assertEquals(image1.imageAddr, result[0].imageAddr) - assertEquals(image2.imageAddr, result[1].imageAddr) + assertTrue(result.any { it.imageAddr == image1.imageAddr }) + assertTrue(result.any { it.imageAddr == image2.imageAddr }) } @Test @@ -152,4 +155,32 @@ class DebugImagesLoaderTest { assertNull(result) } + + @Test + fun `invalid image adresses are ignored for loadDebugImagesForAddresses`() { + val sut = fixture.getSut() + + val image1 = io.sentry.ndk.DebugImage().apply { + imageAddr = "0xNotANumber" + imageSize = 0x1000L + } + + val image2 = io.sentry.ndk.DebugImage().apply { + imageAddr = "0x2000" + imageSize = null + } + + val image3 = io.sentry.ndk.DebugImage().apply { + imageAddr = "0x5000" + imageSize = 0x1000L + } + + whenever(fixture.nativeLoader.loadModuleList()).thenReturn(arrayOf(image1, image2, image3)) + + val hexAddresses = setOf(100L, 0x2000L, 0x2000L, 0x5000L) + val result = sut.loadDebugImagesForAddresses(hexAddresses) + + assertNotNull(result) + assertEquals(2, result.size) + } } From febcd832a6f80fcd03c35f0caa02f64bd6896a30 Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Tue, 21 Jan 2025 17:47:04 +0100 Subject: [PATCH 15/18] Add fetching debug images by addresses update test clean up update test update comments remove file fix imports update docs revert doc use hashset Format code update naming apiDump Improve Nullability, consider case of null imageSize Update tests, ensure code_file and debug_file are set --- .../android/core/IDebugImagesLoader.java | 2 +- .../android/core/NoOpDebugImagesLoader.java | 2 +- .../sentry/android/ndk/DebugImagesLoader.java | 60 +++++++++++-------- .../android/ndk/DebugImagesLoaderTest.kt | 8 +-- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java b/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java index 541ed0f157f..7b98147aab8 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/IDebugImagesLoader.java @@ -13,7 +13,7 @@ public interface IDebugImagesLoader { List loadDebugImages(); @Nullable - Set loadDebugImagesForAddresses(Set addresses); + Set loadDebugImagesForAddresses(Set addresses); void clearDebugImages(); } diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java b/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java index 660e2425956..193b7342193 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/NoOpDebugImagesLoader.java @@ -21,7 +21,7 @@ public static NoOpDebugImagesLoader getInstance() { } @Override - public @Nullable Set loadDebugImagesForAddresses(Set addresses) { + public @Nullable Set loadDebugImagesForAddresses(Set addresses) { return null; } diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index 82bc7a3bd03..35fcfb2fff6 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -56,6 +56,8 @@ public DebugImagesLoader( debugImages = new ArrayList<>(debugImagesArr.length); for (io.sentry.ndk.DebugImage d : debugImagesArr) { final DebugImage debugImage = new DebugImage(); + debugImage.setCodeFile(d.getCodeFile()); + debugImage.setDebugFile(d.getDebugFile()); debugImage.setUuid(d.getUuid()); debugImage.setType(d.getType()); debugImage.setDebugId(d.getDebugId()); @@ -83,7 +85,8 @@ public DebugImagesLoader( * @param addresses Set of memory addresses to find debug images for * @return Set of matching debug images, or null if debug images couldn't be loaded */ - public @Nullable Set loadDebugImagesForAddresses(final @NotNull Set addresses) { + public @Nullable Set loadDebugImagesForAddresses( + final @NotNull Set addresses) { try (final @NotNull ISentryLifecycleToken ignored = debugImagesLock.acquire()) { final @Nullable List allDebugImages = loadDebugImages(); if (allDebugImages == null) { @@ -115,7 +118,7 @@ public DebugImagesLoader( * @return The matching debug image or null if not found */ private @NotNull Set filterImagesByAddresses( - final @NotNull List images, final @NotNull Set addresses) { + final @NotNull List images, final @NotNull Set addresses) { final Set result = new HashSet<>(); for (int i = 0; i < images.size(); i++) { @@ -125,35 +128,40 @@ public DebugImagesLoader( final @Nullable String nextDebugImageAddress = nextDebugImage != null ? nextDebugImage.getImageAddr() : null; - for (final @NotNull Long address : addresses) { - final @Nullable String imageAddress = image.getImageAddr(); - - if (imageAddress != null) { - try { - final long imageStart = Long.parseLong(imageAddress.replace("0x", ""), 16); - final long imageEnd; - - final @Nullable Long imageSize = image.getImageSize(); - if (imageSize != null) { - imageEnd = imageStart + imageSize; - } else if (nextDebugImageAddress != null) { - imageEnd = Long.parseLong(nextDebugImageAddress.replace("0x", ""), 16); - } else { - imageEnd = Long.MAX_VALUE; - } - if (address >= imageStart && address < imageEnd) { - result.add(image); - // once image is added we can skip the remaining addresses and go straight to the next - // image - break; + for (final @NotNull String rawAddress : addresses) { + try { + final long address = Long.parseLong(rawAddress.replace("0x", ""), 16); + + final @Nullable String imageAddress = image.getImageAddr(); + if (imageAddress != null) { + try { + final long imageStart = Long.parseLong(imageAddress.replace("0x", ""), 16); + final long imageEnd; + + final @Nullable Long imageSize = image.getImageSize(); + if (imageSize != null) { + imageEnd = imageStart + imageSize; + } else if (nextDebugImageAddress != null) { + imageEnd = Long.parseLong(nextDebugImageAddress.replace("0x", ""), 16); + } else { + imageEnd = Long.MAX_VALUE; + } + if (address >= imageStart && address < imageEnd) { + result.add(image); + // once image is added we can skip the remaining addresses and go straight to the + // next + // image + break; + } + } catch (NumberFormatException e) { + // ignored, invalid debug image address } - } catch (NumberFormatException e) { - options.getLogger().log(SentryLevel.WARNING, e, "Failed to parse image address."); } + } catch (NumberFormatException e) { + // ignored, invalid address supplied } } } - return result; } diff --git a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt index 650a046d27f..912a2911c5d 100644 --- a/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt +++ b/sentry-android-ndk/src/test/java/io/sentry/android/ndk/DebugImagesLoaderTest.kt @@ -103,7 +103,7 @@ class DebugImagesLoaderTest { whenever(fixture.nativeLoader.loadModuleList()).thenReturn(arrayOf(image1, image2, image3)) val result = sut.loadDebugImagesForAddresses( - setOf(0x1500L, 0x2500L) + setOf("0x1500", "0x2500") ) assertNotNull(result) @@ -128,7 +128,7 @@ class DebugImagesLoaderTest { whenever(fixture.nativeLoader.loadModuleList()).thenReturn(arrayOf(image1, image2)) - val hexAddresses = setOf(-100, 0x1500L) + val hexAddresses = setOf("0xINVALID", "0x1500") val result = sut.loadDebugImagesForAddresses(hexAddresses) assertEquals(1, result!!.size) @@ -150,7 +150,7 @@ class DebugImagesLoaderTest { whenever(fixture.nativeLoader.loadModuleList()).thenReturn(arrayOf(image1, image2)) - val hexAddresses = setOf(-100, 0x10500L) + val hexAddresses = setOf("0x100", "0x10500") val result = sut.loadDebugImagesForAddresses(hexAddresses) assertNull(result) @@ -177,7 +177,7 @@ class DebugImagesLoaderTest { whenever(fixture.nativeLoader.loadModuleList()).thenReturn(arrayOf(image1, image2, image3)) - val hexAddresses = setOf(100L, 0x2000L, 0x2000L, 0x5000L) + val hexAddresses = setOf("0x100", "0x2000", "0x2000", "0x5000") val result = sut.loadDebugImagesForAddresses(hexAddresses) assertNotNull(result) From ade3133113532554c16c932ea365fbd7db720f9c Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Mon, 10 Feb 2025 19:42:41 +0100 Subject: [PATCH 16/18] Fix test --- .../java/io/sentry/android/core/SentryAndroidOptionsTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt index 4f4a12924fc..d3e8e9a239b 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidOptionsTest.kt @@ -182,7 +182,7 @@ class SentryAndroidOptionsTest { private class CustomDebugImagesLoader : IDebugImagesLoader { override fun loadDebugImages(): List? = null - override fun loadDebugImagesForAddresses(addresses: Set?): Set? = null + override fun loadDebugImagesForAddresses(addresses: Set?): Set? = null override fun clearDebugImages() {} } From 2b77bd3503ef8494f5aed3772969aa2f5cd73c81 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Tue, 11 Feb 2025 09:21:25 +0100 Subject: [PATCH 17/18] Update javadoc --- .../main/java/io/sentry/android/ndk/DebugImagesLoader.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java index 35fcfb2fff6..602981c1d01 100644 --- a/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java +++ b/sentry-android-ndk/src/main/java/io/sentry/android/ndk/DebugImagesLoader.java @@ -112,10 +112,10 @@ public DebugImagesLoader( } /** - * Finds a debug image containing the given address using binary search. Requires the images to be - * sorted. + * Finds all debug image containing the given addresses. Assumes that the images are sorted by + * address, which should always be true on Linux/Android and Windows platforms * - * @return The matching debug image or null if not found + * @return All matching debug images or null if none are found */ private @NotNull Set filterImagesByAddresses( final @NotNull List images, final @NotNull Set addresses) { From 187f21ed61b5adc91c3896508549bb0a59945477 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Tue, 11 Feb 2025 12:35:21 +0100 Subject: [PATCH 18/18] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b6e1d8b5a3..199bf7caa3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Add split apks info to the `App` context ([#3193](https://github.com/getsentry/sentry-java/pull/3193)) - Expose new `withSentryObservableEffect` method overload that accepts `SentryNavigationListener` as a parameter ([#4143](https://github.com/getsentry/sentry-java/pull/4143)) - This allows sharing the same `SentryNavigationListener` instance across fragments and composables to preserve the trace +- (Internal) Add API to filter native debug images based on stacktrace addresses ([#4089](https://github.com/getsentry/sentry-java/pull/4089)) ### Fixes