Lab Technical Report LAB-TR-0011

Log Compression and Archive Structure in the iOS 27.0 Sysdiagnose: An Early Observation Tested Against Ten Archives

Daniel Addai

SectraTEK Lab, Prudential Associates

Lab Technical Report, preprint, not peer reviewed

Abstract

A sysdiagnose parser that fits one iOS release can return less on the next without an error, and a list of release differences drawn from one archive per release cannot separate the release from the device. We compare one iOS 27.0 sysdiagnose with nine iOS 26 sysdiagnoses from two other iPhones and re-test the thirteen claims of an initial comparison of one archive per release: a claim survives only if no iOS 26 archive contradicts it. Four differences survive; with one iOS 27.0 capture they remain hypotheses about the release. In the iOS 27.0 archive 94.5 percent of log chunksets use LZBITMAP compression, against none in the iOS 26 archives, and a decoder without the codec recovered 4.6 percent of the records yet reported completion with warnings. A container-manager state file, a launch-services list and four small stores occur only in the iOS 27.0 archive, and its BatteryUI time buckets are stored 86,400 s wide instead of 3,600 s. Six claims fail because an iOS 26 device shows the same property, so comparing one archive per release overstated what is new. Decoder maintainers documented the codec change first; we confirm it on a complete archive and measure its cost.

CCS Concepts • Applied computing → System forensics.

Keywords iOS 27, sysdiagnose, unified logging, tracev3, LZBITMAP, version drift, mobile forensics, tool validation, negative result

ACM Reference FormatDaniel Addai. 2026. Log Compression and Archive Structure in the iOS 27.0 Sysdiagnose: An Early Observation Tested Against Ten Archives. Lab Technical Report LAB-TR-0011, version 1.2. SectraTEK Lab, Prudential Associates. Preprint, not peer reviewed. https://lab.sectratek.com/research/reports/lab-tr-0011/ DOI: https://doi.org/10.5281/zenodo.23717934

1 Introduction

A sysdiagnose is a diagnostic bundle that an iPhone assembles on request. It carries the unified log archive, power and battery logs, crash and resource reports, process listings, configuration state and many small subsystem summaries, and it needs neither a jailbreak nor a full file system extraction. Examiners and incident responders therefore value it, and open-source tools read it [9], [8]. Its content is not a standard. It is a by-product of an operating system that changes every year, and a parser that is right for one release can return less, without an error, on the next.

A motivating failure. On the iOS 27.0 archive studied here, version 0.6.0 of an open-source unified-log decoder [15] finished with the status “completed with warnings” and returned 1,944,016 records. Version 0.7.0, which adds the LZBITMAP codec, returned 42,588,594 records from the same 2,688 log files. The archive and its chunk framing were intact. The older decoder had a gap in its codec list and produced a plausible, partial result; only a count showed the loss (Section 4.1).

The codec change itself is not our discovery. During the iOS 27 beta cycle, a contributor to the decoder reported that iOS 27 log archives were only partly decoded, traced the cause to a new chunkset compression signature and identified the codec as LZBITMAP [13]; a decoder was added [14] and a release added initial iOS 27 support [16]. What was missing, in the public material we found, was a measurement on a complete archive of what an unaware decoder loses, and an inventory of what else changes in the archive.

The problem: claims from one archive per release. Such an inventory is easy to overstate. Our initial comparison set one iOS 26.6 archive against one iOS 27.0 archive and listed thirteen differences. One was that the Special log stream grew from 133 to 782 files, which we read as a change in how the logging daemon rotates data. A device on iOS 26.6.2 holds 1,001 Special files in each of six captures. When we widened the comparison to ten archives from three devices, six of the thirteen claims failed in this way. Version drift is real, but a pair of archives cannot separate it from the device.

Approach. We re-test every claim of the initial comparison against ten archives with a fixed rule, measure the decoder failure on the complete archive, and describe the readers, written from the observed file layouts, that made the file-level comparison possible; their unit checks and wording limits are part of the evidence. We ask four research questions.

  • RQ1 (Persistence). Which differences between the iOS 27.0 archive and the iOS 26 archives hold across the devices we hold, and which are explained by device or capture?
  • RQ2 (Failure mode). How does a decoder that lacks the new codec fail, and what does an examiner see?
  • RQ3 (Reading). For files that are new or newly read on iOS 27, which units and meanings can be proved from the data, and how should a record be worded so that it is not over-read?
  • RQ4 (Method). How many claims of a comparison of one archive per release survive a wider comparison, and which kinds of claim fail?

Contributions. This report makes four contributions.

  • Four iOS 27.0 differences that survive a re-test against nine iOS 26 archives from two devices: LZBITMAP log compression, a container-manager state file, a launch-services list with four small stores, and day-wide BatteryUI buckets (Sections 4.1 to 4.3).
  • A replication with a measurement of the public LZBITMAP report: the cost of the codec change to an unaware decoder on a complete archive, and the signal that exposes it (Section 4.1). This is a confirmation, not a discovery.
  • A methodological finding: six of thirteen claims of a two-archive comparison fail against ten archives, all of them file counts or member presence; with a conservative re-test rule and a recommendation for release comparisons (Sections 3.5, 4.4 and 5.1).
  • Sixteen readers, written from the observed file layouts, for sysdiagnose files in three families, whose unit checks prove the stored units and whose wording rules keep their output from being over-read (Sections 3.4, 4.3 and 4.5).

Scope. The sample is ten complete sysdiagnose archives from three iPhones: three captures of one device on iOS 26.6, six captures of a second device on iOS 26.6.2, and one capture of a third device on iOS 27.0. The iOS 27.0 evidence is therefore a single capture, and no device was captured before and after an update. Every statement about iOS 27 in this report is a hypothesis about the release that rests on that capture; a difference that “survives” is one that no iOS 26 archive contradicts, not one shown to hold for every iOS 27 device. Section 6 states the remaining limits.

Section 2 reviews the format and related work, Section 3 the study design, Section 4 the results, Section 5 what they mean for examiners and for release comparisons, and Section 6 the threats to validity.

2 Background and Related Work

This section describes the log format at issue and places the work among public reports of the iOS 27 change, sysdiagnose tools and artifact studies, and work on testing forensic tools.

2.1 The unified log in a sysdiagnose

