Skip to content

Commit 0503c4b

Browse files
committed
Fix view swizzling
1 parent 4a21751 commit 0503c4b

File tree

6 files changed

+20
-74
lines changed

6 files changed

+20
-74
lines changed

Sources/Swift/Core/Helper/SentryBinaryImageCache.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -157,21 +157,6 @@ import Foundation
157157
return nil
158158
}
159159

160-
func imagePathsFor(inAppInclude: String) -> Set<String> {
161-
lock.synchronized {
162-
var imagePaths = Set<String>()
163-
164-
guard let cache = self.cache else { return imagePaths }
165-
166-
for info in cache {
167-
if SentryInAppLogic.isImageNameInApp(info.name, inAppInclude: inAppInclude) {
168-
imagePaths.insert(info.name)
169-
}
170-
}
171-
return imagePaths
172-
}
173-
}
174-
175160
func getAllBinaryImages() -> [SentryBinaryImageInfo] {
176161
lock.synchronized {
177162
return cache ?? []

Sources/Swift/Core/Integrations/Performance/SentryUIViewControllerSwizzling.swift

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@_implementationOnly import _SentryPrivate
2+
import MachO
23

34
#if (os(iOS) || os(tvOS) || os(visionOS)) && !SENTRY_NO_UI_FRAMEWORK
45
import UIKit
@@ -19,7 +20,6 @@ class SentryUIViewControllerSwizzling {
1920
private let subClassFinder: SentrySubClassFinder
2021
private let imagesActedOnSubclassesOfUIViewControllers: NSMutableSet
2122
private let processInfoWrapper: SentryProcessInfoSource
22-
private let binaryImageCache: SentryBinaryImageCache
2323
private let performanceTracker: SentryUIViewControllerPerformanceTracker
2424

2525
init(
@@ -28,7 +28,6 @@ class SentryUIViewControllerSwizzling {
2828
objcRuntimeWrapper: SentryObjCRuntimeWrapper,
2929
subClassFinder: SentrySubClassFinder,
3030
processInfoWrapper: SentryProcessInfoSource,
31-
binaryImageCache: SentryBinaryImageCache,
3231
performanceTracker: SentryUIViewControllerPerformanceTracker
3332
) {
3433
self.options = options
@@ -38,19 +37,23 @@ class SentryUIViewControllerSwizzling {
3837
self.subClassFinder = subClassFinder
3938
self.imagesActedOnSubclassesOfUIViewControllers = NSMutableSet()
4039
self.processInfoWrapper = processInfoWrapper
41-
self.binaryImageCache = binaryImageCache
4240
self.performanceTracker = performanceTracker
4341
}
4442

4543
func start() {
46-
for inAppInclude in inAppLogic.inAppIncludes {
47-
let imagePathsToInAppInclude = binaryImageCache.imagePathsFor(inAppInclude: inAppInclude)
44+
let imageNames = (0..<_dyld_image_count()).compactMap { i in
45+
_dyld_get_image_name(i).map { String(cString: $0) }
46+
}
4847

49-
if !imagePathsToInAppInclude.isEmpty {
50-
for imagePath in imagePathsToInAppInclude {
51-
swizzleUIViewControllers(ofImage: imagePath)
48+
for inAppInclude in inAppLogic.inAppIncludes {
49+
var found = false
50+
for imageName in imageNames {
51+
if SentryInAppLogic.isImageNameInApp(imageName, inAppInclude: inAppInclude) {
52+
found = true
53+
swizzleUIViewControllers(ofImage: imageName)
5254
}
53-
} else {
55+
}
56+
if !found {
5457
SentrySDKLog.warning(
5558
"Failed to find the binary image(s) for inAppInclude <\(inAppInclude)> and, therefore can't instrument UIViewControllers in these binaries."
5659
)

Sources/Swift/SentryDependencyContainer.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ extension SentryFileManager: SentryFileManagerProtocol { }
234234
objcRuntimeWrapper: objcRuntimeWrapper,
235235
subClassFinder: subClassFinder,
236236
processInfoWrapper: processInfoWrapper,
237-
binaryImageCache: binaryImageCache,
238237
performanceTracker: uiViewControllerPerformanceTracker
239238
)
240239

Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerSwizzlingTests.swift

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@ class SentryUIViewControllerSwizzlingTests: XCTestCase {
1212
let objcRuntimeWrapper = SentryTestObjCRuntimeWrapper()
1313
let subClassFinder: TestSubClassFinder
1414
let processInfoWrapper = MockSentryProcessInfo()
15-
let binaryImageCache: SentryBinaryImageCache
1615
let performanceTracker = SentryUIViewControllerPerformanceTracker()
1716
var options: Options
1817

1918
init() {
2019
subClassFinder = TestSubClassFinder(dispatchQueue: dispatchQueue, objcRuntimeWrapper: objcRuntimeWrapper, swizzleClassNameExcludes: [])
21-
binaryImageCache = SentryDependencyContainer.sharedInstance().binaryImageCache
2220

2321
options = Options.noIntegrations()
2422

@@ -29,15 +27,15 @@ class SentryUIViewControllerSwizzlingTests: XCTestCase {
2927
}
3028

3129
var sut: SentryUIViewControllerSwizzling {
32-
return SentryUIViewControllerSwizzling(options: options, dispatchQueue: dispatchQueue, objcRuntimeWrapper: objcRuntimeWrapper, subClassFinder: subClassFinder, processInfoWrapper: processInfoWrapper, binaryImageCache: binaryImageCache, performanceTracker: performanceTracker)
30+
return SentryUIViewControllerSwizzling(options: options, dispatchQueue: dispatchQueue, objcRuntimeWrapper: objcRuntimeWrapper, subClassFinder: subClassFinder, processInfoWrapper: processInfoWrapper, performanceTracker: performanceTracker)
3331
}
3432

3533
var sutWithDefaultObjCRuntimeWrapper: SentryUIViewControllerSwizzling {
36-
return SentryUIViewControllerSwizzling(options: options, dispatchQueue: dispatchQueue, objcRuntimeWrapper: SentryDependencyContainer.sharedInstance().objcRuntimeWrapper, subClassFinder: subClassFinder, processInfoWrapper: processInfoWrapper, binaryImageCache: binaryImageCache, performanceTracker: performanceTracker)
34+
return SentryUIViewControllerSwizzling(options: options, dispatchQueue: dispatchQueue, objcRuntimeWrapper: SentryDependencyContainer.sharedInstance().objcRuntimeWrapper, subClassFinder: subClassFinder, processInfoWrapper: processInfoWrapper, performanceTracker: performanceTracker)
3735
}
3836

3937
var testableSut: TestSentryUIViewControllerSwizzling {
40-
return TestSentryUIViewControllerSwizzling(options: options, dispatchQueue: dispatchQueue, objcRuntimeWrapper: objcRuntimeWrapper, subClassFinder: subClassFinder, processInfoWrapper: processInfoWrapper, binaryImageCache: binaryImageCache, performanceTracker: performanceTracker)
38+
return TestSentryUIViewControllerSwizzling(options: options, dispatchQueue: dispatchQueue, objcRuntimeWrapper: objcRuntimeWrapper, subClassFinder: subClassFinder, processInfoWrapper: processInfoWrapper, performanceTracker: performanceTracker)
4139
}
4240

4341
var delegate: MockApplication.MockApplicationDelegate {
@@ -187,30 +185,6 @@ class SentryUIViewControllerSwizzlingTests: XCTestCase {
187185
XCTAssertNotNil(SentrySDK.span)
188186
}
189187

190-
/// Xcode 16 introduces a new flag ENABLE_DEBUG_DYLIB (https://developer.apple.com/documentation/xcode/build-settings-reference#Enable-Debug-Dylib-Support)
191-
/// If this flag is enabled, debug builds of app and app extension targets on supported platforms and SDKs
192-
/// will be built with the main binary code in a separate “NAME.debug.dylib”.
193-
/// This test adds this debug.dylib and checks if it gets swizzled.
194-
func testSwizzle_DebugDylib_GetsSwizzled() {
195-
let imageName = String(
196-
cString: class_getImageName(SentryUIViewControllerSwizzlingTests.self)!,
197-
encoding: .utf8)! as NSString
198-
199-
let debugDylib = "\(imageName).debug.dylib"
200-
201-
let image = createCrashBinaryImage(0, name: debugDylib)
202-
SentryDependencyContainer.sharedInstance().binaryImageCache.start(false)
203-
SentryDependencyContainer.sharedInstance().binaryImageCache.binaryImageAdded(image: image)
204-
205-
let sut = fixture.sut
206-
sut.start()
207-
208-
let subClassFinderInvocations = fixture.subClassFinder.invocations
209-
let result = subClassFinderInvocations.invocations.filter { $0.imageName == debugDylib }
210-
211-
XCTAssertEqual(1, result.count)
212-
}
213-
214188
func testSwizzle_fromScene_invalidNotification_NoObject() {
215189
let swizzler = fixture.testableSut
216190

Tests/SentryTests/SentryBinaryImageCacheTests.swift

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -121,25 +121,6 @@ class SentryBinaryImageCacheTests: XCTestCase {
121121
XCTAssertNil(sut.imageByAddress(399))
122122
}
123123

124-
func testImagePathByName() {
125-
let binaryImage = createCrashBinaryImage(0)
126-
let binaryImage2 = createCrashBinaryImage(1)
127-
addBinaryImageToSut(binaryImage)
128-
addBinaryImageToSut(binaryImage2)
129-
130-
let paths = sut.imagePathsFor(inAppInclude: "Expected Name at 0")
131-
XCTAssertEqual(paths.first, "Expected Name at 0")
132-
133-
let paths2 = sut.imagePathsFor(inAppInclude: "Expected Name at 1")
134-
XCTAssertEqual(paths2.first, "Expected Name at 1")
135-
136-
let bothPaths = sut.imagePathsFor(inAppInclude: "Expected")
137-
XCTAssertEqual(bothPaths, ["Expected Name at 0", "Expected Name at 1"])
138-
139-
let didNotFind = sut.imagePathsFor(inAppInclude: "Name at 0")
140-
XCTAssertTrue(didNotFind.isEmpty)
141-
}
142-
143124
func testBinaryImageWithNULLName_DoesNotAddImage() {
144125
let address = UInt64(100)
145126

Tests/SentryTests/SentryCrash/SentryCrashBinaryImageCacheTests.m

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,11 @@ - (void)assertBinaryImageCacheLength:(int)expected
310310
{
311311
int counter = 0;
312312
sentrycrashbic_iterateOverImages(countNumberOfImagesInCache, &counter);
313-
XCTAssertEqual(counter, expected);
313+
NSMutableArray<NSString *> *paths = [NSMutableArray new];
314+
[SentryDependencyContainer.sharedInstance.binaryImageCache.cache enumerateObjectsUsingBlock:^(SentryBinaryImageInfo * _Nonnull obj, NSUInteger __unused idx, BOOL * _Nonnull __unused stop) {
315+
[paths addObject:obj.name];
316+
}];
317+
XCTAssertEqual(counter, expected, @"Cache should have %d images but contained %@", expected, paths);
314318
}
315319

316320
- (void)assertCachedBinaryImages

0 commit comments

Comments
 (0)