Description
This issue is the root cause of parca-dev/parca#5291.
What's the issue
Calling godwarf.LoadTree
with certain offsets in certain binaries can result in incorrect DWARF entries being read.
How to reproduce
First, download and decompress ClickHouse binary:
curl -LO https://s3.amazonaws.com/clickhouse-builds/24.10/2e054d555719f509b96e0cfea4d5f5819c69a61f/package_release/clickhouse
chmod +x clickhouse
./clickhouse --version
Then, compile this:
import (
"debug/dwarf"
"debug/elf"
"fmt"
"github.com/go-delve/delve/pkg/dwarf/godwarf"
)
func main() {
path := "clickhouse"
f, err := elf.Open(path)
if err != nil {
print(err)
return
}
d, err := f.DWARF()
if err != nil {
print(err)
return
}
// DWARF info reader
reader := d.Reader()
_, err = godwarf.LoadTree(0x139d6483, d, 0)
if err != nil {
fmt.Printf("errored: %v\n", err)
}
You will get the following output:
errored: invalid rnglist offset 2858131463 (max 636512)
If, instead, you change the offset passed to LoadTree
to 0x139d02d2
(the start of the compilation unit), the example works properly. Also, by print-debugging, I have checked that the offset that is read for the problematic entry matches the one outputted by llvm-dwarfdump
.
Why does this happen
According to this comment in debug/dwarf
, Reader.Next()
sets the current unit when it passes by a compilation unit DWARF entry, and then uses the offset of the CU to adjust the rnglist offset when encountering one. If Seek()
is called directly to an offset that is after the compilation unit DWARF entry, that information is not set and the offset is incorrect.
How to solve this
Probably, by finding the CU for an offset in the first call and then reusing the reader across recursive calls.
Activity