The log archive inside a sysdiagnose is a directory of tracev3 files in several streams (Persist, Special, Signpost and, on some systems, HighVolume), string tables (uuidtext and shared-cache files) and time-synchronisation files. A tracev3 file is a sequence of chunks, each introduced by a 16-byte header holding a tag, a subtag and a data size. The chunk types we met are a header chunk (tag 0x1000), catalog chunks (0x600b) and chunksets (0x600d). A chunkset carries a block of compressed log entries whose first four bytes identify the codec; we call these bytes its signature. Through iOS 26 the signature reads bv41, the LZ4 frame signature.

2.2 Public reports of the iOS 27 codec change

The decoder maintainers' tracker records the iOS 27 behaviour in detail. The issue reports the error text for the unexpected signature, identifies ZBM followed by 0x0c as LZBITMAP, observes that memory-held logs still use LZ4 while data written to disk uses the new codec, and notes that the persona fields moved some byte offsets [13]. The decoder pull request [14] and the v0.7.0 release [16] followed. Apple documents an LZBITMAP codec constant in its Compression framework [5]. An independent macOS analyst, citing Apple's release notes, reports that logarchives written by version 27 systems, including those in device sysdiagnoses, can be opened only on macOS 26.2 or later [11].

2.3 Sysdiagnose tools and artifact studies

The Sysdiagnose Analysis Framework (SAF) converts archives into structured records and was presented as a collection and analysis pipeline in 2025 [9], [8]. iLEAPP and ALEAPP are Python parser suites [7]. Before this work, none of these tools parsed the files that the readers of Section 3.4 read. MVT is a widely used toolkit for mobile compromise checks [17]. Single-artifact research exists, the shutdown log being the best-known example [18]. We found no peer-reviewed study that compares sysdiagnose or log archive structure across iOS releases; our search used web search only and did not query the academic indexes, so this states what we could find and not what exists.

2.4 Testing forensic tools and claims

The case for testing forensic tools and their assumptions rather than trusting them is made in the tool-reliability literature [12] and in the field's research agenda [10]. Both apply to claims as much as to code: a list of differences between two archives is the output of a procedure and needs a check of its own.

Position of this work. For the codec, this work is a replication with a measurement of a maintainer report [13]. Beyond the codec, it adds what we did not find in the public material: a comparison of sysdiagnose structure across releases that uses two devices on the earlier release and re-tests its own earlier claims. It is also a small, documented instance of the tool-validation practice of [12] applied to our own earlier claims. The readers are engineering that makes the file-level measurements repeatable; they are a research result only in their unit checks.

3 Study Design

Every archive is read once, as a stream, and three analyses run over that stream; recorded decoder runs cover two archives. All results meet in a re-test of the claims of the initial comparison (Figure 1).

Method: from archive to claimEach of the ten archives is streamed once from its compressed tar file and never written to disk. Three analyses run over the stream: an inventory of members and log streams, a walk of the log chunk framing that tallies compression signatures, and file readers for 16 artifacts. Recorded decoder runs with two decoder versions cover two archives, one iOS 26.6 and the iOS 27.0 archive. All results feed a re-test of the 13 claims of the initial two-archive comparison against all ten archives.Ten archivescompressed tar filesStreamed passread once, never writtenInventorymembers, streamsChunk walktags, signaturesFile readers16 artifactsDecoder runstwo archives, two versionsRe-test13 claims, ten archives
Figure 1: Study design. Each archive is streamed from the compressed tar and never written to disk. The inventory, the chunk walk and the file readers are independent of each other; the decoder runs (dashed) were recorded for the initial comparison and cover two archives (Table 3).

3.1 Evidence

The evidence is ten complete, device-generated sysdiagnose archives of three iPhones, labelled D1 to D3 by device (Table 1). Captures were assigned to devices by comparing hashed boot-session and device identifiers: the captures of one device share all of them, and no identifier is shared between devices. The two archives of the initial comparison are one D1 capture and the D3 capture. Captures of the same device are not independent observations: they test capture-to-capture variation, not variation between devices. One further iOS 26.6.2 archive was excluded because its tar stream ends early (812 members read before the error), and a duplicate copy of one D1 archive, byte-identical in size, was counted once. The full file system extractions we inspected hold only partial, in-progress sysdiagnose directories left by the device; they are not usable archives and are not used here.

Table 1: Evidence: ten complete sysdiagnose archives of three research devices (iPhones; device classes only).
DeviceiOS (build)CapturesOrigin
D126.6 (23G71)3Research device of an earlier hardware generation; three captures generated over about 23 hours (shared boot-session and device identifiers in all three)
D226.6.2 (23G90)6Research device; repeat captures of one device (identical volume, boot-session and device identifiers in all six), generated within about two hours
D327.0 (24A437)1Research device of a newer hardware generation, collected with a guided workflow
Total10Excluded: one truncated iOS 26.6.2 archive

All archives come from devices in the Lab's research collection and were used read-only with the owners' permission. All ten report the same sysdiagnose version (3.0), the mode Customer and the same changed properties in their own log, so differences between them are not differences of collection mode; all were produced by the on-device service and delivered as files.

3.2 Inventory and chunk-signature census

For each archive we stream the member list (name, size) and, for every tracev3 member, read the file in memory and walk its chunk framing (Listing 1). At each position the walk reads the tag, the subtag and the 64-bit size, counts the chunk by tag, tallies the signature of every chunkset, and advances by the header plus the size rounded up to eight bytes. The walk must end exactly at the end of the file; a file that does not is counted as a framing error.

Listing 1: The chunk walk applied to every tracev3 file (Python, standard library).

pos = 0
while pos + 16 <= len(data):
    tag, subtag, size = unpack("<IIQ", data[pos:pos+16])
    count[tag] += 1
    if tag == 0x600d:                    # chunkset
        signature[data[pos+16:pos+20]] += 1
    pos = (pos + 16 + size + 7) & ~7    # 8-byte alignment

Members whose names begin with a dot and underscore are AppleDouble companion files that carry extended attributes; they are counted separately and excluded from the evidential member count. The same code runs on every archive. It was written separately from the verification script of the initial comparison, and it reproduces that analysis's member, file and signature counts for the two archives they share (Section 4.4), which is the only check we have on its correctness.

3.3 Decoder runs

