Highlights
✨ core-profile-session stackshot prints symbolicated call stacks
The command used to dump the whole stackshot as JSON. It now prints the call stack of every thread of every process, with the thread's name, dispatch queue, state, QoS, priority and CPU times:
pymobiledevice3 developer dvt core-profile-session stackshot --process SpringBoard
# SpringBoard [42] size 100.4 MB max rss 320.3 MB 9 threads
# Thread 514 com.apple.main-thread waiting user-interactive pri 47 cpu 4.441s user, 0.783s sys
# 0 libsystem_kernel.dylib mach_msg2_trap + 8
# 1 libsystem_kernel.dylib mach_msg_overwrite + 424
# 2 libsystem_kernel.dylib mach_msg + 24
# 3 CoreFoundation __CFRunLoopServiceMachPort + 136
# ...- Frames are symbolicated against the Xcode device support of the device, in pure Python. When it is missing, a warning points at
developer fetch-symbols downloadand frames are printed as image + offset.--symbols DIRuses another symbols tree. --jsonprints the raw stackshot as before, and--outstill writes it to a file. Scripts that parsed the default output need to add--json.--process PID/NAMElimits the output to one process.- Swift and C++ names are printed mangled, and main executables as
uuid + offset.
✨ Kernel frames in stackshot
Given the kernelcache of the firmware the device runs, kernel frames get the name of their kernel image. With the kernel signatures of blacktop/symbolicator they are symbolicated too, and the kernel function a blocked thread resumes in is printed as its continuation. Both need ipsw installed.
pymobiledevice3 developer dvt core-profile-session stackshot \
--kernelcache kernelcache.release.iphone17 --kernel-signatures symbolicator/kernel
# 0 com.apple.kernel thread_invoke + 1232 (kernel)
# 4 com.apple.kernel sbwait + 236 (kernel)
# 5 com.apple.kernel soreceive + 2060 (kernel)The signatures name part of the kernel only; a frame in a function they do not match stays as image + offset.
✨ fetch-symbols download keeps what it already downloaded
It downloaded several GB and split the shared cache again on every run. A finalized DeviceSupport directory is now left alone, and with an explicit output directory the files already having the size the device reports are kept. --force downloads everything again.
pymobiledevice3 developer fetch-symbols download
# INFO Symbols were already downloaded into: ~/Library/Developer/Xcode/iOS DeviceSupport/... (use --force to download them again)With ipsw_parser 1.8.2 it also handles a device reporting its shared cache under /System/Cryptexes/OS, and a shared cache Xcode's extractor refuses.
✨ dvt oslog prints messages the way the device does
- Numbers follow their printf conversion: a
-1for%dno longer prints as18446744073709551615, nor a%fas its raw bits. %{bool}d,%{BOOL}dand%{errno}d, nil objects, padded strings, uuid and data arguments, a literal%%, and the Network, mDNS and CoreLocation value types are printed likeos_logdoes.- Rows are stamped with the device's time instead of the time the host printed them.
--format jsonrecords gainformat_stringandarguments, a list of{type, value}per argument.- The parser is about 18 times faster (about 1,100 to 20,000 rows/s on a replayed capture), so it no longer falls behind a busy device.
🐛 Bug fixes
dvt oslogexited with "unpack requires a buffer of 4 bytes" on a thread id of0x1000000or above, and most lines carried a stray NUL.os_traceread the mach timestamp of an entry two bytes early.- Passing a timeout to the notification proxy raised
AssertionErrorbefore anything was sent. - Finishing a sysdiagnose archive got a fresh full
--timeoutinstead of what was left of it.
What's Changed
- be5e7ba dvt: Symbolicate kernel frames in core-profile-session stackshot (#2023) (@doronz88)
- a5ed174 deps: Require ipsw_parser 1.8.2 (#2022) (@doronz88)
- a64f2ea dvt: Print symbolicated call stacks in core-profile-session stackshot (#2022) (@doronz88)
- 812e971 fetch_symbols: Keep already downloaded symbols unless given --force (#2022) (@doronz88)
- 385fead os_trace: Read the mach timestamp from its own bytes (#2021) (@doronz88)
- 7f2721b dvt: Add the format string and its arguments to oslog's JSON (#2020) (@doronz88)
- 64b546e activity_trace_tap: Print the Network, mDNS and location value types (#2020) (@doronz88)
- 6b989be activity_trace_tap: Print bool and errno arguments like os_log (#2020) (@doronz88)
- 37a9a3c activity_trace_tap: Put uuid and data arguments back together (#2020) (@doronz88)
- 952a922 activity_trace_tap: Print nil objects and padded strings like os_log (#2020) (@doronz88)
- 0653de5 activity_trace_tap: End a message at its last visible character (#2020) (@doronz88)
- ad9f5f1 activity_trace_tap: Print a literal "%%" once (#2020) (@doronz88)
- f569689 activity_trace_tap: Build the row class once per table (#2019) (@doronz88)
- 6cdcb61 activity_trace_tap: Stamp rows with the device's time (#2018) (@Cassian433)
- d5fc1f8 activity_trace_tap: Print message numbers per their printf conversion (#2017) (@Cassian433)
- 1d19afd activity_trace_tap: Drop the padding NULs from message text (#2017) (@Cassian433)
- ef7ea1e activity_trace_tap: Decode thread ids of any width (#2017) (@Cassian433)
- 5ce586a crash_reports: Count the sysdiagnose wait against the whole --timeout (#2016) (@Cassian433)
- 1f35373 notification_proxy: Apply the timeout to each receive (#2016) (@Cassian433)
Full Changelog: v11.27.2...v11.28.0