Files
luma/Sources/LumaCore/SystemDrainService.swift
Ole André Vadla Ravnås 4f7f06e57d Follow frida-swift's regenerated API
Take the regenerated bindings on both frontends.
2026-08-13 12:46:09 +02:00

84 lines
2.4 KiB
Swift

import Frida
/// Shared out-of-process itrace drainer. One script attached to the device's
/// system session (PID 0) drains every target's ringbuffer, keyed by session
/// id. task_for_pid capability is fixed per device, so a single denial
/// disqualifies system draining for the whole device.
@MainActor
public final class SystemDrainService {
private let device: Device
private let agentSource: String
private var session: Session?
private var script: Script?
private var capable: Bool?
public init(device: Device, agentSource: String) {
self.device = device
self.agentSource = agentSource
}
func openBuffer(sessionId: String, location: String) async -> Bool {
guard let script = await acquire() else { return false }
do {
try await script.exports.openBuffer(sessionId, location)
return true
} catch {
capable = false
return false
}
}
func drain(sessionId: String) async throws -> [UInt8]? {
try await script?.exports.drain(sessionId) as? [UInt8]
}
func lost(sessionId: String) async -> Int {
(try? await script?.exports.getLost(sessionId)) as? Int ?? 0
}
func close(sessionId: String) async throws -> [UInt8]? {
try await script?.exports.close(sessionId) as? [UInt8]
}
func shutdown() async {
if let script {
try? await script.unload()
self.script = nil
}
if let session {
try? await session.detach()
self.session = nil
}
}
private func acquire() async -> Script? {
if let script { return script }
guard capable != false else { return nil }
do {
let params = try await device.querySystemParameters()
guard (params["platform"] as? String) == "darwin",
(params["access"] as? String) == "full"
else {
capable = false
return nil
}
let sysSession = try await device.attach(pid: 0)
let sysScript = try await sysSession.createScript(
source: agentSource,
name: "itrace-drain",
runtime: .qjs
)
try await sysScript.load()
session = sysSession
script = sysScript
return sysScript
} catch {
capable = false
return nil
}
}
}