For one D1 archive and the D3 archive, the log archive was decoded with the open-source unifiedlog_iterator of the Mandiant library, version 0.6.0 and version 0.7.0 [15], [16]. The decoded records were normalised into one read-only relational store per archive, and aggregate queries over the stores gave the log-level counts of Section 4.6. These runs and stores were made for the initial comparison and were not repeated for this report; their inputs and a verification script that re-derives every printed figure from stored aggregates are retained, and its 56 checks pass. We treat the log-level counts as a lower-confidence layer than the file-level counts, which we reproduced in this study.

3.4 Readers for new structured files

Sixteen artifacts read files that earlier tools did not parse (Section 4.5). They fall into three families (3, 3 and 10 artifacts), each built and tested as one unit: the ContainerManager state file of iOS 27 [1]; the BatteryUI per-app runtime property lists [2]; and five text and property-list sources [3], namely the associated-domains database printed by swcutil (the mechanism by which an app and a website declare each other [6]), the managed-configuration event lists, the Network Extension configuration archive, the iCloud Drive state printed by brctl, and the process list printed by taskinfo. A parser for the container state file was also written for SAF [4] (an open pull request). All readers follow six rules.

  1. Observed layout. Each reader was written from the printed or serialised layout of the file as observed. The pull request for the ten readers of the third family states that they were written from the file formats and not copied from other tools [3]; the pull requests of the other six readers make no such statement, and we did not audit any reader against the source of other tools. Values are reported as stored, with a stated unit only where the unit was proved.
  2. Never raise. A reader returns an empty value on input it cannot read, rejects out-of-range times instead of inventing a date, and keeps unknown keys, so one damaged value costs one cell.
  3. Units are tested, not assumed. For the BatteryUI runtimes we tested whether any value in a bucket exceeds the bucket width, whether bucket totals equal the sum of the app values, and whether values equal a round cap (Section 4.3).
  4. Wording limits. A row is a lead and not proof: a container birth time is not an install time; a container with no directory cannot be called removed; an app absent from a list is not evidence that it did not run; an empty result does not prove absence.
  5. Independent recount. Row counts were compared with counts from separate code that reads the raw file with no reader code (service blocks, process: lines, event dictionaries, an archive walker for the Network Extension rules).
  6. Synthetic fixtures. Unit tests use generated files with invented identifiers and reserved example domains. For two families a sanitised copy of the real structure was added after review, with every identifying value replaced and all times shifted by one constant offset.

For this report we re-ran the released readers, unchanged, on one archive of each device (Section 4.5). This is both a regression check and the first test of the readers on a third device.

3.5 Re-test rule

The initial comparison produced claims of the form “X is new, removed or changed in iOS 27”. A claim is supported if the property holds in the iOS 27.0 archive and in none of the nine iOS 26 archives (or, for a quantity, if the iOS 27.0 value lies outside the whole iOS 26 range); not supported if some iOS 26 archive shows the iOS 27 value; and unresolved if the data are consistent but one device cannot separate the release from the device. We apply the rule mechanically. It is deliberately conservative: with one iOS 27 archive, a supported claim means only that no contradiction was found.

3.6 Consistency checks

The reference for every count is what the archive stores, and four checks test agreement with it. First, the census code reproduces the initial comparison's counts for the two archives they share. Second, the verification script of the initial comparison re-derives every printed log figure from stored inputs (56 checks pass). Third, the released readers reproduced, on the D1 and D2 archives, the row counts recorded when they were released; on the D3 archive the counts for the container and BatteryUI readers equal those recorded with them [1], [2]. Fourth, a decoder run that recovers every chunkset is checked against the chunkset count (Section 4.1). None of these shows that a record means what we say it means.

3.7 Tools and versions

Census: our own Python, standard library only (Listing 1). Readers: the released readers (version in Artifact Availability), run through the parser suite’s command-line tool on the gzip archive in a Python 3.13 virtual environment, with output written outside the evidence folders [1], [2], [3]. Decoder: unifiedlog_iterator 0.6.0 and 0.7.0 [16].

4 Results

Four differences survive the re-test, one decoder failure is quantified, and six claims of the initial comparison fail. Table 2 answers each research question; the subsections give the evidence, beginning with the differences that hold.

Table 2: Answers to the research questions on the ten archives, with the strength of the evidence.
QuestionAnswerStrength of evidenceWhere
RQ1 PersistenceFour differences hold: LZBITMAP in 94.5 percent of chunksets (none in iOS 26); a container-manager state file; a launch-services list and four small stores; BatteryUI buckets stored 86,400 s wide. The smaller Persist stream and BatteryBDC schema 3.3 are unresolved.Moderate for the compression change (it matches a public maintainer report); low to moderate for the bucket widths; low for every other statement about iOS 27Sec. 4.1 to 4.3; Figures 2 to 4
RQ2 Failure modeThe decoder without the codec completes with warnings and returns 4.6 percent of the records; its diagnostics repeat one message, an incorrect compression signature that decodes to ZBM and 0x0c.One archive; recorded runs, re-derived from stored aggregatesSec. 4.1; Table 3
RQ3 ReadingBatteryUI runtimes are in seconds (an hour cap of 3,600.0); a stored bucket width need not bound its values; a container birth time is not an install time, and a container without a directory cannot be called removed.Argued from the stored values; meaning is not provedSec. 4.3 and 4.5
RQ4 MethodOf thirteen claims, five are supported, six are not and two are unresolved. All six failures are file counts or member presence that a device on an earlier release also shows.Conservative rule, not a hypothesis testSec. 4.4; Tables 4 and 5

4.1 The codec change and the silent loss (RQ1, RQ2)

The compression signature separates the releases completely (Figure 2). All ten archives frame cleanly: every tracev3 file ends exactly at its last chunk and only the three known chunk types occur (zero framing errors). The nine iOS 26 archives hold 1,005,929 chunksets; 1,005,839 are LZ4 and 90 are stored uncompressed (bv4-, 15 in each D2 capture), and none uses LZBITMAP. The iOS 27.0 archive holds 99,642 chunksets, of which 94,197 (94.5 percent) are LZBITMAP, 5,442 are LZ4 and 3 are stored. All LZBITMAP signatures read ZBM followed by 0x0c; we saw no 0x09 variant, which the maintainers' discussion associates with other uses of the codec [13]. By stream, the Persist and Signpost files are entirely LZBITMAP; the LZ4 chunksets lie in the Special stream (5,278) and the live-data file (164 of its 207), which matches the maintainers' observation that memory-held logs keep LZ4 [13].

