diff --git a/Sources/Testing/SourceAttribution/Backtrace.swift b/Sources/Testing/SourceAttribution/Backtrace.swift index fd7972cc4..6f6fcaabb 100644 --- a/Sources/Testing/SourceAttribution/Backtrace.swift +++ b/Sources/Testing/SourceAttribution/Backtrace.swift @@ -40,6 +40,16 @@ public struct Backtrace: Sendable { self.addresses = addresses.map { Address(UInt(bitPattern: $0)) } } +#if os(Android) && !SWT_NO_DYNAMIC_LINKING + /// The `backtrace()` function. + /// + /// This function was added to Android with API level 33, which is higher than + /// our minimum deployment target, so we look it up dynamically at runtime. + private static let _backtrace = symbol(named: "backtrace").map { + castCFunction(at: $0, to: (@convention(c) (UnsafeMutablePointer, CInt) -> CInt).self) + } +#endif + /// Get the current backtrace. /// /// - Parameters: @@ -66,9 +76,9 @@ public struct Backtrace: Sendable { initializedCount = .init(clamping: backtrace(addresses.baseAddress!, .init(clamping: addresses.count))) } #elseif os(Android) - initializedCount = addresses.withMemoryRebound(to: UnsafeMutableRawPointer.self) { addresses in - .init(clamping: backtrace(addresses.baseAddress!, .init(clamping: addresses.count))) - } +#if !SWT_NO_DYNAMIC_LINKING + initializedCount = .init(clamping: _backtrace?(addresses.baseAddress!, .init(clamping: addresses.count))) +#endif #elseif os(Linux) || os(FreeBSD) || os(OpenBSD) initializedCount = .init(clamping: backtrace(addresses.baseAddress!, .init(clamping: addresses.count))) #elseif os(Windows)