@@ -116,36 +116,17 @@ internal struct DumpGenericMetadata: ParsableCommand {
116116 @Flag ( help: " Show allocations in mangled form " )
117117 var mangled : Bool = false
118118
119+ @Flag ( help: " Scan for data that looks like Swift type metadata. " )
120+ var scanSearch : Bool = false
121+
119122 func run( ) throws {
120123 disableStdErrBuffer ( )
121124 var metadataSummary = [ String: MetadataSummary] ( )
122125 var allProcesses = [ ProcessMetadata] ( )
123126 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)
149130
150131 // Update summary
151132 generics. forEach { metadata in
@@ -182,6 +163,57 @@ internal struct DumpGenericMetadata: ParsableCommand {
182163 }
183164 }
184165
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+
185217 private func dumpText( process: any RemoteProcess , generics: [ Metadata ] ) throws {
186218 var erroneousMetadata : [ ( ptr: swift_reflection_ptr_t , name: String ) ] = [ ]
187219 var output = try Output ( metadataOptions. outputFile)
0 commit comments