@@ -49,8 +49,6 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
49
49
}
50
50
}
51
51
52
- let ptrace : SwiftInspectLinux . PTrace
53
-
54
52
// We call mmap/munmap in the remote process to alloc/free memory for our own
55
53
// use without impacting existing allocations in the remote process.
56
54
lazy var mmapSymbol : RemoteSymbol = RemoteSymbol ( " mmap " , self . symbolCache)
@@ -63,16 +61,6 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
63
61
lazy var mallocEnableSymbol : RemoteSymbol = RemoteSymbol ( " malloc_enable " , self . symbolCache)
64
62
lazy var mallocIterateSymbol : RemoteSymbol = RemoteSymbol ( " malloc_iterate " , self . symbolCache)
65
63
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
-
76
64
// Linux and Android have no supported method to enumerate allocations in the
77
65
// heap of a remote process. Android does, however, support the malloc_iterate
78
66
// API, which enumerates allocations in the current process. We leverage this
@@ -81,26 +69,27 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
81
69
override internal func iterateHeap( _ body: ( swift_addr_t , UInt64 ) -> Void ) {
82
70
var regionCount = 0
83
71
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
+ }
98
89
}
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
104
93
}
105
94
106
95
if regionCount == 0 {
@@ -116,16 +105,16 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
116
105
117
106
// Iterate a single heap region in the remote process and return an array
118
107
// 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 -> [ (
120
109
base: swift_addr_t , len: UInt64
121
110
) ] {
122
111
// Allocate a page-sized buffer in the remote process that malloc_iterate
123
112
// will populaate with metadata describing each heap entry it enumerates.
124
113
let dataLen = sysconf ( Int32 ( _SC_PAGESIZE) )
125
114
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)
127
116
defer {
128
- _ = try ? self . munmapRemote ( addr: remoteDataAddr, len: dataLen)
117
+ _ = try ? self . munmapRemote ( ptrace , addr: remoteDataAddr, len: dataLen)
129
118
}
130
119
131
120
// Allocate and inialize a local buffer that will be used to copy metadata
@@ -142,9 +131,9 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
142
131
// executed in the remote process.
143
132
let codeLen = heap_iterate_callback_len ( )
144
133
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)
146
135
defer {
147
- _ = try ? self . munmapRemote ( addr: remoteCodeAddr, len: codeLen)
136
+ _ = try ? self . munmapRemote ( ptrace , addr: remoteCodeAddr, len: codeLen)
148
137
}
149
138
150
139
// Copy the malloc_iterate callback implementation to the remote process.
@@ -158,9 +147,9 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
158
147
159
148
// Disable malloc/free while enumerating the region to get a consistent
160
149
// snapshot of existing allocations.
161
- try self . mallocDisableRemote ( )
150
+ try self . mallocDisableRemote ( ptrace )
162
151
defer {
163
- _ = try ? self . mallocEnableRemote ( )
152
+ _ = try ? self . mallocEnableRemote ( ptrace )
164
153
}
165
154
166
155
// Collects (base, len) pairs describing each heap allocation in the remote
@@ -169,7 +158,7 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
169
158
170
159
let regionLen = region. endAddr - region. startAddr
171
160
let args = [ region. startAddr, regionLen, remoteCodeAddr, remoteDataAddr]
172
- _ = try self . ptrace. callRemoteFunction ( at : mallocIterateAddr, with: args) {
161
+ _ = try ptrace. jump ( to : mallocIterateAddr, with: args) {
173
162
// This callback is invoked when a SIGTRAP is encountered in the remote
174
163
// process. In this context, this signal indicates there is no more room
175
164
// in the allocated metadata region (see AndroidCLib/heap.c).
@@ -183,11 +172,11 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
183
172
}
184
173
try self . process. writeMem ( remoteAddr: remoteDataAddr, localAddr: buffer, len: UInt ( dataLen) )
185
174
186
- var regs = try self . ptrace. getRegSet ( )
175
+ var regs = try ptrace. getRegSet ( )
187
176
regs. step ( RegisterSet . trapInstructionSize)
188
177
189
- try self . ptrace. setRegSet ( regSet: regs)
190
- try self . ptrace. cont ( )
178
+ try ptrace. setRegSet ( regSet: regs)
179
+ try ptrace. cont ( )
191
180
}
192
181
193
182
try self . process. readMem ( remoteAddr: remoteDataAddr, localAddr: buffer, len: UInt ( dataLen) )
@@ -219,37 +208,37 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
219
208
}
220
209
221
210
// 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 {
223
212
guard let sym = self . mmapSymbol. addr else {
224
213
throw RemoteProcessError . missingSymbol ( self . mmapSymbol. name)
225
214
}
226
215
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)
228
217
}
229
218
230
219
// 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 {
232
221
guard let sym = self . munmapSymbol. addr else {
233
222
throw RemoteProcessError . missingSymbol ( self . munmapSymbol. name)
234
223
}
235
224
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)
237
226
}
238
227
239
228
// call malloc_disable in the remote process
240
- internal func mallocDisableRemote( ) throws {
229
+ internal func mallocDisableRemote( _ ptrace : PTrace ) throws {
241
230
guard let sym = self . mallocDisableSymbol. addr else {
242
231
throw RemoteProcessError . missingSymbol ( self . mallocDisableSymbol. name)
243
232
}
244
- _ = try self . ptrace. callRemoteFunction ( at : sym)
233
+ _ = try ptrace. jump ( to : sym)
245
234
}
246
235
247
236
// call malloc_enable in the remote process
248
- internal func mallocEnableRemote( ) throws {
237
+ internal func mallocEnableRemote( _ ptrace : PTrace ) throws {
249
238
guard let sym = self . mallocEnableSymbol. addr else {
250
239
throw RemoteProcessError . missingSymbol ( self . mallocEnableSymbol. name)
251
240
}
252
- _ = try self . ptrace. callRemoteFunction ( at : sym)
241
+ _ = try ptrace. jump ( to : sym)
253
242
}
254
243
}
255
244
0 commit comments