Implement remoteFetchSymbols service client and ios fetchsymbols command (#700) - #814
Open
danielpaulus wants to merge 2 commits into
Open
Implement remoteFetchSymbols service client and ios fetchsymbols command (#700)#814danielpaulus wants to merge 2 commits into
danielpaulus wants to merge 2 commits into
Conversation
Implement a RemoteXPC client for com.apple.dt.remoteFetchSymbols that downloads the dyld shared cache from iOS 17+ devices for local symbolication, mirroring pymobiledevice3's RemoteFetchSymbolsService: - ios/http: support XPC file-transfer side streams (even stream ids): register/open additional HTTP2 streams, buffer their DATA frames, surface END_STREAM as io.EOF and replenish connection/stream flow-control windows so multi-gigabyte transfers don't stall. - ios/xpc: add the FileTransferStreamResponseFlag used to open a file transfer stream and encode support for FileTransfer objects (codec symmetry, used by fixture tests). - ios/fetchsymbols: new service client (DSCFilePaths request with XPCDictionary_sideChannel UUID, per-file metadata messages, chunked raw content on stream (index+1)*2) plus caching helpers with traversal-safe cache paths and atomic temp-file writes. - CLI: `ios fetchsymbols [--path=<dir>]`, cached per iOS version+build under the base dir, skips fully downloaded files and warns that this is a multi-gigabyte download. Unit tests cover the request/response envelope encode/decode, response parsing, chunk reassembly over a fake in-memory HTTP2 server (incl. interleaved reply-channel data and window updates) and the caching logic. Real-device download validation follows up via e2e on an iOS 17+ farm device. Fixes #700 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Owner
Author
|
/test-devices |
Contributor
Contributor
|
❌ Real-device tests failed — see run. |
RemoteXPC file-transfer flow control replenished the receive window by len(d.Data()), which excludes the Pad Length byte and padding. RFC 7540 6.9.1 requires the entire DATA frame payload (including padding) to be accounted for in flow control, so padded frames leaked window on both the connection and stream and could eventually stall a large dyld shared cache download. Replenish by the frame header Length instead, and add a test that sends exactly-sized padded frames and asserts the full frame length is credited back. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Owner
Author
Adversarial review (Claude)Reviewed the full diff with focus on the shared HTTP2 layer, XPC FileTransfer codec, chunk reassembly, and path handling. One correctness defect fixed; the rest of the PR holds up well. Fixed
Verified correct (no change needed)
Considered and dismissed (out of scope / not regressions)
Test status
Not merging — leaving that to a maintainer. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Resolving symbol addresses of a remote iOS process currently requires parsing Mach-O headers over GDB RSP memory reads. Only Xcode can download the dyld shared cache ("Preparing debugger support"), so go-ios users have no way to get device libraries locally for fast symbol resolution, crash symbolication or offline analysis (#700).
Design
New RemoteXPC client for
com.apple.dt.remoteFetchSymbols, mirroring pymobiledevice3'sRemoteFetchSymbolsServiceand the file-transfer stream handling in itsRemoteXPCConnection:{"XPCDictionary_sideChannel": <uuid>, "DSCFilePaths": []}(wanting-reply flag) → the reply carries the file count.filePathplus an XPC file-transfer object whosesproperty is the expected byte length (go-ios already decodes this asxpc.FileTransfer).(i+1)*2with an empty XPC wrapper flaggedFILE_TX_STREAM_RESPONSE(0x00200000); the device streams the raw file bytes as DATA frames on that stream, terminated byEND_STREAM.<dir>/<ProductVersion>_<BuildVersion>/<on-device path>so the multi-GB download is cached per iOS version/build and reused across devices.This is RemoteXPC only — no dtx/nskeyedarchiver code is touched.
Implementation
ios/http: file-transfer side streams for the existingHttpConnection—NewFileStreamReadWriterregisters an extra stream id, DATA frames for it are buffered (interleaved stream 1/3 frames keep working),END_STREAMsurfaces asio.EOF, and received bytes are granted back to the connection + stream flow-control windows (batched at 256 KiB, force-flushed at stream end) so multi-gigabyte transfers don't stall on the 1 MiB initial window.ios/xpc: newFileTransferStreamResponseFlagconst;FileTransferencode support (inverse of the existing decoder) for codec symmetry and fixture tests.ios/fetchsymbols:New/ListFiles/DownloadFile/DownloadToCacheclient plus caching helpers: traversal-safeCachePath(device-controlled paths cannot escape the cache dir),IsCached(size match), atomic temp-file + rename writes so interrupted downloads never look cached, and a progress callback.ios fetchsymbols [--path=<dir>](default./ios-symbols), gated on a running tunnel, prints an explicit multi-gigabyte-download warning with file count/total size before transferring, logs progress every 512 MiB, skips already-cached files, JSON summary output. Registered in the command registry,needsAutomaticTunnelInfo, help catalog and usage doc.Options considered
ios/fileservice's raw data connection — rejected: remoteFetchSymbols does not use thecom.apple.coredevice.fileservice.datawire protocol; its content arrives on extra HTTP2 streams of the same XPC connection.xpc.Connectiona built-in file-transfer API — rejected for now:xpcstays transport-agnostic; the side-stream mechanics live inios/http(which owns the HTTP2 framing) and the service package composes them. Smallest surface change to shared code.HttpConnectionis intentionally single-threaded like all other go-ios XPC services; files download sequentially. Simpler, and throughput is tunnel-bound anyway. (Preferred: option 2/3 as implemented.)Test plan
go build ./...andgo test ./...pass;gofmt -lclean on changed files.ios/fetchsymbols: DSCFilePaths request envelope encode/decode roundtrip (side-channel UUID included), file-count and per-file metadata fixture decode + parsing (incl. thefileTransferexpected length), chunk reassembly (copyFileChunks) incl. short-stream and error propagation, cache-path traversal safety, cached-size checks, atomic write semantics, progress reporting.ios/http: fake in-memory HTTP2 server test that streams a 360 KiB payload in 16 KB DATA frames on a file stream — verifies reassembly, EOF onEND_STREAM, buffering of interleaved reply-channel data, full flow-control window replenishment, and rejection of unknown/duplicate/reserved stream ids.Fixes #700
🤖 Generated with Claude Code
https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk