lidia/README.md
Lidia is a binary format for efficient lookup of symbols of a binary by virtual address.
The Lidia format achieves its performance through a carefully designed architecture:
This design makes Lidia particularly well-suited for applications that need to perform many address lookups, such as symbolizing profiles with thousands of samples.
go get github.com/grafana/pyroscope/lidia
Lidia uses a binary format with the following sections:
The Lidia file format consists of the following sections in order:
The header contains metadata about the file and its sections:
| Offset | Size | Description |
|---|---|---|
| 0x00 | 4 | Magic number: [0x2e, 0x64, 0x69, 0x61] (".dia") |
| 0x04 | 4 | Version number (currently 1) |
| 0x08 | 32 | VA Table Header |
| 0x28 | 32 | Range Table Header |
| 0x48 | 24 | Strings Table Header |
| 0x60 | 32 | Line Tables Header |
| Offset | Size | Description |
|---|---|---|
| 0x00 | 8 | Entry size (4 or 8 bytes) |
| 0x08 | 8 | Number of entries |
| 0x10 | 8 | Offset to table data |
| 0x18 | 4 | CRC32C checksum |
| 0x1C | 4 | (reserved) |
| Offset | Size | Description |
|---|---|---|
| 0x00 | 8 | Field size (4 or 8 bytes) |
| 0x08 | 8 | Number of entries |
| 0x10 | 8 | Offset to table data |
| 0x18 | 4 | CRC32C checksum |
| 0x1C | 4 | (reserved) |
| Offset | Size | Description |
|---|---|---|
| 0x00 | 8 | Size of strings data |
| 0x08 | 8 | Offset to table data |
| 0x10 | 4 | CRC32C checksum |
| 0x14 | 4 | (reserved) |
| Offset | Size | Description |
|---|---|---|
| 0x00 | 8 | Field size (2 or 4 bytes) |
| 0x08 | 8 | Number of entries |
| 0x10 | 8 | Offset to table data |
| 0x18 | 4 | CRC32C checksum |
| 0x1C | 4 | (reserved) |
Follows immediately after the header at offset 0x80. Contains virtual addresses (VAs) of functions, sorted in ascending order.
Follows after the VA Table. Contains information about each function range. Each entry contains 8 fields:
| Field | Description |
|---|---|
| length | Length of the function in bytes |
| depth | Inlining depth (0 for non-inlined functions) |
| funcOffset | Offset into the Strings Table for the function name |
| fileOffset | Offset into the Strings Table for the source file path |
| lineTable | {idx, count} Reference to Line Table entries |
| callFile | Offset into the Strings Table for the call site file path |
| callLine | Line number at the call site |
Each field is either 4 or 8 bytes, as specified in the Range Table Header.
Follows after the Range Table. Contains null-terminated strings referenced by the Range Table.
Follows after the Strings Table. Contains line number information for functions. Each entry contains two fields:
| Field | Description |
|---|---|
| Offset | Offset within the function |
| LineNumber | Source line number at this offset |
Each field is either 2 or 4 bytes, as specified in the Line Tables Header.
If enabled with WithCRC(), each section has a CRC32C checksum for data integrity validation.
The checksums are calculated using the Castagnoli polynomial.
import "github.com/grafana/pyroscope/lidia"
// Open a lidia file
file, err := os.Open("symbolization.lidia")
if err != nil {
log.Fatal(err)
}
defer file.Close()
table, err := lidia.OpenReader(file, lidia.WithCRC())
if err != nil {
log.Fatal(err)
}
defer table.Close()
// Look up a function symbol by address
frames, err := table.Lookup(0x408ed0)
if err != nil {
log.Fatal(err)
}
for _, frame := range frames {
fmt.Printf("Function: %s\n", frame.FunctionName)
if frame.SourceFile != "" {
fmt.Printf(" File: %s:%d\n", frame.SourceFile, frame.SourceLine)
}
}
// Create from an executable file
err := lidia.CreateLidia("path/to/executable", "output.lidia",
lidia.WithCRC(), lidia.WithLines(), lidia.WithFiles())
if err != nil {
log.Fatal(err)
}
// Or from an already opened ELF file
elfFile, err := elf.Open("path/to/executable")
if err != nil {
log.Fatal(err)
}
defer elfFile.Close()
output, err := os.Create("output.lidia")
if err != nil {
log.Fatal(err)
}
defer output.Close()
err = lidia.CreateLidiaFromELF(elfFile, output,
lidia.WithCRC(), lidia.WithLines(), lidia.WithFiles())
if err != nil {
log.Fatal(err)
}
This module is currently in development (v0.x). The API may change until v1.0.0 is released.
We follow semantic versioning.
See the LICENSE file for details.