Le format de fichier tracev3 expliqué
Au cœur des fichiers tracev3 de macOS : en-tête, catalogue, chunksets LZ4, chunks firehose, oversize, statedump, chaînes uuidtext et dsc, timesync.
En bref. Un fichier .tracev3 est un flux de chunks. Un chunk d'en-tête décrit la machine et le démarrage, des chunks de catalogue listent les processus et les subsystems, et chaque catalogue est suivi de chunksets — des blocs compressés en LZ4 contenant les entrées firehose (les messages de journal), les chaînes oversize, et les enregistrements statedump et simpledump. Le texte provient des fichiers uuidtext et dsc, l'heure des fichiers timesync. C'est cette structure que décode Unified Log Parser, à l'aide du parseur open source de Mandiant compilé en WebAssembly.
La structure décrite ci-dessous s'appuie sur les travaux publics de rétro-ingénierie de Mandiant (macos-UnifiedLogs) et de Joachim Metz (libyal dtformats). Apple ne documente pas ce format, et les champs signalés comme inconnus dans ces sources le sont aussi ici.
Chunks et préambules
Chaque chunk commence par un préambule de 16 octets : un tag sur 32 bits, un sous-tag sur 32 bits et une taille de données sur 64 bits. Les chunks sont alignés sur 8 octets. Les tags qui comptent :
| Tag | Chunk |
|---|---|
0x1000 | En-tête |
0x600b | Catalogue |
0x600d | Chunkset (compressé) |
0x6001 | Firehose (dans un chunkset) |
0x6002 | Oversize (dans un chunkset) |
0x6003 | Statedump (dans un chunkset) |
0x6004 | Simpledump (dans un chunkset) |
Un fichier commence donc toujours par les octets 00 10 00 00 : c'est ainsi que le parseur le reconnaît, quel que soit son nom.
En-tête
L'en-tête enregistre la base de temps Mach (numérateur et dénominateur), le temps continu au moment de la création du fichier, le décalage de fuseau horaire et l'indicateur d'heure d'été, ainsi que des sous-chunks contenant la version de build (par exemple 25G83), le modèle matériel (Mac14,14), l'UUID de démarrage, le PID de logd et le chemin du fichier de fuseau horaire. L'UUID de démarrage rattache chaque entrée à une session de démarrage et aux bons enregistrements timesync. L'onglet Sources du parseur affiche ces valeurs.
Catalogue
Un catalogue décrit les entrées des chunksets qui le suivent :
- un tableau d'UUID — ceux des binaires qui ont journalisé et celui du cache partagé ;
- une table des chaînes de subsystems et de catégories ;
- des entrées de processus : PID, identifiant utilisateur effectif, index de l'UUID de l'exécutable principal et de celui du cache partagé, UUID supplémentaires (bibliothèques chargées) avec leurs adresses de chargement, et subsystems utilisés par le processus ;
- des descripteurs de sous-chunks : intervalle de temps, taille décompressée et algorithme de compression de chaque chunkset.
Les entrées firehose désignent leur processus par une paire d'identifiants résolue dans cette table, et leur subsystem par un petit index.
Chunksets
Un chunkset est un bloc compressé. La plupart utilisent LZ4 avec l'en-tête de bloc bv41 propre à Apple (bv41- signale un bloc non compressé) ; les versions récentes peuvent aussi utiliser LZBITMAP, que le parseur prend en charge. Une fois décompressé, un chunkset est à nouveau une suite de chunks.
Firehose
Un chunk firehose comporte un préambule avec un temps continu de base, puis des entrées. Chaque entrée possède un type d'activité (log, activity, trace, signpost, loss), un type de journal (Default, Info, Debug, Error, Fault, ou un type de signpost), des indicateurs, un identifiant de thread, un delta temporel et une zone de données. Les indicateurs précisent où se trouve la chaîne de format : dans le fichier uuidtext propre au processus (exécutable principal), dans le cache partagé (dsc), à un décalage absolu, ou relativement à un autre UUID. La zone de données contient les arguments — nombres, chaînes, ou références vers des données privées et des chaînes oversize.
Oversize
Les arguments trop volumineux pour l'entrée sont stockés dans des chunks oversize, identifiés par une référence de données. Ils peuvent se trouver dans un fichier ultérieur à celui de l'entrée qui les référence : c'est pourquoi un parseur doit conserver les données oversize d'un fichier à l'autre et retenter la résolution des entrées en suspens à la fin.
Statedump et simpledump
Les statedumps sont des instantanés qu'un processus écrit à la demande — une plist, un protobuf ou un objet personnalisé doté d'un titre (la « TCC Authorization Cache » en est un). Les simpledumps sont des messages courts journalisés sans chaîne de format par launchd et quelques autres processus.
uuidtext et dsc : le texte manquant
Un fichier uuidtext (/private/var/db/uuidtext/XX/…, où XX est le premier octet de l'UUID et le nom du fichier correspond aux 30 chiffres hexadécimaux restants) commence par la signature 0x66778899, liste des plages de l'espace d'adressage du binaire, contient les chaînes de format correspondantes et se termine par le chemin du binaire. Un fichier dsc (uuidtext/dsc/<32 hex>, signature hcsd) fait de même pour l'ensemble du cache partagé dyld et nomme chacun des frameworks qu'il contient.
Pour restituer un message, le parseur identifie le bon fichier à partir de l'UUID du catalogue et des indicateurs de l'entrée, lit la chaîne de format au décalage enregistré et applique les arguments à la manière de printf : %d, %s, %@, %{public}s, %{private}@ et des décodeurs de type comme %{errno}d, %{uuid_t}.16P ou %{bool}d. Les arguments privés qui n'ont pas été capturés apparaissent sous la forme <private>.
timesync
Les fichiers timesync contiennent, pour chaque UUID de démarrage, un en-tête (signature 0xbbb0, base de temps, heure de démarrage) et des enregistrements associant un temps continu à une heure réelle. L'heure réelle d'une entrée correspond à l'heure de l'enregistrement précédent le plus proche, augmentée du temps continu écoulé multiplié par la base de temps — 125/3 sur Apple silicon, 1/1 sur Intel.
Ce que cela implique en pratique
- Collectez
uuidtext,dscettimesyncavec les fichiers tracev3 (guide de collecte). - Attendez-vous malgré tout à quelques entrées « non résolues » : une chaîne peut manquer dans les fichiers qu'Apple a conservés.
- Comparez les entrées importantes avec
log show. Validé sur une archive réelle, le parseur a restitué à l'identique environ 99 % des messages de type log, activity et state ; seule la présentation des signposts diffère.
Consultez le glossaire pour chaque terme, ou ouvrez vos propres fichiers dans le parseur.