Skip to content

Commit 37dc7d5

Browse files
committed
[swift-inspect] Force forkCorpse if VMUProcInfo advises it.
Various processes, such as launchd, are unsafe to inspect directly. Inspecting them pauses them and the system does not like it when they're paused. Forking a corpse avoids this, as the original process continues running while we inspect the forked corpse. VMUProcInfo provides a shouldAnalyzeWithCorpse call which tells us whether we're inspecting one of those processes. When we are, then we force the forkCorpse option even when it's not specified. Add shims to Symbolication+Extensions.swift to allow calls to VMUProcInfo and use it to force forkCorpse when appropriate. rdar://124720793
1 parent 72615fe commit 37dc7d5

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

tools/swift-inspect/Sources/swift-inspect/DarwinRemoteProcess.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,17 @@ internal final class DarwinRemoteProcess: RemoteProcess {
125125
return nil
126126
}
127127

128-
if forkCorpse {
128+
// Consult with VMUProcInfo to determine if we should force forkCorpse.
129+
let forceForkCorpse: Bool
130+
if let procInfoClass = getVMUProcInfoClass() {
131+
let procInfo = procInfoClass.init(task: task)
132+
forceForkCorpse = procInfo.shouldAnalyzeWithCorpse
133+
} else {
134+
// Default to not forcing forkCorpse.
135+
forceForkCorpse = false
136+
}
137+
138+
if forkCorpse || forceForkCorpse {
129139
var corpse = task_t()
130140
let maxRetry = 6
131141
for retry in 0..<maxRetry {

tools/swift-inspect/Sources/swift-inspect/Symbolication+Extensions.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ private func symbol<T>(_ handle: UnsafeMutableRawPointer, _ name: String) -> T {
3030
return unsafeBitCast(result, to: T.self)
3131
}
3232

33+
private func objcClass<T>(_ name: String) -> T? {
34+
guard let result = objc_getClass(name) as? AnyClass else {
35+
return nil
36+
}
37+
return unsafeBitCast(result, to: T.self)
38+
}
39+
3340
enum Sym {
3441
static let pidFromHint: @convention(c) (AnyObject) -> pid_t =
3542
symbol(symbolicationHandle, "pidFromHint")
@@ -97,6 +104,16 @@ typealias CSSymbolicatorRef = CSTypeRef
97104
typealias CSSymbolRef = CSTypeRef
98105
typealias CSSymbolOwnerRef = CSTypeRef
99106

107+
// Declare just enough of VMUProcInfo for our purposes. It does not actually
108+
// conform to this protocol, but ObjC protocol method dispatch is based entirely
109+
// around msgSend and the presence of the method on the class, not conformance.
110+
@objc protocol VMUProcInfo {
111+
@objc(initWithTask:)
112+
init(task: task_read_t)
113+
114+
var shouldAnalyzeWithCorpse: Bool { get }
115+
}
116+
100117
func pidFromHint(_ hint: String) -> pid_t? {
101118
let result = Sym.pidFromHint(hint as NSString)
102119
return result == 0 ? nil : result
@@ -231,4 +248,8 @@ func machErrStr(_ kr: kern_return_t) -> String {
231248
return "\(errStr) (0x\(errHex))"
232249
}
233250

251+
func getVMUProcInfoClass() -> VMUProcInfo.Type? {
252+
return objcClass("VMUProcInfo")
253+
}
254+
234255
#endif

0 commit comments

Comments
 (0)