Skip to content

Commit 9604994

Browse files
committed
PR Feedback: make PTrace a non-copyable struct
1 parent 5488f2f commit 9604994

File tree

3 files changed

+28
-18
lines changed

3 files changed

+28
-18
lines changed

tools/swift-inspect/Sources/SwiftInspectLinux/PTrace.swift

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@
1313
import Foundation
1414
import LinuxSystemHeaders
1515

16-
public class PTrace {
16+
// Provides scoped access to a PTrace object.
17+
public func withPTracedProcess(pid: pid_t, _ closure: (consuming PTrace) throws -> Void) throws {
18+
let ptrace = try PTrace(pid)
19+
try closure(ptrace)
20+
}
21+
22+
public struct PTrace: ~Copyable {
1723
enum PTraceError: Error {
1824
case operationFailure(_ command: CInt, pid: pid_t, errno: CInt = get_errno())
1925
case waitFailure(pid: pid_t, errno: CInt = get_errno())
@@ -22,15 +28,10 @@ public class PTrace {
2228

2329
let pid: pid_t
2430

25-
// Provides scoped access to a PTrace object.
26-
public static func withAttachedProcess(pid: pid_t, _ closure: (PTrace) throws -> Void) throws {
27-
let ptrace = try PTrace(pid);
28-
try closure(ptrace)
29-
}
30-
3131
// Initializing a PTrace instance attaches to the target process, waits for
3232
// it to stop, and leaves it in a stopped state. The caller may resume the
3333
// process by calling cont().
34+
// NOTE: clients must use withPTracedProcess instead of direct initialization.
3435
init(_ pid: pid_t) throws {
3536
guard ptrace_attach(pid) != -1 else {
3637
throw PTraceError.operationFailure(PTRACE_ATTACH, pid: pid)
@@ -108,7 +109,8 @@ public class PTrace {
108109
// is stopped with a SIGTRAP signal. In this case, the caller is responsible
109110
// for taking action on the signal.
110111
public func jump(
111-
to address: UInt64, with args: [UInt64] = [], _ callback: (() throws -> Void)? = nil
112+
to address: UInt64, with args: [UInt64] = [],
113+
_ callback: ((borrowing PTrace) throws -> Void)? = nil
112114
) throws -> UInt64 {
113115
let origRegs = try self.getRegSet()
114116
defer { try? self.setRegSet(regSet: origRegs) }
@@ -140,7 +142,7 @@ public class PTrace {
140142
guard wStopSig(status) == SIGTRAP, let callback = callback else { break }
141143

142144
// give the caller the opportunity to handle SIGTRAP
143-
try callback()
145+
try callback(self)
144146
}
145147

146148
let sigInfo = try self.getSigInfo()

tools/swift-inspect/Sources/SwiftInspectLinux/RegisterSet.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ public typealias RegisterSet = user_pt_regs
1919
extension RegisterSet {
2020
public static var trapInstructionSize: UInt { return 4 } // brk #0x0
2121

22-
public func setupCall(_ ptrace: PTrace, to funcAddr: UInt64, with args: [UInt64], returnTo returnAddr: UInt64) throws -> RegisterSet {
22+
public func setupCall(
23+
_ ptrace: borrowing PTrace, to funcAddr: UInt64, with args: [UInt64],
24+
returnTo returnAddr: UInt64
25+
) throws -> RegisterSet {
2326
// The first 8 arguments are passed in regsters. Any additional arguments
2427
// must be pushed on the stack, which is not implemented.
2528
precondition(args.count <= 8)
@@ -53,7 +56,10 @@ public typealias RegisterSet = pt_regs
5356
extension RegisterSet {
5457
public static var trapInstructionSize: UInt { return 1 } // int3
5558

56-
public func setupCall(_ ptrace: PTrace, to funcAddr: UInt64, with args: [UInt64], returnTo returnAddr: UInt64) throws -> RegisterSet {
59+
public func setupCall(
60+
_ ptrace: borrowing PTrace, to funcAddr: UInt64, with args: [UInt64],
61+
returnTo returnAddr: UInt64
62+
) throws -> RegisterSet {
5763
// The first 6 arguments are passed in registers. Any additional arguments
5864
// must be pushed on the stack, which is not implemented.
5965
precondition(args.count <= 6)

tools/swift-inspect/Sources/swift-inspect/AndroidRemoteProcess.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
7070
var regionCount = 0
7171
var allocCount = 0
7272
do {
73-
try PTrace.withAttachedProcess(pid: self.processIdentifier) { ptrace in
73+
try withPTracedProcess(pid: self.processIdentifier) { ptrace in
7474
for entry in self.memoryMap.entries {
7575
// Limiting malloc_iterate calls to only memory regions that are known
7676
// to contain heap allocations is not strictly necessary but it does
@@ -105,7 +105,7 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
105105

106106
// Iterate a single heap region in the remote process and return an array
107107
// of (base, len) pairs describing each heap allocation in the region.
108-
internal func iterateHeapRegion(_ ptrace: PTrace, region: MemoryMap.Entry) throws -> [(
108+
internal func iterateHeapRegion(_ ptrace: borrowing PTrace, region: MemoryMap.Entry) throws -> [(
109109
base: swift_addr_t, len: UInt64
110110
)] {
111111
// Allocate a page-sized buffer in the remote process that malloc_iterate
@@ -158,7 +158,7 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
158158

159159
let regionLen = region.endAddr - region.startAddr
160160
let args = [region.startAddr, regionLen, remoteCodeAddr, remoteDataAddr]
161-
_ = try ptrace.jump(to: mallocIterateAddr, with: args) {
161+
_ = try ptrace.jump(to: mallocIterateAddr, with: args) { ptrace in
162162
// This callback is invoked when a SIGTRAP is encountered in the remote
163163
// process. In this context, this signal indicates there is no more room
164164
// in the allocated metadata region (see AndroidCLib/heap.c).
@@ -208,7 +208,9 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
208208
}
209209

210210
// call mmap in the remote process with the provided arguments
211-
internal func mmapRemote(_ ptrace: PTrace, len: Int, prot: Int32, flags: Int32) throws -> UInt64 {
211+
internal func mmapRemote(_ ptrace: borrowing PTrace, len: Int, prot: Int32, flags: Int32) throws
212+
-> UInt64
213+
{
212214
guard let sym = self.mmapSymbol.addr else {
213215
throw RemoteProcessError.missingSymbol(self.mmapSymbol.name)
214216
}
@@ -217,7 +219,7 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
217219
}
218220

219221
// call munmap in the remote process with the provdied arguments
220-
internal func munmapRemote(_ ptrace: PTrace, addr: UInt64, len: Int) throws -> UInt64 {
222+
internal func munmapRemote(_ ptrace: borrowing PTrace, addr: UInt64, len: Int) throws -> UInt64 {
221223
guard let sym = self.munmapSymbol.addr else {
222224
throw RemoteProcessError.missingSymbol(self.munmapSymbol.name)
223225
}
@@ -226,15 +228,15 @@ internal final class AndroidRemoteProcess: LinuxRemoteProcess {
226228
}
227229

228230
// call malloc_disable in the remote process
229-
internal func mallocDisableRemote(_ ptrace: PTrace) throws {
231+
internal func mallocDisableRemote(_ ptrace: borrowing PTrace) throws {
230232
guard let sym = self.mallocDisableSymbol.addr else {
231233
throw RemoteProcessError.missingSymbol(self.mallocDisableSymbol.name)
232234
}
233235
_ = try ptrace.jump(to: sym)
234236
}
235237

236238
// call malloc_enable in the remote process
237-
internal func mallocEnableRemote(_ ptrace: PTrace) throws {
239+
internal func mallocEnableRemote(_ ptrace: borrowing PTrace) throws {
238240
guard let sym = self.mallocEnableSymbol.addr else {
239241
throw RemoteProcessError.missingSymbol(self.mallocEnableSymbol.name)
240242
}

0 commit comments

Comments
 (0)