@@ -35,7 +35,7 @@ internal struct KSCrashBacktrace: BacktraceReporting {
3535 func generateBacktrace( threadID: ThreadID ) throws -> BacktraceReport ? {
3636 // Convert Mach thread_t to pthread_t
3737 guard let pthread = pthread_from_mach_thread_np ( threadID) else {
38- telemetry. error ( " [KSCrashBacktrace] Failed to get pthread for thread with ID: \( threadID) " )
38+ telemetry. error ( " Failed to get pthread for thread with ID: \( threadID) " )
3939 return nil
4040 }
4141
@@ -66,6 +66,14 @@ internal struct KSCrashBacktrace: BacktraceReporting {
6666 let loadAddress = binaryImage. address
6767 let uuid = UUID ( uuid: imageUUID. withMemoryRebound ( to: uuid_t. self, capacity: 1 ) { $0. pointee } )
6868
69+ let offset : UInt64
70+ if address >= loadAddress {
71+ offset = UInt64 ( address) - loadAddress
72+ } else {
73+ offset = 0
74+ telemetry. error ( " Invalid image load address, symbolication will fail " )
75+ }
76+
6977 // Get architecture from binary image's CPU type
7078 let architecture = String ( cString: kscpu_archForCPU (
7179 cpu_type_t ( binaryImage. cpuType) ,
@@ -84,7 +92,7 @@ internal struct KSCrashBacktrace: BacktraceReporting {
8492 }
8593
8694 // Format: frame_index (4 chars left-aligned) + library_name (35 chars left-aligned) + addresses + offset
87- return String ( format: " %-4ld %-35@ 0x%016llx 0x%016llx + %lld " , index, libraryName, address, loadAddress, UInt64 ( address ) - loadAddress )
95+ return String ( format: " %-4ld %-35@ 0x%016llx 0x%016llx + %lld " , index, libraryName, address, loadAddress, offset )
8896 }
8997 . joined ( separator: " \n " )
9098
@@ -108,7 +116,7 @@ internal struct KSCrashBacktrace: BacktraceReporting {
108116 private func getThreadName( pthread: pthread_t ) -> String ? {
109117 var buffer = [ CChar] ( repeating: 0 , count: 256 )
110118 guard pthread_getname_np ( pthread, & buffer, buffer. count) == KERN_SUCCESS, buffer [ 0 ] != 0 else {
111- telemetry. error ( " [KSCrashBacktrace] Failed to get pthread name" )
119+ telemetry. error ( " Failed to get pthread name " )
112120 return nil // fails or empty
113121 }
114122 return String ( cString: buffer)
@@ -124,16 +132,19 @@ internal struct KSCrashBacktrace: BacktraceReporting {
124132/// This allows us to determine the correct architecture (arm64, arm64e, etc.) for each
125133/// binary image, which is critical for accurate stacktrace symbolication.
126134private func symbolicate( address: uintptr_t ) -> KSBinaryImage ? {
127- // initalize the binary image cache.
128- // this has an atomic check so isn't expensive
129- // except for the first call.
130- ksbic_init ( )
131-
132135 let untaggedAddress = kssymbolicator_callInstructionAddress ( address)
133-
136+ let instructionPointer = UnsafeRawPointer ( bitPattern: untaggedAddress)
137+
138+ // Use standard dladdr() instead of ksdl_dladdr() to work around a bug where ksdl_dladdr()
139+ // can return the wrong image when looking up addresses in the presence of dynamic
140+ // frameworks. The bug causes unsigned arithmetic underflow when calculating the
141+ // instruction offset.
142+ //
143+ // This was fixed in KSCrash and is currently pending release.
144+ // See: https://github.com/DataDog/dd-sdk-ios/issues/2645
134145 var info = Dl_info ( )
135146 guard
136- ksdl_dladdr ( untaggedAddress , & info) ,
147+ dladdr ( instructionPointer , & info) != 0 ,
137148 let baseAddress = info. dli_fbase,
138149 let fileName = info. dli_fname
139150 else {
0 commit comments