@@ -116,36 +116,17 @@ internal struct DumpGenericMetadata: ParsableCommand {
116
116
@Flag ( help: " Show allocations in mangled form " )
117
117
var mangled : Bool = false
118
118
119
+ @Flag ( help: " Scan for data that looks like Swift type metadata. " )
120
+ var scanSearch : Bool = false
121
+
119
122
func run( ) throws {
120
123
disableStdErrBuffer ( )
121
124
var metadataSummary = [ String: MetadataSummary] ( )
122
125
var allProcesses = [ ProcessMetadata] ( )
123
126
try inspect ( options: options) { process in
124
- let allocations : [ swift_metadata_allocation_t ] =
125
- try process. context. allocations. sorted ( )
126
-
127
- let stacks : [ swift_reflection_ptr_t : [ swift_reflection_ptr_t ] ] =
128
- backtraceOptions. style == nil
129
- ? [ swift_reflection_ptr_t: [ swift_reflection_ptr_t] ] ( )
130
- : try process. context. allocationStacks
131
-
132
- let generics : [ Metadata ] = allocations. compactMap { allocation -> Metadata ? in
133
- let pointer = swift_reflection_allocationMetadataPointer ( process. context, allocation)
134
- if pointer == 0 { return nil }
135
- let allocation = allocations. last ( where: { pointer >= $0. ptr && pointer < $0. ptr + swift_reflection_ptr_t( $0. size) } )
136
- let garbage = ( allocation == nil && swift_reflection_ownsAddressStrict ( process. context, UInt ( pointer) ) == 0 )
137
- var currentBacktrace : String ?
138
- if let style = backtraceOptions. style, let allocation, let stack = stacks [ allocation. ptr] {
139
- currentBacktrace = backtrace ( stack, style: style, process. symbolicate)
140
- }
141
-
142
- return Metadata ( ptr: pointer,
143
- allocation: allocation,
144
- name: process. context. name ( type: pointer, mangled: mangled) ?? " <unknown> " ,
145
- isArrayOfClass: process. context. isArrayOfClass ( pointer) ,
146
- garbage: garbage,
147
- backtrace: currentBacktrace)
148
- } // generics
127
+ let generics = scanSearch
128
+ ? try metadataFromScanning ( process: process)
129
+ : try metadataFromAllocations ( process: process)
149
130
150
131
// Update summary
151
132
generics. forEach { metadata in
@@ -182,6 +163,57 @@ internal struct DumpGenericMetadata: ParsableCommand {
182
163
}
183
164
}
184
165
166
+ private func metadataFromAllocations( process: any RemoteProcess ) throws -> [ Metadata ] {
167
+ let allocations : [ swift_metadata_allocation_t ] =
168
+ try process. context. allocations. sorted ( )
169
+
170
+ let stacks : [ swift_reflection_ptr_t : [ swift_reflection_ptr_t ] ] =
171
+ backtraceOptions. style == nil
172
+ ? [ swift_reflection_ptr_t: [ swift_reflection_ptr_t] ] ( )
173
+ : try process. context. allocationStacks
174
+
175
+ return allocations. compactMap { allocation -> Metadata ? in
176
+ let pointer = swift_reflection_allocationMetadataPointer ( process. context, allocation)
177
+ if pointer == 0 { return nil }
178
+ let allocation = allocations. last ( where: { pointer >= $0. ptr && pointer < $0. ptr + swift_reflection_ptr_t( $0. size) } )
179
+ let garbage = ( allocation == nil && swift_reflection_ownsAddressStrict ( process. context, UInt ( pointer) ) == 0 )
180
+ var currentBacktrace : String ?
181
+ if let style = backtraceOptions. style, let allocation, let stack = stacks [ allocation. ptr] {
182
+ currentBacktrace = backtrace ( stack, style: style, process. symbolicate)
183
+ }
184
+
185
+ return Metadata ( ptr: pointer,
186
+ allocation: allocation,
187
+ name: process. context. name ( type: pointer, mangled: mangled) ?? " <unknown> " ,
188
+ isArrayOfClass: process. context. isArrayOfClass ( pointer) ,
189
+ garbage: garbage,
190
+ backtrace: currentBacktrace)
191
+ }
192
+ }
193
+
194
+ private func metadataFromScanning( process: any RemoteProcess ) throws -> [ Metadata ] {
195
+ var metadata : [ Metadata ] = [ ]
196
+
197
+ func scanMemory( address: swift_reflection_ptr_t , size: UInt64 ) {
198
+ for candidate in stride ( from: address, to: address + swift_reflection_ptr_t( size) , by: MemoryLayout< UInt> . size) {
199
+ guard let name = process. context. name ( type: candidate, mangled: mangled) else {
200
+ continue
201
+ }
202
+ let m = Metadata ( ptr: candidate,
203
+ allocation: nil ,
204
+ name: name,
205
+ isArrayOfClass: process. context. isArrayOfClass ( candidate) ,
206
+ garbage: false ,
207
+ backtrace: nil )
208
+ metadata. append ( m)
209
+ }
210
+ }
211
+
212
+ process. iteratePotentialMetadataPages ( scanMemory)
213
+
214
+ return metadata
215
+ }
216
+
185
217
private func dumpText( process: any RemoteProcess , generics: [ Metadata ] ) throws {
186
218
var erroneousMetadata : [ ( ptr: swift_reflection_ptr_t , name: String ) ] = [ ]
187
219
var output = try Output ( metadataOptions. outputFile)
0 commit comments