Chunkset compression signatures and decoder recoveryPanel (a): chunksets by compression signature. iOS 26.6, device D1, 3 captures: LZ4 144,668, stored 0, LZBITMAP 0 of 144,668. iOS 26.6.2, device D2, 6 captures: LZ4 861,171, stored 90, LZBITMAP 0 of 861,261. iOS 27.0, device D3, 1 capture: LZ4 5,442, stored 3, LZBITMAP 94,197 of 99,642 (94.5 percent). Panel (b): records recovered from the iOS 27.0 archive by decoder version 0.6.0, 1,944,016 of 42,588,594 (4.6 percent), and by version 0.7.0, 42,588,594 (100 percent).(a) Chunksets by compression signatureiOS 26.6 (D1, 3)LZBITMAP 0 of 144,668iOS 26.6.2 (D2, 6)LZBITMAP 0 of 861,261iOS 27.0 (D3, 1)LZBITMAP 94,197 of 99,642 (94.5%)LZ4 or storedLZBITMAP (ZBM)(b) Records recovered from the iOS 27.0 archivedecoder 0.6.04.6% (1,944,016 records)decoder 0.7.0100% (42,588,594 records)
Figure 2: (a) Chunksets by compression signature for the three devices; the nine iOS 26 archives together hold 1,005,929 chunksets. (b) Records recovered from the iOS 27.0 archive by two versions of the decoder. Sources: chunk census of this study; decoder runs recorded for the initial comparison.

The consequence for a decoder is large and quiet (Table 3). Version 0.6.0 returned 1,944,016 records from the iOS 27.0 archive, 4.6 percent of the 42,588,594 that version 0.7.0 returned, and its status was “completed with warnings”. It logged 208,135 diagnostics, of which 90,940 were retained and 117,195 counted but not kept once the queue filled. The retained messages repeat one pattern, an incorrect compression signature with the numeric value 206,389,850; that is 0x0C4D425A, the little-endian reading of 5A 42 4D 0C, which is ZBM and 0x0c. Version 0.7.0 recovered every record with none rejected; the two runs read the same 2,688 log files. The share of records recovered (4.6 percent) is close to the share of chunksets that are not LZBITMAP (5.5 percent), as expected if the older decoder skips every chunkset it cannot decompress and decodes the rest; chunksets differ in record count, so exact agreement is not expected.

Table 3: Decoder runs on the two decoded archives.
Archive, decoderStatusRecordsDiagnosticsLoss events
D1 26.6, 0.6.0completed25,598,2867,509 notices, 499 coverage386
D3 27.0, 0.6.0completed with warnings1,944,016208,135 errorsnot reported
D3 27.0, 0.7.0completed42,588,59462 notices, 215 coverage968

Loss events are records the log itself marks as data dropped on the device before collection. The D1 archive gave the same record count under 0.7.0 in our engineering record of that run; that run was not retained and is not recomputable.

4.2 Archive members present only on iOS 27.0 (RQ1)

Three groups of members occur in the iOS 27.0 archive and in none of the nine iOS 26 archives (Figure 3, upper rows): the ContainerManager state file (3.98 MB); a LaunchServices directory with an identifier list; and four small stores, namely OS analytics, a tailspin binary-location map, application-managed-feature configuration and a logging-preferences policy. Of the members that the initial comparison listed as new or removed, these are the ones that the wider comparison does not contradict; the lower rows of Figure 3 show the others (Section 4.4).

Presence of selected archive members by iOS versionCaptures that contain each item over captures examined, for iOS 26.6 (device D1, 3 captures), iOS 26.6.2 (device D2, 6 captures) and iOS 27.0 (device D3, 1 capture). Present only in the iOS 27.0 archive: logs/ContainerManager/state.json 0/3, 0/6, 1/1; logs/LaunchServices 0/3, 0/6, 1/1; logs/OSAnalytics, the tailspin binary-location map and two more small stores 0/3, 0/6, 1/1. Not specific to iOS 27.0: logs/fsck/fsck_apfs.log 0/3, 6/6, 1/1; SiriAnalytics database 3/3, 0/6, 0/1; UARP packet captures 3/3, 0/6, 1/1 (one file); logs/AVConference 3/3, 0/6, 1/1; StagingLogs last-build directory 3/3, 6/6, 1/1; BatteryUI upgrade-marker file 0/3, 6/6, 1/1.26.6D1, 326.6.2D2, 627.0D3, 1Present only in the iOS 27.0 archiveContainerManager/state.json0/30/61/1LaunchServices directory0/30/61/1OSAnalytics, tailspin map, +20/30/61/1Not specific to iOS 27.0fsck/fsck_apfs.log0/36/61/1SiriAnalytics database3/30/60/1UARP packet captures3/30/61/1AVConference logs3/30/61/1StagingLogs, last build3/36/61/1BatteryUI upgrade marker0/36/61/1
Figure 3: Presence of selected archive members, as captures that contain the item over captures examined. Upper rows: present only in the iOS 27.0 archive. Lower rows: members the initial comparison listed as new or removed that an iOS 26 device also has, or also lacks. Source: member census of this study.

The data narrow one published statement. The release description of the container-state reader says that iOS 27 sysdiagnoses “no longer carry” the older container-manager and app-installation text logs [1]. In the nine iOS 26 archives the logs/MobileContainerManager and logs/appinstallation directories were already absent, and only the mobile_installation logs and a short appinstallation summary remain on every release we hold. The statement is true of the older parsers' inputs, which return nothing on this archive, but our data cannot place the change at iOS 27. The state file itself is new relative to every iOS 26 archive we hold.

4.3 BatteryUI: a proved unit and a changed bucket width (RQ1, RQ3)

The BatteryUI property lists hold per-app foreground and background runtime and energy values in four range entries (DayKey, DayTapKey, WeekKey, WeekTapKey), each a series of buckets with a stored start and end. We tested the unit of the runtimes against the data instead of assuming it. In all ten archives no foreground runtime in a tap bucket exceeds the stored width of its bucket in seconds. In the iOS 27.0 main file ten values equal exactly 3,600.0 and none is larger, which is the signature of an hour cap on a runtime in seconds; on D1 the largest value in an hour-wide bucket is 2,635.4, far more than an hour holds in minutes. Each bucket's foreground and background time equals the sum of its app values in the files checked at merge [2]. Energy values have no established unit and are labelled as stored.

