After the header the file is a sequence of objects, each starting on an 8-byte boundary and padded to a multiple of 8. Objects refer to each other by their offset in the file. All numbers are little-endian.
Object header
| Offset | Size | Name | Description |
|---|---|---|---|
0 | 1 | type | See types. |
1 | 1 | flags | For data objects, how the payload is compressed: 0x1 XZ, 0x2 LZ4, 0x4 Zstandard; 0 not compressed. |
2 | 6 | reserved | Zeros. |
8 | 8 | size | The object’s size, header included, without the padding. |
| Type | Object |
|---|---|
| 0 | Unused |
| 1 | Data |
| 2 | Field |
| 3 | Entry |
| 4 | Data hash table |
| 5 | Field hash table |
| 6 | Entry array |
| 7 | Tag |
Data object
One FIELD=value pair, such as MESSAGE=Started session 3.,
stored once and shared by every entry that has it.
| Offset | Size | Name | Description |
|---|---|---|---|
16 | 8 | hash | Hash of the (uncompressed) payload. |
24 | 8 | next_hash_offset | Next data object in the same hash table bucket. |
32 | 8 | next_field_offset | Next data object with the same field name. |
40 | 8 | entry_offset | The first entry that uses this data, stored inline. |
48 | 8 | entry_array_offset | An entry array listing the other entries that use it. |
56 | 8 | n_entries | How many entries use it. |
64 | varies | payload | Regular files: the payload, FIELD=value, possibly compressed. |
64 | 4 + 4 | tail_entry_array_offset, tail_entry_array_n_entries | Compact files: the last entry array for this data and how full it is; the payload then starts at 72. |
Field object
| Offset | Size | Name | Description |
|---|---|---|---|
16 | 8 | hash | Hash of the field name. |
24 | 8 | next_hash_offset | Next field object in the same bucket. |
32 | 8 | head_data_offset | The first data object with this field. |
40 | varies | payload | The field name, such as _SYSTEMD_UNIT. |
Entry object
One log entry.
| Offset | Size | Name | Description |
|---|---|---|---|
16 | 8 | seqnum | Sequence number, rising through the series. |
24 | 8 | realtime | Wall-clock time, microseconds since 1970. |
32 | 8 | monotonic | Microseconds since boot. |
40 | 16 | boot_id | The boot the monotonic time belongs to. |
56 | 8 | xor_hash | XOR of the Jenkins hashes of all its data payloads, to spot duplicates when merging files. |
64 | varies | items | One per data object: regular files 16 bytes (object_offset and hash, 8 each); compact files 4 bytes (object_offset). |
Hash tables
The data and field hash tables are arrays of 16-byte buckets after the object header:
head_hash_offset and tail_hash_offset, the first and last
object in the bucket’s chain. An object is in bucket hash mod number of buckets.
The hash is SipHash-2-4 keyed with file_id when the header’s
KEYED_HASH flag is set, and Jenkins lookup3
(hashlittle2, 64-bit) otherwise; the entry’s xor_hash always
uses Jenkins.
Entry array object
| Offset | Size | Name | Description |
|---|---|---|---|
16 | 8 | next_entry_array_offset | The next array of the chain; 0 at the end. |
24 | varies | items | Entry object offsets in order: 8 bytes each, or 4 in compact files. Unused slots are 0. |
The header’s entry_array_offset starts the chain of all entries; each
data object has its own chain for the entries that use it. Arrays usually double in
size along a chain.
Tag object
Used by Forward Secure Sealing, which lets a verifier detect later tampering.
| Offset | Size | Name | Description |
|---|---|---|---|
16 | 8 | seqnum | Sequence number of the tag. |
24 | 8 | epoch | The sealing key’s epoch. |
32 | 32 | tag | HMAC-SHA256 over the objects since the previous tag. |