@@ -14,10 +14,10 @@ private import _TestingInternals
14
14
@_spi ( ForToolsIntegrationOnly)
15
15
extension Backtrace {
16
16
/// Demangle a symbol name.
17
- ///
17
+ ///
18
18
/// - Parameters:
19
19
/// - mangledSymbolName: The symbol name to demangle.
20
- ///
20
+ ///
21
21
/// - Returns: The demangled form of `mangledSymbolName` according to the
22
22
/// Swift standard library or the platform's C++ standard library, or `nil`
23
23
/// if the symbol name could not be demangled.
@@ -31,35 +31,62 @@ extension Backtrace {
31
31
return String ( validatingCString: demangledSymbolName)
32
32
}
33
33
34
- /// Symbolicate a sequence of addresses.
35
- ///
34
+ /// An enumeration describing the symbolication mode to use when handling
35
+ /// events containing backtraces.
36
+ public enum SymbolicationMode : Sendable {
37
+ /// The backtrace should be symbolicated, but no demangling should be
38
+ /// performed.
39
+ case mangled
40
+
41
+ /// The backtrace should be symbolicated and Swift and C++ symbols should be
42
+ /// demangled if possible.
43
+ case demangled
44
+ }
45
+
46
+ /// A type representing an instance of ``Backtrace/Address`` that has been
47
+ /// symbolicated by a call to ``Backtrace/symbolicate(_:)``.
48
+ public struct SymbolicatedAddress : Sendable {
49
+ /// The (unsymbolicated) address from the backtrace.
50
+ public var address : Address
51
+
52
+ /// The offset of ``address`` from the start of the corresponding function,
53
+ /// if available.
54
+ ///
55
+ /// If ``address`` could not be resolved to a symbol, the value of this
56
+ /// property is `nil`.
57
+ public var offset : UInt64 ?
58
+
59
+ /// The name of the symbol at ``address``, if available.
60
+ ///
61
+ /// If ``address`` could not be resolved to a symbol, the value of this
62
+ /// property is `nil`.
63
+ public var symbolName : String ?
64
+ }
65
+
66
+ /// Symbolicate the addresses in this backtrace.
67
+ ///
36
68
/// - Parameters:
37
- /// - addresses: The sequence of addresses. These addresses must have
38
- /// originated in the current process.
39
69
/// - mode: How to symbolicate the addresses in the backtrace.
40
- ///
70
+ ///
41
71
/// - Returns: An array of strings representing the names of symbols in
42
72
/// `addresses`.
43
- ///
44
- /// If an address in `addresses` cannot be symbolicated, it is converted to a
45
- /// string using ``Swift/String/init(describingForTest:)``.
46
- private static func _symbolicate ( addresses : UnsafeBufferPointer < UnsafeRawPointer ? > , mode : SymbolicationMode ) -> [ String ] {
47
- let count = addresses . count
48
- var symbolNames = [ ( String , displacement : UInt ) ? ] ( repeating : nil , count : count )
73
+ ///
74
+ /// If an address in `addresses` cannot be symbolicated, the corresponding
75
+ /// instance of ``SymbolicatedAddress`` in the resulting array has a `nil`
76
+ /// value for its ``Backtrace/SymbolicatedAddress/symbolName`` property.
77
+ public func symbolicate ( _ mode : SymbolicationMode ) -> [ SymbolicatedAddress ] {
78
+ var result = addresses . map { SymbolicatedAddress ( address : $0 ) }
49
79
50
80
#if SWT_TARGET_OS_APPLE
51
81
for (i, address) in addresses. enumerated ( ) {
52
- guard let address else {
53
- continue
54
- }
55
82
var info = Dl_info ( )
56
- if 0 != dladdr ( address, & info) {
57
- let displacement = UInt ( bitPattern : address) - UInt( bitPattern: info. dli_saddr)
83
+ if 0 != dladdr ( UnsafePointer ( bitPattern : UInt ( clamping : address) ) , & info) {
84
+ let offset = address - Address ( clamping : UInt ( bitPattern: info. dli_saddr) )
58
85
if var symbolName = info. dli_sname. flatMap ( String . init ( validatingCString: ) ) {
59
86
if mode != . mangled {
60
- symbolName = _demangle ( symbolName) ?? symbolName
87
+ symbolName = Self . _demangle ( symbolName) ?? symbolName
61
88
}
62
- symbolNames [ i] = ( symbolName , displacement )
89
+ result [ i] = SymbolicatedAddress ( address : address , offset : offset , symbolName : symbolName )
63
90
}
64
91
}
65
92
}
@@ -77,21 +104,17 @@ extension Backtrace {
77
104
return
78
105
}
79
106
for (i, address) in addresses. enumerated ( ) {
80
- guard let address else {
81
- continue
82
- }
83
-
84
107
withUnsafeTemporaryAllocation ( of: SYMBOL_INFO_PACKAGEW . self, capacity: 1 ) { symbolInfo in
85
108
let symbolInfo = symbolInfo. baseAddress!
86
109
symbolInfo. pointee. si. SizeOfStruct = ULONG ( MemoryLayout< SYMBOL_INFOW> . stride)
87
110
symbolInfo. pointee. si. MaxNameLen = ULONG ( MAX_SYM_NAME)
88
111
var displacement = DWORD64 ( 0 )
89
- if SymFromAddrW ( hProcess, DWORD64 ( clamping: UInt ( bitPattern : address) ) , & displacement, symbolInfo. pointer ( to: \. si) !) ,
112
+ if SymFromAddrW ( hProcess, DWORD64 ( clamping: address) , & displacement, symbolInfo. pointer ( to: \. si) !) ,
90
113
var symbolName = String . decodeCString ( symbolInfo. pointer ( to: \. si. Name) !, as: UTF16 . self) ? . result {
91
114
if mode != . mangled {
92
- symbolName = _demangle ( symbolName) ?? symbolName
115
+ symbolName = Self . _demangle ( symbolName) ?? symbolName
93
116
}
94
- symbolNames [ i] = ( symbolName , UInt ( clamping : displacement) )
117
+ result [ i] = SymbolicatedAddress ( address : address , offset : displacement, symbolName : symbolName )
95
118
}
96
119
}
97
120
}
@@ -102,67 +125,13 @@ extension Backtrace {
102
125
#warning("Platform-specific implementation missing: backtrace symbolication unavailable")
103
126
#endif
104
127
105
- var result = [ String] ( )
106
- result. reserveCapacity ( count)
107
- for (i, address) in addresses. enumerated ( ) {
108
- let formatted = if let ( symbolName, displacement) = symbolNames [ i] {
109
- if mode == . preciseDemangled {
110
- " \( i) \( symbolName) ( \( String ( describingForTest: address) ) + \( displacement) ) "
111
- } else {
112
- symbolName
113
- }
114
- } else {
115
- String ( describingForTest: address)
116
- }
117
- result. append ( formatted)
118
- }
119
128
return result
120
129
}
130
+ }
121
131
122
- /// An enumeration describing the symbolication mode to use when handling
123
- /// events containing backtraces.
124
- public enum SymbolicationMode : Sendable {
125
- /// The backtrace should be symbolicated, but no demangling should be
126
- /// performed.
127
- case mangled
128
-
129
- /// The backtrace should be symbolicated and Swift and C++ symbols should be
130
- /// demangled if possible.
131
- case demangled
132
-
133
- /// The backtrace should be symbolicated, Swift and C++ symbols should be
134
- /// demangled if possible, and precise symbol addresses and offsets should
135
- /// be provided if available.
136
- case preciseDemangled
137
- }
132
+ // MARK: - Codable
138
133
139
- /// Symbolicate the addresses in this backtrace.
140
- ///
141
- /// - Parameters:
142
- /// - mode: How to symbolicate the addresses in the backtrace.
143
- ///
144
- /// - Returns: An array of strings representing the names of symbols in
145
- /// `addresses`.
146
- ///
147
- /// If an address in `addresses` cannot be symbolicated, it is converted to a
148
- /// string using ``Swift/String/init(describingForTest:)``.
149
- public func symbolicate( _ mode: SymbolicationMode ) -> [ String ] {
150
- #if _pointerBitWidth(_64)
151
- // The width of a pointer equals the width of an `Address`, so we can just
152
- // bitcast the memory rather than mapping through UInt first.
153
- addresses. withUnsafeBufferPointer { addresses in
154
- addresses. withMemoryRebound ( to: UnsafeRawPointer ? . self) { addresses in
155
- Self . _symbolicate ( addresses: addresses, mode: mode)
156
- }
157
- }
158
- #else
159
- let addresses = addresses. map { UnsafeRawPointer ( bitPattern: UInt ( $0) ) }
160
- return addresses. withUnsafeBufferPointer { addresses in
161
- Self . _symbolicate ( addresses: addresses, mode: mode)
162
- }
163
- #endif
164
- }
165
- }
134
+ extension Backtrace . SymbolicatedAddress : Codable { }
166
135
167
136
#if os(Windows)
168
137
// MARK: -
0 commit comments