The stored bucket width differs between the releases (Figure 4). In all three D1 captures and all six D2 captures the DayTapKey buckets are 3,600 s wide and the single WeekKey bucket 864,000 s. In the iOS 27.0 file, and in its upgrade-marker file, every bucket is stored 86,400 s wide. The 24 buckets of DayTapKey are still present, and ten of their values equal 3,600.0, so a width of 86,400 s does not describe the period a value covers: the stored times of that entry do not bound its values. This is the one structural BatteryUI difference that separates the iOS 27.0 file from both iOS 26 devices and from the corpus files; what produces it is not established. The notes of the BatteryUI reader record five sysdiagnoses from a public test corpus (Artifact Availability), from iOS 13.3.1 to iOS 26.6, in which the DayTapKey buckets are 3,600 s wide on iOS 17.3, 26.5.2 and 26.6 and no bucket times are stored on iOS 14.3 [2]. Among the files we know of, the 86,400 s shape occurs only on iOS 27.0.

Stored BatteryUI bucket width by range entry and iOS versionDot plot on a logarithmic axis from 3,600 to 864,000 seconds. DayKey: 86,400 seconds in iOS 26.6, 26.6.2 and 27.0. DayTapKey: 3,600 in iOS 26.6 and 26.6.2, 86,400 in iOS 27.0. WeekKey: 864,000 in iOS 26.6 and 26.6.2, 86,400 in iOS 27.0. WeekTapKey: 86,400 in all three.Stored bucket width (logarithmic axis)3,600 s1 h86,400 s1 d864,000 s10 dDayKeyDayTapKeyWeekKeyWeekTapKeyiOS 26.6 (D1)iOS 26.6.2 (D2)iOS 27.0 (D3)
Figure 4: Stored width of the BatteryUI buckets by range entry and device. Dots of a row lie at the same position where the widths are equal. Source: bucket start and end times in the BatteryUI property lists of all ten archives.

4.4 Six claims that did not survive (RQ4)

Table 4 applies the rule of Section 3.5 to each claim of the initial comparison that the ten archives can address. Of the thirteen claims, five are supported, six are not, and two are unresolved. Every failed claim is of one kind: a file count, or the presence of a member, that we read as a release effect and that a device on an earlier release also shows.

Table 4: Claims of the initial two-archive comparison re-tested against ten archives.
Claim of the initial comparisonEvidence in ten archivesStatus
Chunksets use LZBITMAP in iOS 270 of 1,005,929 in nine iOS 26 archives; 94,197 of 99,642 in iOS 27.0Supported
An unaware decoder loses most records4.6 percent recovered (recorded run)Supported for the one archive
ContainerManager state file is newAbsent from all nine iOS 26 archivesSupported
LaunchServices list and four small stores are newAbsent from all nine iOS 26 archivesSupported
BatteryUI bucket width differs3,600 and 864,000 s on 9 of 9 iOS 26 archives (two devices); 86,400 s on iOS 27.0 (one device)Supported; one iOS 27 device
Special stream grew from 133 to 782 filesD2 (iOS 26.6.2): 1,001 in all six capturesNot supported
Shared-cache string files doubledTwo files on D2Not supported
SiriAnalytics database removedAbsent from 6 of 6 D2 capturesNot supported as iOS 27
Accessory packet captures reduced from 28 to 2None on D2Not supported as iOS 27
Staging directory of the last build is newPresent in all ten archivesNot supported
File-system check log is newPresent in 6 of 6 D2 capturesNot supported
Persist stream is smaller349 MB against 515 to 532 MB; one iOS 27 deviceUnresolved
BatteryBDC schema 3.3 is newOnly in the iOS 27.0 archive; version sets differ by deviceUnresolved

File counts follow the device. Our census reproduces the initial comparison's counts for the two archives it shares with that analysis: 3,963 and 5,495 members, 199 and 831 tracev3 files, and the signature counts of Section 4.1. Table 5 and Figure 5 place those two archives among the others. Between-device differences are large and within-device differences are small: the six D2 captures, made within two hours, have 1,281 tracev3 files each, and the three D1 captures have 164, 199 and 206. The iOS 27.0 archive does not stand out on file counts. Its 831 files lie between D1 and D2, and its Special stream (782 files) is smaller than that of D2 (1,001 files in every capture). The growth of the Special stream is therefore not shown to be an iOS 27 effect, and the same holds for the doubled shared-cache string files (two on D2) and for the lower count of time-synchronisation files (one on D2). Crash and spin report files show the same caution within one device: the three D1 captures hold 4, 14 and 21, so the initial comparison's drop from 14 to 5 sits inside the within-device range of the earlier release.

Table 5: Archive inventory by device (range over captures; D3 has one capture).
MeasureD1 26.6 (3)D2 26.6.2 (6)D3 27.0 (1)
Compressed archive (MB)707–7851,768–1,7751,097
Unpacked (MB)1,325–1,4723,215–3,2242,093
Members3,878–3,9633,820–3,8225,495
Members, no AppleDouble2,595–2,6743,261–3,2634,151
tracev3 files164–2061,281831
Persist, files51–525136
Persist, MB524–532515–524349
Special, files101–1411,001782
Special, MB205–2871,150–1,156913
Signpost, files10–1322812
Signpost, MB18–2645911
Shared-cache string files122
timesync files713
Subdirectories of logs/555261
Crash and spin reports4–2185
Chunk framing errors000

Sizes in megabytes (106 bytes). Source: chunk and member census of this study, one pass per archive.

Special stream file count and Persist size in each of the ten archivesTen bars per panel, one per capture, grouped by device and iOS version. Panel (a), tracev3 files in the Special stream: iOS 26.6 (D1) 101, 133 and 141; iOS 26.6.2 (D2) 1,001 in each of six captures; iOS 27.0 (D3) 782. Panel (b), Persist stream size in megabytes: D1 532, 524 and 529; D2 524, 515, 520, 516, 522 and 516; D3 349.(a) Special stream, tracev3 files04008001,2001011331417821,001 in each of six(b) Persist stream, megabytes020040060053252452952451552051652251634926.6 (D1)26.6.2 (D2)27.0(D3)
Figure 5: Special stream file count (a) and Persist size (b) in each of the ten archives, grouped by device. Bars within a group are captures of the same device. The iOS 27.0 Special count lies inside the range spanned by the two iOS 26 devices; its Persist size lies below both. Source: chunk and member census of this study.

