From: Ian Lance Taylor Date: Fri, 3 Mar 2023 22:29:44 +0000 (-0800) Subject: debug/elf: support zstd compression X-Git-Tag: go1.21rc1~857 X-Git-Url: http://www.git.cypherpunks.ru/?a=commitdiff_plain;h=48a1dcb92778a349e13bcb8be10a40047f0cf7d1;p=gostls13.git debug/elf: support zstd compression Test cases added to debug/dwarf because that is where it matters in practice. The new test binary line-gcc-zstd.elf built with gcc -g -no-pie -Wl,--compress-debug-sections=zstd line[12].c using gcc (Debian 12.2.0-10) 12.2.0 with a development version of the GNU binutils. Fixes #55107 Change-Id: I48507c96902e1f83a174e5647b5cc403d965b52b Reviewed-on: https://go-review.googlesource.com/c/go/+/473256 TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Auto-Submit: Ian Lance Taylor Reviewed-by: Than McIntosh --- diff --git a/api/next/55107.txt b/api/next/55107.txt new file mode 100644 index 0000000000..234f030ffd --- /dev/null +++ b/api/next/55107.txt @@ -0,0 +1,2 @@ +pkg debug/elf, const COMPRESS_ZSTD = 2 #55107 +pkg debug/elf, const COMPRESS_ZSTD CompressionType #55107 diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 3a455b9677..e06991d726 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -78,6 +78,7 @@ var bootstrapDirs = []string{ "internal/types/errors", "internal/unsafeheader", "internal/xcoff", + "internal/zstd", "math/big", "math/bits", "sort", diff --git a/src/debug/dwarf/entry_test.go b/src/debug/dwarf/entry_test.go index 4e96dbfc1d..1ce1c98f60 100644 --- a/src/debug/dwarf/entry_test.go +++ b/src/debug/dwarf/entry_test.go @@ -69,6 +69,12 @@ func TestReaderSeek(t *testing.T) { {0x40117e, nil}, } testRanges(t, "testdata/line-clang-dwarf5.elf", want) + + want = []wantRange{ + {0x401126, [][2]uint64{{0x401126, 0x40116a}}}, + {0x40116a, [][2]uint64{{0x40116a, 0x401180}}}, + } + testRanges(t, "testdata/line-gcc-zstd.elf", want) } func TestRangesSection(t *testing.T) { @@ -156,6 +162,15 @@ func TestReaderRanges(t *testing.T) { {"f2", [][2]uint64{{0x401180, 0x401197}}}, }, }, + { + "testdata/line-gcc-zstd.elf", + subprograms{ + {"f2", nil}, + {"main", [][2]uint64{{0x40114b, 0x40116a}}}, + {"f1", [][2]uint64{{0x401126, 0x40114b}}}, + {"f2", [][2]uint64{{0x40116a, 0x401180}}}, + }, + }, } for _, test := range tests { diff --git a/src/debug/dwarf/line_test.go b/src/debug/dwarf/line_test.go index 163fc3bbb9..e947d99ebb 100644 --- a/src/debug/dwarf/line_test.go +++ b/src/debug/dwarf/line_test.go @@ -48,6 +48,44 @@ func TestLineELFGCC(t *testing.T) { testLineTable(t, want, files, elfData(t, "testdata/line-gcc.elf")) } +func TestLineELFGCCZstd(t *testing.T) { + // Generated by: + // # gcc --version | head -n1 + // gcc (Debian 12.2.0-10) 12.2.0 + // # gcc -g -no-pie -Wl,--compress-debug-sections=zstd line*.c + + zfile1H := &LineFile{Name: "/home/iant/go/src/debug/dwarf/testdata/line1.h"} + zfile1C := &LineFile{Name: "/home/iant/go/src/debug/dwarf/testdata/line1.c"} + zfile2C := &LineFile{Name: "/home/iant/go/src/debug/dwarf/testdata/line2.c"} + + // Line table based on readelf --debug-dump=rawline,decodedline + want := []LineEntry{ + {Address: 0x401126, File: zfile1H, Line: 2, Column: 1, IsStmt: true}, + {Address: 0x40112a, File: zfile1H, Line: 5, Column: 8, IsStmt: true}, + {Address: 0x401131, File: zfile1H, Line: 5, Column: 2, IsStmt: true}, + {Address: 0x401133, File: zfile1H, Line: 6, Column: 10, IsStmt: true, Discriminator: 3}, + {Address: 0x40113d, File: zfile1H, Line: 5, Column: 22, IsStmt: true, Discriminator: 3}, + {Address: 0x401141, File: zfile1H, Line: 5, Column: 15, IsStmt: true, Discriminator: 1}, + {Address: 0x401147, File: zfile1H, Line: 7, Column: 1, IsStmt: true}, + {Address: 0x40114b, File: zfile1C, Line: 6, Column: 1, IsStmt: true}, + {Address: 0x40114f, File: zfile1C, Line: 7, Column: 2, IsStmt: true}, + {Address: 0x401159, File: zfile1C, Line: 8, Column: 2, IsStmt: true}, + {Address: 0x401168, File: zfile1C, Line: 9, Column: 1, IsStmt: true}, + {Address: 0x40116a, EndSequence: true}, + + {Address: 0x40116a, File: zfile2C, Line: 4, Column: 1, IsStmt: true}, + {Address: 0x40116e, File: zfile2C, Line: 5, Column: 2, IsStmt: true}, + {Address: 0x40117d, File: zfile2C, Line: 6, Column: 1, IsStmt: true}, + {Address: 0x401180, EndSequence: true}, + } + files := [][]*LineFile{ + {zfile1C, zfile1H, zfile1C}, + {zfile2C, zfile2C}, + } + + testLineTable(t, want, files, elfData(t, "testdata/line-gcc-zstd.elf")) +} + func TestLineGCCWindows(t *testing.T) { // Generated by: // > gcc --version @@ -277,7 +315,7 @@ func testLineTable(t *testing.T, want []LineEntry, files [][]*LineFile, d *Data) } // Compare line tables. - if !compareLines(got, want) { + if !compareLines(t, got, want) { t.Log("Line tables do not match. Got:") dumpLines(t, got) t.Log("Want:") @@ -312,8 +350,10 @@ func dumpFiles(t *testing.T, files []*LineFile) { } } -func compareLines(a, b []LineEntry) bool { +func compareLines(t *testing.T, a, b []LineEntry) bool { + t.Helper() if len(a) != len(b) { + t.Errorf("len(a) == %d, len(b) == %d", len(a), len(b)) return false } @@ -326,11 +366,13 @@ func compareLines(a, b []LineEntry) bool { continue } if al.File.Name != bl.File.Name { + t.Errorf("%d: name %v != name %v", i, al.File.Name, bl.File.Name) return false } al.File = nil bl.File = nil if al != bl { + t.Errorf("%d: %#v != %#v", i, al, bl) return false } } diff --git a/src/debug/dwarf/testdata/line-gcc-zstd.elf b/src/debug/dwarf/testdata/line-gcc-zstd.elf new file mode 100644 index 0000000000..45cbe72039 Binary files /dev/null and b/src/debug/dwarf/testdata/line-gcc-zstd.elf differ diff --git a/src/debug/elf/elf.go b/src/debug/elf/elf.go index ccb7e5a893..8b064bd880 100644 --- a/src/debug/elf/elf.go +++ b/src/debug/elf/elf.go @@ -728,6 +728,7 @@ type CompressionType int const ( COMPRESS_ZLIB CompressionType = 1 /* ZLIB compression. */ + COMPRESS_ZSTD CompressionType = 2 /* ZSTD compression. */ COMPRESS_LOOS CompressionType = 0x60000000 /* First OS-specific. */ COMPRESS_HIOS CompressionType = 0x6fffffff /* Last OS-specific. */ COMPRESS_LOPROC CompressionType = 0x70000000 /* First processor-specific type. */ @@ -736,6 +737,7 @@ const ( var compressionStrings = []intName{ {1, "COMPRESS_ZLIB"}, + {2, "COMPRESS_ZSTD"}, {0x60000000, "COMPRESS_LOOS"}, {0x6fffffff, "COMPRESS_HIOS"}, {0x70000000, "COMPRESS_LOPROC"}, diff --git a/src/debug/elf/elf_test.go b/src/debug/elf/elf_test.go index 623a4147a7..0350d53050 100644 --- a/src/debug/elf/elf_test.go +++ b/src/debug/elf/elf_test.go @@ -38,7 +38,7 @@ var nameTests = []nameTest{ {R_SPARC_GOT22, "R_SPARC_GOT22"}, {ET_LOOS + 5, "ET_LOOS+5"}, {ProgFlag(0x50), "0x50"}, - {COMPRESS_ZLIB + 1, "COMPRESS_ZLIB+1"}, + {COMPRESS_ZLIB + 2, "COMPRESS_ZSTD+1"}, } func TestNames(t *testing.T) { diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go index 04737e6b2f..7485337905 100644 --- a/src/debug/elf/file.go +++ b/src/debug/elf/file.go @@ -23,6 +23,7 @@ import ( "errors" "fmt" "internal/saferio" + "internal/zstd" "io" "os" "strings" @@ -164,6 +165,10 @@ func (s *Section) Open() io.ReadSeeker { switch s.compressionType { case COMPRESS_ZLIB: zrd = zlib.NewReader + case COMPRESS_ZSTD: + zrd = func(r io.Reader) (io.ReadCloser, error) { + return io.NopCloser(zstd.NewReader(r)), nil + } } if zrd == nil { diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 24ad2def85..4415b92a29 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -251,7 +251,7 @@ var depsRules = ` < index/suffixarray; # executable parsing - FMT, encoding/binary, compress/zlib, internal/saferio + FMT, encoding/binary, compress/zlib, internal/saferio, internal/zstd < runtime/debug < debug/dwarf < debug/elf, debug/gosym, debug/macho, debug/pe, debug/plan9obj, internal/xcoff