@@ -49,8 +49,6 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
4949 }
5050 }
5151
52- let ptrace : SwiftInspectLinux . PTrace
53-
5452 // We call mmap/munmap in the remote process to alloc/free memory for our own
5553 // use without impacting existing allocations in the remote process.
5654 lazy var mmapSymbol : RemoteSymbol = RemoteSymbol ( " mmap " , self . symbolCache)
@@ -63,16 +61,6 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
6361 lazy var mallocEnableSymbol : RemoteSymbol = RemoteSymbol ( " malloc_enable " , self . symbolCache)
6462 lazy var mallocIterateSymbol : RemoteSymbol = RemoteSymbol ( " malloc_iterate " , self . symbolCache)
6563
66- override init ? ( processId: ProcessIdentifier ) {
67- do {
68- self . ptrace = try SwiftInspectLinux . PTrace ( process: processId)
69- } catch {
70- print ( " failed initialization: \( error) " )
71- return nil
72- }
73- super. init ( processId: processId)
74- }
75-
7664 // Linux and Android have no supported method to enumerate allocations in the
7765 // heap of a remote process. Android does, however, support the malloc_iterate
7866 // API, which enumerates allocations in the current process. We leverage this
@@ -81,26 +69,27 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
8169 override internal func iterateHeap( _ body: ( swift_addr_t , UInt64 ) -> Void ) {
8270 var regionCount = 0
8371 var allocCount = 0
84- for entry in self . memoryMap. entries {
85- // Limiting malloc_iterate calls to only memory regions that are known
86- // to contain heap allocations is not strictly necessary but it does
87- // significantly improve the speed of heap iteration.
88- guard entry. isHeapRegion ( ) else { continue }
89-
90- // collect all of the allocations in this heap region
91- let allocations : [ ( base: swift_addr_t , len: UInt64 ) ]
92- do {
93- allocations = try self . iterateHeapRegion ( region: entry)
94- regionCount += 1
95- } catch {
96- print ( " failed iterating remote heap: \( error) " )
97- return
72+ do {
73+ try PTrace . withAttachedProcess ( pid: self . processIdentifier) { ptrace in
74+ for entry in self . memoryMap. entries {
75+ // Limiting malloc_iterate calls to only memory regions that are known
76+ // to contain heap allocations is not strictly necessary but it does
77+ // significantly improve the speed of heap iteration.
78+ guard entry. isHeapRegion ( ) else { continue }
79+
80+ // collect all of the allocations in this heap region
81+ let allocations : [ ( base: swift_addr_t , len: UInt64 ) ]
82+ allocations = try self . iterateHeapRegion ( ptrace, region: entry)
83+ regionCount += 1
84+ allocCount += allocations. count
85+
86+ // process all of the collected allocations
87+ for alloc in allocations { body ( alloc. base, alloc. len) }
88+ }
9889 }
99-
100- allocCount += allocations. count
101-
102- // process all of the collected allocations
103- for alloc in allocations { body ( alloc. base, alloc. len) }
90+ } catch {
91+ print ( " failed iterating remote heap: \( error) " )
92+ return
10493 }
10594
10695 if regionCount == 0 {
@@ -116,16 +105,16 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
116105
117106 // Iterate a single heap region in the remote process and return an array
118107 // of (base, len) pairs describing each heap allocation in the region.
119- internal func iterateHeapRegion( region: MemoryMap . Entry ) throws -> [ (
108+ internal func iterateHeapRegion( _ ptrace : PTrace , region: MemoryMap . Entry ) throws -> [ (
120109 base: swift_addr_t , len: UInt64
121110 ) ] {
122111 // Allocate a page-sized buffer in the remote process that malloc_iterate
123112 // will populaate with metadata describing each heap entry it enumerates.
124113 let dataLen = sysconf ( Int32 ( _SC_PAGESIZE) )
125114 let remoteDataAddr = try self . mmapRemote (
126- len: dataLen, prot: PROT_READ | PROT_WRITE, flags: MAP_ANON | MAP_PRIVATE)
115+ ptrace , len: dataLen, prot: PROT_READ | PROT_WRITE, flags: MAP_ANON | MAP_PRIVATE)
127116 defer {
128- _ = try ? self . munmapRemote ( addr: remoteDataAddr, len: dataLen)
117+ _ = try ? self . munmapRemote ( ptrace , addr: remoteDataAddr, len: dataLen)
129118 }
130119
131120 // Allocate and inialize a local buffer that will be used to copy metadata
@@ -142,9 +131,9 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
142131 // executed in the remote process.
143132 let codeLen = heap_iterate_callback_len ( )
144133 let remoteCodeAddr = try mmapRemote (
145- len: codeLen, prot: PROT_READ | PROT_WRITE | PROT_EXEC, flags: MAP_ANON | MAP_PRIVATE)
134+ ptrace , len: codeLen, prot: PROT_READ | PROT_WRITE | PROT_EXEC, flags: MAP_ANON | MAP_PRIVATE)
146135 defer {
147- _ = try ? self . munmapRemote ( addr: remoteCodeAddr, len: codeLen)
136+ _ = try ? self . munmapRemote ( ptrace , addr: remoteCodeAddr, len: codeLen)
148137 }
149138
150139 // Copy the malloc_iterate callback implementation to the remote process.
@@ -158,9 +147,9 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
158147
159148 // Disable malloc/free while enumerating the region to get a consistent
160149 // snapshot of existing allocations.
161- try self . mallocDisableRemote ( )
150+ try self . mallocDisableRemote ( ptrace )
162151 defer {
163- _ = try ? self . mallocEnableRemote ( )
152+ _ = try ? self . mallocEnableRemote ( ptrace )
164153 }
165154
166155 // Collects (base, len) pairs describing each heap allocation in the remote
@@ -169,7 +158,7 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
169158
170159 let regionLen = region. endAddr - region. startAddr
171160 let args = [ region. startAddr, regionLen, remoteCodeAddr, remoteDataAddr]
172- _ = try self . ptrace. callRemoteFunction ( at : mallocIterateAddr, with: args) {
161+ _ = try ptrace. jump ( to : mallocIterateAddr, with: args) {
173162 // This callback is invoked when a SIGTRAP is encountered in the remote
174163 // process. In this context, this signal indicates there is no more room
175164 // in the allocated metadata region (see AndroidCLib/heap.c).
@@ -183,11 +172,11 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
183172 }
184173 try self . process. writeMem ( remoteAddr: remoteDataAddr, localAddr: buffer, len: UInt ( dataLen) )
185174
186- var regs = try self . ptrace. getRegSet ( )
175+ var regs = try ptrace. getRegSet ( )
187176 regs. step ( RegisterSet . trapInstructionSize)
188177
189- try self . ptrace. setRegSet ( regSet: regs)
190- try self . ptrace. cont ( )
178+ try ptrace. setRegSet ( regSet: regs)
179+ try ptrace. cont ( )
191180 }
192181
193182 try self . process. readMem ( remoteAddr: remoteDataAddr, localAddr: buffer, len: UInt ( dataLen) )
@@ -219,37 +208,37 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
219208 }
220209
221210 // call mmap in the remote process with the provided arguments
222- internal func mmapRemote( len: Int , prot: Int32 , flags: Int32 ) throws -> UInt64 {
211+ internal func mmapRemote( _ ptrace : PTrace , len: Int , prot: Int32 , flags: Int32 ) throws -> UInt64 {
223212 guard let sym = self . mmapSymbol. addr else {
224213 throw RemoteProcessError . missingSymbol ( self . mmapSymbol. name)
225214 }
226215 let args = [ 0 , UInt64 ( len) , UInt64 ( prot) , UInt64 ( flags) ]
227- return try self . ptrace. callRemoteFunction ( at : sym, with: args)
216+ return try ptrace. jump ( to : sym, with: args)
228217 }
229218
230219 // call munmap in the remote process with the provdied arguments
231- internal func munmapRemote( addr: UInt64 , len: Int ) throws -> UInt64 {
220+ internal func munmapRemote( _ ptrace : PTrace , addr: UInt64 , len: Int ) throws -> UInt64 {
232221 guard let sym = self . munmapSymbol. addr else {
233222 throw RemoteProcessError . missingSymbol ( self . munmapSymbol. name)
234223 }
235224 let args : [ UInt64 ] = [ addr, UInt64 ( len) ]
236- return try self . ptrace. callRemoteFunction ( at : sym, with: args)
225+ return try ptrace. jump ( to : sym, with: args)
237226 }
238227
239228 // call malloc_disable in the remote process
240- internal func mallocDisableRemote( ) throws {
229+ internal func mallocDisableRemote( _ ptrace : PTrace ) throws {
241230 guard let sym = self . mallocDisableSymbol. addr else {
242231 throw RemoteProcessError . missingSymbol ( self . mallocDisableSymbol. name)
243232 }
244- _ = try self . ptrace. callRemoteFunction ( at : sym)
233+ _ = try ptrace. jump ( to : sym)
245234 }
246235
247236 // call malloc_enable in the remote process
248- internal func mallocEnableRemote( ) throws {
237+ internal func mallocEnableRemote( _ ptrace : PTrace ) throws {
249238 guard let sym = self . mallocEnableSymbol. addr else {
250239 throw RemoteProcessError . missingSymbol ( self . mallocEnableSymbol. name)
251240 }
252- _ = try self . ptrace. callRemoteFunction ( at : sym)
241+ _ = try ptrace. jump ( to : sym)
253242 }
254243}
255244
0 commit comments