Member presence follows the device. The file-system check log is present in all six D2 captures and in the iOS 27.0 archive but not in the D1 captures; the SiriAnalytics database is present on D1 and absent from D2 and D3; the packet-capture directory for accessory firmware holds 14 files on D1, none on D2 and one on D3; and a directory of conferencing logs is present on D1 and D3 but not on D2 (Figure 3, lower rows). The staging directory that preserves logs from the previous build, which the initial comparison read as a new “upgrade trail”, is present in all ten archives, and a BatteryUI upgrade-marker file occurs on D2 as well. The BatteryBDC schema versions present are 3.3, 3.0, 2.9 and 1.0 on D3, 3.0, 2.9, 2.8 and 2.6 on D1, and only 3.0 on D2, so the set of versions tracks the device's history of updates and not only the release.

Unresolved. One file-level difference remains: the Persist stream is 349 MB in 36 files on iOS 27.0, against 515 to 532 MB in 51 or 52 files in all nine iOS 26 archives. We leave it unresolved, because a shorter retention window or lighter use on one device would produce the same.

4.5 The readers on three devices (RQ3)

The released readers parsed one archive of each device without error (Table 6). On the D1 and D2 archives the row counts equal those recorded when the readers were released, a regression check in a changed environment. On the iOS 27.0 archive, the families written on 26.x layouts still read the files: associated domains, managed-configuration events, Network Extension, brctl and taskinfo all produce rows, and the two families first tested on the 27.0 file give the counts recorded with them [1], [2]. Two outputs are empty on iOS 27.0. For the per-app associated-domain settings, the SETTINGS section of the printed swcutil file is present but prints no entries, where the 26.x files print 35 and 11; for the profile events, the stored list is empty. We cannot attribute either to the release, because both depend on what was configured on the device.

Table 6: Rows reported by the readers on one archive of each device.
Artifact (source file)D1D2D3
Container state: containers with a directory (ContainerManager/state.json)no fileno file1,738
Container state: containers without a directoryno fileno file419
Container state: code-signing registrationsno fileno file1,799
BatteryUI: per-app runtime rows (BatteryUIPlist)2721,009699
BatteryUI: time buckets367272
Associated domains (swcutil_show.txt)1,9421,6901,776
Associated-domain settings35110
Managed configuration: setting events (MCSettingsEvents.plist)431376531
Managed configuration: profile events2100
Network Extension: configurations (com.apple.networkextension.plist)223
Network Extension: path rule groups323
iCloud Drive containers (brctl-container-list.txt)7134120
iCloud Drive version history; sync state (brctl-dump.txt)21; 215; 2113; 21
Process task info (taskinfo.txt)413554582

D2: the first capture. The container and BatteryUI readers are described in [1] and [2], the rest in [3]. BatteryUI snapshot rows (1, 2 and 2) are not shown. Rows are one per stored record; the sync-state reader reports a fixed number of header and scheduler lines. Counts equal those recorded at release wherever one was recorded. Source: readers re-run for this study; the output was not saved in any repository.

The container-state reader gives, on the iOS 27.0 file, 1,738 containers that had a directory when the state was captured, 419 recorded without one, and 1,799 registrations. The SAF port, which reads the same file differently, reports 4,744 events (2,157 container records, 1,799 code-signing, 637 extension-to-app, 58 caller records, 15 class-path, 11 persona and 67 managed-path), with the per-type counts equal to an independent count of the file's records [4]. The two numbers of container records differ by construction: our artifacts split containers by whether a directory exists, and the SAF parser emits every container record. A container's birth time is when the device created the container, not when anyone installed an app, and a container with no directory cannot be told apart as removed, replaced or never created; the notes in both tools say so.

4.6 Log content of the two decoded archives

The log-level comparison rests on the two decoded archives, which come from different devices of different hardware generations, with different usage, capture windows and decoder versions. We report selected differences with their confounds in Table 7 and draw no release-level conclusion from them. One correction of the initial comparison stands. Dividing the record count by the time span suggests that iOS 27 logs 4.6 times more densely per hour, but the D1 span of 780 hours is mostly a thin tail, with 99.99 percent of its records in its busiest four days, while the D3 records are spread over twelve days (eight days with at least a million records, against four). Averaged over days with at least a million records, the daily rate is 6.4 million for D1 and 5.0 million for D3, that is, not higher. The D3 log set also contains 25 boot identifiers against 2.

Table 7: Selected log-level differences between the two decoded archives, with the confound that prevents a release-level reading.
MeasureD1 26.6D3 27.0Confound
Decoded records25,598,28642,588,594Different devices, usage and windows (780 h and 283 h)
Fault-level records (share)19,997 (0.078%)203,730 (0.478%)Usage; noise from a few system daemons
Statedump records with a process name0 of 48,392166,805 of 166,805Different decoder versions; cannot separate OS from decoder
Image-signal-processor subsystem records01,036,132Different camera hardware; its daemon name changes with the chip generation
Network connection-category records255,6251,561,241Usage; a third-party VPN app on D3
Network Extension subsystem records2,745114,940Same VPN app
Sandbox violation reports28,80462,035Usage
Managed-configuration subsystem records3,78823,094Whether either device was managed is unknown
Records flagged as redacted (share)27.5%25.0%Usage; no thinner payloads seen
Media-analysis subsystem records1,9002,123,214Photo-library size and usage
Distinct boot identifiers225Restarts may truncate the dense window

Source: analysis stores of the initial comparison, re-derived from stored inputs by its verification script (56 checks pass). Counts are unified-log records of each archive; they are not repeated on the other eight archives.

The log-level observation we consider robust is the decoder behaviour of Section 4.1; the content differences of Table 7 remain hypotheses. Access payloads for permission checks remain private in both archives, and the share of records flagged as redacted does not fall, so on this pair the log gives no evidence of thinner payloads. An examiner should not expect to reconstruct sensor-access indicators from logs alone.

5 Discussion

The results say as much about how release changes are found as about what changed. This section draws three lessons.

5.1 A pair of archives yields candidates, not findings

