Skip to content

Commit e1544d3

Browse files
committed
dwbug/elf: support old-style compressed DWARF
GCC and LLVM support zlib-compressing DWARF debug sections (and there's some evidence that this may be happening by default in some circumstances now). Add support for reading compressed DWARF sections. Since ELF relocations apply to the decompressed data, decompression is done before applying relocations. Since relcations are applied by debug/elf, decompression must also be handled there. Note that this is different from compressed ELF sections, which is a more general mechanism used by very recent versions of GCC. Updates #11773. Change-Id: I3f4bf1b04d0802cc1e8fcb7c2a5fcf6c467c5089 Reviewed-on: https://go-review.googlesource.com/17340 Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Austin Clements <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent 606d9a7 commit e1544d3

File tree

5 files changed

+60
-6
lines changed

5 files changed

+60
-6
lines changed

src/cmd/dist/deps.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ package main
55
var builddeps = map[string][]string{
66
"bufio": {"bytes", "errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
77
"bytes": {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
8+
"compress/flate": {"bufio", "bytes", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
9+
"compress/zlib": {"bufio", "bytes", "compress/flate", "errors", "fmt", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
810
"container/heap": {"runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort"},
911
"crypto": {"errors", "hash", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
1012
"crypto/sha1": {"crypto", "errors", "hash", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
1113
"debug/dwarf": {"encoding/binary", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
12-
"debug/elf": {"bytes", "debug/dwarf", "encoding/binary", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
14+
"debug/elf": {"bufio", "bytes", "compress/flate", "compress/zlib", "debug/dwarf", "encoding/binary", "errors", "fmt", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
1315
"debug/macho": {"bytes", "debug/dwarf", "encoding/binary", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
1416
"encoding": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
1517
"encoding/base64": {"errors", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
@@ -25,6 +27,7 @@ var builddeps = map[string][]string{
2527
"go/scanner": {"bytes", "errors", "fmt", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
2628
"go/token": {"errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
2729
"hash": {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
30+
"hash/adler32": {"errors", "hash", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
2831
"internal/race": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
2932
"internal/singleflight": {"internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
3033
"internal/syscall/windows": {"errors", "internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "unicode/utf16"},
@@ -57,5 +60,5 @@ var builddeps = map[string][]string{
5760
"unicode": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
5861
"unicode/utf16": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
5962
"unicode/utf8": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
60-
"cmd/go": {"bufio", "bytes", "container/heap", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "internal/race", "internal/singleflight", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
63+
"cmd/go": {"bufio", "bytes", "compress/flate", "compress/zlib", "container/heap", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/singleflight", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
6164
}

src/debug/elf/file.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package elf
77

88
import (
99
"bytes"
10+
"compress/zlib"
1011
"debug/dwarf"
1112
"encoding/binary"
1213
"errors"
@@ -863,6 +864,22 @@ func (f *File) DWARF() (*dwarf.Data, error) {
863864
return nil, err
864865
}
865866

867+
if len(b) >= 12 && string(b[:4]) == "ZLIB" {
868+
dlen := binary.BigEndian.Uint64(b[4:12])
869+
dbuf := make([]byte, dlen)
870+
r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
871+
if err != nil {
872+
return nil, err
873+
}
874+
if _, err := io.ReadFull(r, dbuf); err != nil {
875+
return nil, err
876+
}
877+
if err := r.Close(); err != nil {
878+
return nil, err
879+
}
880+
b = dbuf
881+
}
882+
866883
for _, r := range f.Sections {
867884
if r.Type != SHT_RELA && r.Type != SHT_REL {
868885
continue
@@ -887,17 +904,23 @@ func (f *File) DWARF() (*dwarf.Data, error) {
887904
// Don't bother loading others.
888905
var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil}
889906
for i, s := range f.Sections {
890-
if !strings.HasPrefix(s.Name, ".debug_") {
907+
suffix := ""
908+
switch {
909+
case strings.HasPrefix(s.Name, ".debug_"):
910+
suffix = s.Name[7:]
911+
case strings.HasPrefix(s.Name, ".zdebug_"):
912+
suffix = s.Name[8:]
913+
default:
891914
continue
892915
}
893-
if _, ok := dat[s.Name[7:]]; !ok {
916+
if _, ok := dat[suffix]; !ok {
894917
continue
895918
}
896919
b, err := sectionData(i, s)
897920
if err != nil {
898921
return nil, err
899922
}
900-
dat[s.Name[7:]] = b
923+
dat[suffix] = b
901924
}
902925

903926
d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, nil, dat["str"])

src/debug/elf/file_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,34 @@ func TestDWARFRelocations(t *testing.T) {
514514
}
515515
}
516516

517+
func TestCompressedDWARF(t *testing.T) {
518+
// Test file built with GCC 4.8.4 and as 2.24 using:
519+
// gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c
520+
f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj")
521+
if err != nil {
522+
t.Fatal(err)
523+
}
524+
dwarf, err := f.DWARF()
525+
if err != nil {
526+
t.Fatal(err)
527+
}
528+
reader := dwarf.Reader()
529+
n := 0
530+
for {
531+
entry, err := reader.Next()
532+
if err != nil {
533+
t.Fatal(err)
534+
}
535+
if entry == nil {
536+
break
537+
}
538+
n++
539+
}
540+
if n != 18 {
541+
t.Fatalf("want %d DWARF entries, got %d", 18, n)
542+
}
543+
}
544+
517545
func TestNoSectionOverlaps(t *testing.T) {
518546
// Ensure 6l outputs sections without overlaps.
519547
if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" {
Binary file not shown.

src/go/build/deps_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ var pkgDeps = map[string][]string{
218218
"database/sql": {"L4", "container/list", "database/sql/driver"},
219219
"database/sql/driver": {"L4", "time"},
220220
"debug/dwarf": {"L4"},
221-
"debug/elf": {"L4", "OS", "debug/dwarf"},
221+
"debug/elf": {"L4", "OS", "debug/dwarf", "compress/zlib"},
222222
"debug/gosym": {"L4"},
223223
"debug/macho": {"L4", "OS", "debug/dwarf"},
224224
"debug/pe": {"L4", "OS", "debug/dwarf"},

0 commit comments

Comments
 (0)