Reading view

There are new articles available, click to refresh the page.

How does macOS keep its log?

One of the mysteries of the Unified log since its introduction almost ten years ago in macOS Sierra has been how it keeps such extensive records of what happens between the start of kernel boot and the user logging in. This must have been sufficiently challenging before Catalina, but since then the separate Data volume, where log files are stored, has been locked away by FileVault until the user’s password enables it to be accessed.

Log entries are initially stored in memory, and from there most are written to tracev3 files in their respective directories in /var/db/diagnostics. logd is responsible for that, and for maintaining the contents of that directory. Ironically, logd maintains its own old-style log in text files inside that directory, but its terse entries there reveal little about how it does its job. What they do reveal is that logd has an assistant, logd_helper, with its own old-style text logs that are a bit more informative.

In Apple silicon Macs, logd_helper apparently connects every few minutes to five coprocessors, SMC (System Management Controller), AOP (Always-On Processor), DCPEXT0, DCPEXT1 and DCPEXT2 (Display Co-Processors). There appears to be nothing equivalent in Intel Macs. It also conducts ‘harvests’ shortly after it has started up, so solving the mystery of where all the log entries are saved prior to unlocking the Data volume.

Soon after the start of kernel boot, once the Preboot volume is generally accessible and logd is running, logd starts writing log entries to temporary storage in the Preboot volume. You can see that in the path /System/Volumes/Preboot/[UUID]/PreLoginData, where there’s a complete diagnostics directory, and one to store longer log entries in the warren of directories in uuidtext. Those are identical in layout to permanent log storage in /var/db.

Shortly after user login, with the Data volume unlocked at last, logd_helper is started, and it merges log files from Preboot/[UUID]/PreLoginData/diagnostics and those files in Preboot/[UUID]/PreLoginData/uuidtext into permanent log storage in the Data volume in /var/db/diagnostics and /var/db/uuidtext, a process it refers to as harvesting. logd_helper can also harvest from entries stored in memory.

Once this merger has been completed, log directories in Preboot/[UUID]/PreLoginData/diagnostics are left empty, as are logdata.statistics files there, making the log record of kernel boot complete, right up to unlocking of the Data volume.

That explains how tens of thousands of log entries can still be recorded faithfully in a Data volume that can’t be unlocked for some time yet.

Once normal logging to /var/db/diagnostics is running, logd maintains the tracev3 files containing log entries there. Its goals appear to be:

  • in the Persist folder, file size is normally 10.4-10.5 MB, although it may be smaller when truncated by shutdown;
  • Persist files are removed with age to maintain a typical total size for that folder of just under 530 MB in just over 50 files, bringing the size of the whole diagnostics folder to between 1-2 GB;
  • in Special and Signpost, log file size is normally 2.0-2.1 MB when closed, but entries are weeded progressively until each file is empty and can be deleted;
  • timesync files are less than 1 KB;
  • HighVolume is seldom if ever used.

The overall effect on historical log entries is that those in Persist files are rate-sensitive and removed sooner when log entries are written more frequently. However, selected entries in Special files may last considerably longer, but become less frequent with age. A few of those may be retained for hours or days longer than the oldest in Persist files. I have no insight into the rules that logd follows when deciding when to weed entries from Special files.

Extended entries stored in the warren of folders in /var/db/uuidtext are purged periodically on request from CacheDelete, as with other purgeable storage, at least once a day. That should ensure that the contents are only retained while they’re still referred to by entries in the log files.

As far as I’m aware, the user gets no say in the size limits imposed on log storage, and there’s no option to increase them to allow logs to be retained for longer. However, as both /var/db/diagnostics and /var/db/uuidtext folders should be backed up by Time Machine and most third-party utilities, you can always analyse those backups when you need to check older log entries.

What happens in early kernel boot on Apple silicon?

Secure Boot on an Apple silicon Mac is unlike anything you’ve seen in the past, sequences that start from the Boot ROM, and progress through two levels of ‘firmware’ before even loading the kernel. This article tries to explain its main stages up to the point that OpenDirectory is started, about 10 seconds after pressing the Power button.

The first three stages are essentially the same, whether the Mac is starting up from macOS on its internal SSD, or from a copy installed on external storage:

  1. The Boot ROM, which is in the hardware, and can’t be changed. In this context, its most important task is to verify the executable for the next stage, load and run it. If that isn’t possible, then the fallback is to go into DFU mode and await a connection over USB.
  2. The Low-Level Bootloader, LLB, to verify and read stored security settings, and locate and verify the software for the next stage, then hand over to it. This is stored in dedicated Flash memory, and relies on LocalPolicy and other files stored in protected areas on the internal SSD.
  3. iBoot or iBoot Stage 2, popularly but incorrectly called the ‘firmware’, has to verify a set of hashes used to guarantee the integrity of key information, by comparing a stored copy of the hash against a hash of that hash, termed its signature. Among those is the root hash of the Signed System Volume (SSV), but iBoot doesn’t attempt to access the SSV or its hashes, merely passing on the verified root hash for the kernel to use later. Once it has completed those checks, iBoot verifies, loads and runs the macOS kernel.