Six of the thirteen claims of a careful two-archive comparison did not survive a third device, and all six were of one kind: a file count or the presence of a member that we read as a release effect and that a device on a nearby release also shows. What survived differs in kind. The codec change has independent support: a public maintainer report [13], our reproduction on a complete archive, and a measured effect. The new structured files are absent from every iOS 26 archive we hold, and the BatteryUI width change is the best-supported structural difference, because the iOS 26 widths agree across two devices and three corpus files. The lesson is not that comparing two archives is wrong, but that its output is a list of candidates. We recommend that any statement of the form “X changed in release Y” about a sysdiagnose be checked against at least two devices on the earlier release and, ideally, against one device captured before and after the update.

5.2 The examiner's risk is the failure mode, not the codec

For examiners the finding that matters most is how the older decoder failed. It finished and said so; the loss was visible only as a count. A short test avoids it: tally the signatures of the chunksets in a sample of tracev3 files (Listing 1) and compare the number of records decoded with what the signatures predict. Record the decoder version with every result. Treat a file-count difference between two archives as a lead until a second device agrees, and state the coverage window of a log, not only its span.

5.3 Units and wording belong in the reader

The readers carry their limits in their notes, and the iOS 27 state file shows why. A reader that prints a container birth time under the column name “installed” would be wrong; one that reports a container without a directory as “removed” would be wrong; and the BatteryUI runtimes would be wrong by a factor of sixty if read in minutes. The unit test of Section 4.3 is cheap and should be routine for any value whose unit the file does not state.

6 Threats to Validity

Internal validity. Counts were produced by our own code and compared with a second pass of earlier code and with counts recorded when the readers were released; agreement shows that the code does what its specification says, not that the specification matches what the operating system meant. The log-level counts of Section 4.6 come from recorded runs and stores that we did not repeat. The census walks only the chunk framing and the signature; it does not decompress, so it says nothing about the content of the chunksets.

Construct validity. A row is a record the device stored or printed, not proof of a user action; we did not observe the actions that produced these records. Container times are creation times of directories, not install times. “Absent from an archive” means absent from that capture; a member can be written only when a component has run. No result shows that a difference is caused by the release rather than by hardware, usage or capture conditions.

External validity. This is the dominant limit. There is one iOS 27 capture. The three devices are of two hardware generations, were captured under different conditions, and are not a sample of any population; nothing seen on them is shown to hold on others. The D1 and D2 captures are repeat captures of one device each and are not independent. We have no iOS 27.x update, no iOS 18 or earlier archive, and no iPad. The corpus run quoted for the BatteryUI widths is from a public test corpus, not ours, and was read from the reader’s notes.

Conclusion validity. No statistical inference is made from three devices. The status labels of Table 4 follow a conservative rule and are not hypothesis tests.

Selection. The archives are those held in the Lab's research collection. The comparison was widened because the first claims seemed worth checking, and the claims that failed are reported with those that passed. The one archive excluded is truncated; it was not excluded for its content.

Limitations. Neither decoder version was re-run on the other eight archives, so the log-level counts rest on one recorded measurement. The statement that logarchives written by version 27 systems open only on macOS 26.2 or later [11] was not tested.

7 Conclusion and Future Work

A single iOS 27.0 sysdiagnose differs from nine iOS 26 sysdiagnoses in four ways that the two iOS 26 devices do not explain: most log chunksets use a new codec that an older decoder drops while reporting completion; a container-manager state file appears; a launch-services list and four small stores appear; and BatteryUI buckets are stored a day wide. Six other differences that a comparison of one archive per release suggested are properties of the device or the capture, and we withdrew them. The methodological result is that a release comparison of sysdiagnose structure needs more than one device per release before its differences are findings. Any sysdiagnose parser, open-source tools included, can run the tally of Listing 1 and the re-test rule. This is an early observation, and its iOS 27 half is one capture.

Future work, in order of value: (1) a second iOS 27 device, and a device captured immediately before and after an update to iOS 27, so that the release effect can be separated from the device; (2) captures whose device history is documented (camera use, a profile install, a VPN configuration) to test the log-level hypotheses of Table 7 against a documented history; (3) a re-run of both decoder versions on the other eight archives, so that the log-level counts rest on a repeated measurement; (4) an iOS 18 or iOS 17 archive for the files that the older readers expect (uuid2path is absent from every iOS 26 and iOS 27 archive we hold), and verification of the Network Extension VPN, content-filter and per-app keys on a device that has them configured.

Artifact Availability

The sixteen readers are released as part of iLEAPP [7] under the MIT licence, merged through three pull requests: #2509 (container state), #2521 (BatteryUI) and #2575 (associated domains, managed-configuration events, Network Extension, brctl, task info). The container-state parser for SAF is open for review as pull request #262 (EUPL-1.2). Synthetic generators and fixtures are released with the readers. The test corpus of Sections 4.3 and 5.1 is iLEAPP’s [2]. The census routine is given in full in Listing 1. The archives cannot be released; the real-data results can be checked only by someone holding comparable archives.

Data Handling Statement

Test data were of two kinds: (1) full file system extractions and sysdiagnose archives of research devices (test devices) provided to the Lab by their owners and held in its research collection, used read-only for research with the owners' permission and never copied into any repository, fixture, paper or public file, except the sanitised copies of file structure described in this paper, in which every identifying value was replaced; (2) fully synthetic files written by the author with invented values (reserved example domains, placeholder identifiers). The ten archives in this paper are of kind (1), and only aggregate counts, device classes, operating system versions and file or table names are reported. No names, numbers, accounts, serial numbers, network names, application lists, hashes or file paths from the real data appear in this report. A leak scan compared the released fixtures with the real sources before release. No offensive technique, exploit or credential-recovery method is described.

Declaration of AI Assistance

The reader code, the data checks and the drafting of this report were produced with AI assistance (Anthropic Claude). The author directed the work, reviewed the results and the text, and is responsible for the content.

