Files
rea/docs/apple-ips.md
T
rodricksz4h5 0a2b7af905 fix(apple): keep the documented terminating process, parent pid and metadata members of IPS reports (#7079)
Apple's crash report JSON documents termination.byPid, byProc and flags, the body's parentPid, and
the metadata line's build_version and platform. The parser shapes did not list them, so they were
reported only by name in unlisted_keys / unlisted_body_keys and their values were dropped: a
watchdog kill no longer said which process ended it, and process kept parentProc without its pid.
#4297 asks for termination members beyond namespace/code/indicator to be retained as recorded, and
docs/apple-ips.md says documented fields are reproduced.

They are now kept: termination.by_proc, termination.by_pid and termination.flags, process.parent_pid
and metadata.build_version / metadata.platform. The integers are recorded integers, so they count
toward max_integer_text_bytes and a type mismatch is recorded like the other fields.
2026-10-25 13:56:51 +08:00

6.9 KiB

Apple IPS crash reports

inspect_apple_ips / inspect-apple-ips answers whether one selected local Apple .ips file is a crash report (bug_type string "309"), which process, exception, and termination facts that report records, which threads and usedImages rows it lists, and which documented crash classes its strings match. It reads the file without executing a target and does not require Xcode, atos, a disassembler, or pwntools.

rea inspect-apple-ips /absolute/path/to/report.ips --json

The CLI resolves relative paths against the caller's working directory. MCP requires an absolute filesystem path and preserves that exact selection:

{
  "name": "inspect_apple_ips",
  "arguments": { "path": "/artifacts/report.ips" }
}

Observations

The inline Evidence result contains the artifact path, SHA-256, and byte length. metadata is the first-line JSON object. bug_type stays a string. The crash body is parsed only when that string is "309". Other types, including "288" stackshots, return no crash result.

process, exception, termination, faulting_thread, threads, and images reproduce documented body fields when present, including each image's name and each frame's symbolLocation (as symbol_location, the byte offset from the start of recorded_symbol). termination keeps the terminating process as by_proc and by_pid and its flags; process.parent_pid keeps parentPid next to parent; and metadata keeps build_version and platform. Integers keep their decimal literals and a hexadecimal form, including arm64e registers above 2^53. Frame roles follow the recorded frame index: row zero of the resolved faulting thread is faulting_instruction, row zero of other threads is current_instruction, and later rows are return_address. Each runtime address uses that row's own image base and offset. The recorded inline flag does not supply a missing offset or authorize borrowing another row's address. When faultingThread is missing or does not resolve to a recorded thread object, row-zero roles are unknown; the recorded lookup remains available. A translated process records Rosetta's registers in a nested threadState.rosetta object; each one is reported as rosetta.<name> and counts toward the register budget. A