Kernel boot (5.3 seconds)

These stages leave little evidence of what takes place, as they don’t write to the log. Instead they leave terse binary data known as breadcrumbs that may be found in NVRAM. The only log entries for them are the initial announcement, and the start of the kernel phase. Throughout this article, I quote these from macOS 26.2 in Full Security mode on a Mac mini M4 Pro, with the Power button being pressed at about 0.0 seconds.
0.24 === system boot: F5BD2102-F86A-4823-8FF9-A4535295F9FA
5.30 kprintf initialized

The kernel takes over from iBoot at about 5.3 seconds, and reports its version, in this case Darwin Kernel Version 25.2.0. The log stream is configured, and the iBoot versions are given. It then starts running up security systems, including CoreCrypto, and loads security policy with Apple Mobile File Integrity (AMFI) and Seatbelt sandbox policy (Sandbox).

Early hardware (5.6 seconds)

Then the kernel enters its main phase for starting hardware and its services. First are AppleT6041ANEHAL and IOAccessoryManager, followed by IOThunderboltFamily. Some of these are still security-related, including AppleCredentialManager and a long series of initialisation for the Secure Enclave, beginning with the detailed
5.696 "AppleSEPKeyStore":pid:0,:327: starting (BUILT: Nov 18 2025 20:56:29) ("normal" variant 🌽 , 2155.60.14)
KernelBluetoothFamily starts at about 5.7 seconds, and AppleT6040PCIeC shortly afterwards.

At 5.71 seconds AppleARMWatchdogTimer is started to keep an eye on processes that become unresponsive, and that’s followed by the traditional copyright notice that has been there since the first Mac OS X:
5.712 Copyright (c) 1982, 1986, 1989, 1991, 1993 The Regents of the University of California. All rights reserved
a reminder of long-past history.

That’s followed by the start of RTBuddy, AppleSMC and at 5.836 seconds AppleSEPManager. RTBuddy provides communications support to the real-time operating system RTKit that’s run on the co-processors and support cores within the SoC, believed to include the Apple Neural Engine (ANE), Display Coprocessor (DCP), NVMe controller, and System Management Controller (SMC). RTBuddy messages are then frequent throughout the log during the kernel phase.

CPU cores (6.1 seconds)

Up to this point, the kernel has been running on a single CPU core, but by about 6 seconds it’s time to start up all the CPU cores one by one. This occurs by cluster, starting with cluster 0 of E cores, followed by the P cluster(s) in numeric order.

Once those are running, APFS and NFS are loaded and started, the former in an entry giving version details:
6.130 apfs_module_start:3677: load: com.apple.filesystems.apfs, v2632.40.17, apfs-2632.40.17, 2025/11/18
Gatekeeper is enabled, and AppleSystemPolicy started. Despite the implications of its name, the Always-On Processor (AOP) is then readied with its SMC service.

File system (6.3 seconds)

At 6.315 seconds, APFS starts its work accessing the three containers in the SSD, disk0s1, disk0s2 and disk0s3. It then gets the boot device, declares it as BSD root: disk3s1 and starts to mount the SSV. That may seem paradoxical, as by this time the kernel from the SSV has been running for over a second, but that was loaded by iBoot, together with the kernel extensions it requires. Similarly, the NVRAM is prepared for use by deleting nonce seeds, writing breadcrumbs from the previous boot phases, etc.

APFS continues to mount volumes, including Recovery at disk3s3 and the macOS Base System. The OS run by the Secure Enclave Processor, SEP/OS, is declared alive at 6.37 seconds, and the SEP is then preparing.

Userspace boot (6.4 seconds)

This is declared at 6.375 seconds, and the kernel then attempts to load launchd. Additional volumes are mounted from 6.8 seconds, including VM, Preboot, Update, xART, ISCPreboot and Hardware.

With the SEP running, BiometricKit is started at 8.788 seconds. At about 9 seconds, APFS tries to mount the Data volume at disk3s5, but that can only be successful if FileVault isn’t enabled, so that fails, and has to await the loginwindow and the user password entered there. At 9.429 seconds, a long list of boot tasks is given.

At 9.875 seconds, OpenDirectory is started, followed by the first of two wallclock time adjustments
=== system wallclock time adjusted
at which point all log times are adjusted accordingly.

By this stage, 10 seconds after the Power button was pressed, the kernel and other processes that are just about to start up have access to the hidden containers and volumes, and the SSV, but not the Data volume (unless FileVault is disabled). Logs are most probably stored in memory until they can be written to the Data volume, and none of the settings or processes on that can be read. Those all require the user to unlock the Data volume.

There’s a superbly detailed account of security aspects in this article.

❌