References

  1. Daniel Addai. 2026. Add Container Manager State artifacts for iOS 27 sysdiagnose. iLEAPP pull request #2509, merged October 19, 2026. Retrieved October 27, 2026 from https://github.com/abrignoni/iLEAPP/pull/2509
  2. Daniel Addai. 2026. Add BatteryUI per-app runtime artifacts for iOS sysdiagnose. iLEAPP pull request #2521, merged October 20, 2026. Retrieved October 27, 2026 from https://github.com/abrignoni/iLEAPP/pull/2521
  3. Daniel Addai. 2026. Sysdiagnose: associated domains, MC event lists, Network Extension, iCloud Drive (brctl) and process task info. iLEAPP pull request #2575, merged October 25, 2026. Retrieved October 27, 2026 from https://github.com/abrignoni/iLEAPP/pull/2575
  4. Daniel Addai. 2026. new: [parser] containermanager_state - iOS 27 ContainerManager/state.json. Pull request #262, EC-DIGIT-CSIRC/sysdiagnose, open. Retrieved October 27, 2026 from https://github.com/EC-DIGIT-CSIRC/sysdiagnose/pull/262
  5. Apple. [n. d.]. COMPRESSION_LZBITMAP. Compression framework, Apple Developer Documentation. Retrieved October 27, 2026 from https://developer.apple.com/documentation/compression/compression_lzbitmap (Title confirmed; page body not read.)
  6. Apple. [n. d.]. Supporting associated domains. Apple Developer Documentation. Retrieved October 27, 2026 from https://developer.apple.com/documentation/xcode/supporting-associated-domains (Title confirmed; page body not read.)
  7. Alexis Brignoni et al. [n. d.]. iLEAPP. GitHub repository (MIT licence). Retrieved October 27, 2026 from https://github.com/abrignoni/iLEAPP
  8. D. Durvaux and C. Vandeplas. 2025. Building a pipeline to analyse iOS devices at scale. Talk, hack.lu 2025, October 23, 2025. Retrieved October 27, 2026 from https://pretalx.com/hack-lu-2025/talk/CMHBFT/
  9. EC-DIGIT-CSIRC. [n. d.]. Sysdiagnose Analysis Framework (SAF). GitHub repository (EUPL-1.2). Retrieved October 27, 2026 from https://github.com/EC-DIGIT-CSIRC/sysdiagnose
  10. Simson L. Garfinkel. 2010. Digital forensics research: The next 10 years. Digital Investigation 7 (2010), S64–S73. https://doi.org/10.1016/j.diin.2010.05.009 (Bibliographic data confirmed from index records; full text not read.)
  11. hoakley. 2026. Explainer: sysdiagnose and logarchives. The Eclectic Light Company, June 27, 2026. Retrieved October 27, 2026 from https://eclecticlight.co/2026/06/27/explainer-sysdiagnose-and-logarchives/
  12. Graeme Horsman. 2019. Tool testing and reliability issues in the field of digital forensics. Digital Investigation 28 (2019), 163–175. https://doi.org/10.1016/j.diin.2019.01.009 (Bibliographic data confirmed from index records; full text not read.)
  13. macos-UnifiedLogs contributors. 2026. Parsing of iOS 27 log archives partially fails. Issue #145, mandiant/macos-UnifiedLogs, opened August 4, 2026, closed August 27, 2026. Retrieved October 27, 2026 from https://github.com/mandiant/macos-UnifiedLogs/issues/145
  14. macos-UnifiedLogs contributors. 2026. Rust based lzbitmap decompression support. Pull request #147, mandiant/macos-UnifiedLogs, merged August 8, 2026. Retrieved October 27, 2026 from https://github.com/mandiant/macos-UnifiedLogs/pull/147
  15. Mandiant. [n. d.]. macos-UnifiedLogs. GitHub repository (Apache-2.0). Retrieved October 27, 2026 from https://github.com/mandiant/macos-UnifiedLogs
  16. Mandiant. 2026. macos-UnifiedLogs release v0.7.0. Changelog dated September 12, 2026; lists LZBITMAP decompression and initial iOS 27 support. Retrieved October 27, 2026 from https://github.com/mandiant/macos-UnifiedLogs/releases/tag/v0.7.0
  17. MVT Project. [n. d.]. Mobile Verification Toolkit (MVT). GitHub repository. Retrieved October 27, 2026 from https://github.com/mvt-project/mvt (Existence confirmed.)
  18. Maher Yamout. 2024. A lightweight method to detect potential iOS malware. Securelist (Kaspersky), January 16, 2024. Retrieved October 27, 2026 from https://securelist.com/shutdown-log-lightweight-ios-malware-detection-method/111734/

Cite and download

Cite as

Daniel Addai. 2026. Log Compression and Archive Structure in the iOS 27.0 Sysdiagnose: An Early Observation Tested Against Ten Archives. Lab Technical Report LAB-TR-0011, version 1.2. SectraTEK Lab, Prudential Associates. Preprint, not peer reviewed. https://lab.sectratek.com/research/reports/lab-tr-0011/ DOI: https://doi.org/10.5281/zenodo.23717934

Citation guide

DOI (all versions): 10.5281/zenodo.23717934
DOI of version 1.0: 10.5281/zenodo.23717935
Archived at Zenodo: https://zenodo.org/records/23717935 (PDF and files)

lab-tr-0011.bib
@techreport{addai2026labtr0011,
  author      = {Addai, Daniel},
  title       = {Log Compression and Archive Structure in the iOS 27.0
                 Sysdiagnose: An Early Observation Tested Against Ten
                 Archives},
  institution = {SectraTEK Lab, Prudential Associates},
  type        = {Lab Technical Report},
  number      = {LAB-TR-0011},
  year        = {2026},
  month       = oct,
  doi         = {10.5281/zenodo.23717934},
  url         = {https://doi.org/10.5281/zenodo.23717934},
  howpublished = {https://lab.sectratek.com/research/reports/lab-tr-0011/},
  note        = {Version 1.2, preprint, not peer reviewed. CC BY 4.0}
}

Licence: CC BY 4.0. The print layout of this page is set for US Letter in two columns.

Versions and corrections

VersionDateChange
1.02026-10-27First release. Also covers the readers for new sysdiagnose files (Section 3.4); no separate report is issued for them.
1.02026-10-27Posted on Zenodo (preprint), DOI 10.5281/zenodo.23717935.
1.12026-10-27Corrected the data-handling statement: it now names the exception for the sanitised copies of file structure described in the paper, in which every identifying value was replaced.
1.22026-10-28Corrected the process wording: the readers are described as written from the observed file layouts, which is what is documented, and not as clean-room readers; the assignment of captures to devices now rests on a comparison of hashed device identifiers.

Corrections: see versions 1.1 and 1.2 above. Errors can be reported through the corrections page.