12
12
13
13
#if os(Android)
14
14
15
- import Foundation
16
15
import AndroidCLib
16
+ import Foundation
17
17
import LinuxSystemHeaders
18
18
import SwiftInspectLinux
19
19
import SwiftRemoteMirror
@@ -49,20 +49,24 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
49
49
super. init ( processId: processId)
50
50
}
51
51
52
+ // Linux and Android have no supported method to enumerate allocations in the
53
+ // heap of a remote process. Android does, however, support the malloc_iterate
54
+ // API, which enumerates allocations in the current process. We leverage this
55
+ // API by invoking it in the remote process with ptrace and using simple IPC
56
+ // (SIGTRAP and process_vm_readv and process_vm_writev) to fetch the results.
52
57
override internal func iterateHeap( _ body: ( swift_addr_t , UInt64 ) -> Void ) {
53
58
var regionCount = 0
54
59
var allocCount = 0
55
60
for entry in self . memoryMap. entries {
56
61
// Limiting malloc_iterate calls to only memory regions that are known
57
62
// to contain heap allocations is not strictly necessary but it does
58
- // significantly improves the speed of heap iteration.
63
+ // significantly improve the speed of heap iteration.
59
64
guard entry. isHeapRegion ( ) else { continue }
60
65
61
66
// collect all of the allocations in this heap region
62
67
let allocations : [ ( base: swift_addr_t , len: UInt64 ) ]
63
68
do {
64
- allocations = try self . iterateHeapRegion (
65
- startAddr: entry. startAddr, endAddr: entry. endAddr)
69
+ allocations = try self . iterateHeapRegion ( region: entry)
66
70
regionCount += 1
67
71
} catch {
68
72
print ( " failed iterating remote heap: \( error) " )
@@ -75,7 +79,7 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
75
79
for alloc in allocations { body ( alloc. base, alloc. len) }
76
80
}
77
81
78
- if allocCount == 0 {
82
+ if regionCount == 0 {
79
83
// This condition most likely indicates the MemoryMap.Entry.isHeapRegion
80
84
// filtering is needs to be modified to support a new heap region naming
81
85
// convention in a newer Android version.
@@ -86,12 +90,7 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
86
90
}
87
91
}
88
92
89
- // Linux and Android have no supported method to enumerate allocations in the
90
- // heap of a remote process. Android does, however, support the malloc_iterate
91
- // API, which enumerates allocations in the current process. We leverage this
92
- // API by invoking it in the remote process using ptrace and using simple IPC
93
- // (SIGTRAP and process_vm_readv and process_vm_writev).
94
- internal func iterateHeapRegion( startAddr: UInt64 , endAddr: UInt64 ) throws -> [ (
93
+ internal func iterateHeapRegion( region: MemoryMap . Entry ) throws -> [ (
95
94
base: swift_addr_t , len: UInt64
96
95
) ] {
97
96
// We call mmap/munmap in the remote process to alloc/free memory for our
@@ -119,7 +118,9 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
119
118
// Allocate a page-sized buffer in the remote process that malloc_iterate
120
119
// will populaate with metadata describing each heap entry it enumerates.
121
120
let dataLen = sysconf ( Int32 ( _SC_PAGESIZE) )
122
- var mmapArgs = [ 0 , UInt64 ( dataLen) , UInt64 ( PROT_READ | PROT_WRITE) , UInt64 ( MAP_ANON | MAP_PRIVATE) ]
121
+ var mmapArgs = [
122
+ 0 , UInt64 ( dataLen) , UInt64 ( PROT_READ | PROT_WRITE) , UInt64 ( MAP_ANON | MAP_PRIVATE) ,
123
+ ]
123
124
let remoteDataAddr : UInt64 = try self . ptrace. callRemoteFunction ( at: mmapAddr, with: mmapArgs)
124
125
defer {
125
126
let munmapArgs : [ UInt64 ] = [ remoteDataAddr, UInt64 ( dataLen) ]
@@ -128,7 +129,8 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
128
129
129
130
// Allocate and inialize a local buffer that will be used to copy metadata
130
131
// to/from the target process.
131
- let buffer = UnsafeMutableRawPointer . allocate ( byteCount: dataLen, alignment: MemoryLayout< UInt64> . alignment)
132
+ let buffer = UnsafeMutableRawPointer . allocate (
133
+ byteCount: dataLen, alignment: MemoryLayout< UInt64> . alignment)
132
134
defer { buffer. deallocate ( ) }
133
135
guard heap_iterate_metadata_init ( buffer, dataLen) else {
134
136
throw RemoteProcessError . heapIterationFailed
@@ -160,8 +162,8 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
160
162
}
161
163
162
164
var allocations : [ ( base: swift_addr_t , len: UInt64 ) ] = [ ]
163
- let regionLen = endAddr - startAddr
164
- let args = [ startAddr, regionLen, remoteCodeAddr, remoteDataAddr]
165
+ let regionLen = region . endAddr - region . startAddr
166
+ let args = [ region . startAddr, regionLen, remoteCodeAddr, remoteDataAddr]
165
167
_ = try self . ptrace. callRemoteFunction ( at: mallocIterateAddr, with: args) {
166
168
// This callback is invoked when a SIGTRAP is encountered in the remote
167
169
// process. In this context, this signal indicates there is no more room
@@ -180,6 +182,7 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
180
182
regs. step ( RegisterSet . trapInstructionSize)
181
183
182
184
try self . ptrace. setRegSet ( regSet: regs)
185
+ try self . ptrace. cont ( )
183
186
}
184
187
185
188
try self . process. readMem ( remoteAddr: remoteDataAddr, localAddr: buffer, len: UInt ( dataLen) )
0 commit comments