mirror of
https://github.com/golang/go
synced 2024-11-18 03:04:45 -07:00
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 <iant@golang.org> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
606d9a7e18
commit
e1544d3bb6
7
src/cmd/dist/deps.go
vendored
7
src/cmd/dist/deps.go
vendored
@ -5,11 +5,13 @@ package main
|
||||
var builddeps = map[string][]string{
|
||||
"bufio": {"bytes", "errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
|
||||
"bytes": {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
|
||||
"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"},
|
||||
"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"},
|
||||
"container/heap": {"runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort"},
|
||||
"crypto": {"errors", "hash", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
|
||||
"crypto/sha1": {"crypto", "errors", "hash", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
|
||||
"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"},
|
||||
"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"},
|
||||
"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"},
|
||||
"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"},
|
||||
"encoding": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
|
||||
"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{
|
||||
"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"},
|
||||
"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"},
|
||||
"hash": {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
|
||||
"hash/adler32": {"errors", "hash", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
|
||||
"internal/race": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
|
||||
"internal/singleflight": {"internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
|
||||
"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{
|
||||
"unicode": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
|
||||
"unicode/utf16": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
|
||||
"unicode/utf8": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
|
||||
"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"},
|
||||
"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"},
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ package elf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"debug/dwarf"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
@ -863,6 +864,22 @@ func (f *File) DWARF() (*dwarf.Data, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(b) >= 12 && string(b[:4]) == "ZLIB" {
|
||||
dlen := binary.BigEndian.Uint64(b[4:12])
|
||||
dbuf := make([]byte, dlen)
|
||||
r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := io.ReadFull(r, dbuf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = dbuf
|
||||
}
|
||||
|
||||
for _, r := range f.Sections {
|
||||
if r.Type != SHT_RELA && r.Type != SHT_REL {
|
||||
continue
|
||||
@ -887,17 +904,23 @@ func (f *File) DWARF() (*dwarf.Data, error) {
|
||||
// Don't bother loading others.
|
||||
var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil}
|
||||
for i, s := range f.Sections {
|
||||
if !strings.HasPrefix(s.Name, ".debug_") {
|
||||
suffix := ""
|
||||
switch {
|
||||
case strings.HasPrefix(s.Name, ".debug_"):
|
||||
suffix = s.Name[7:]
|
||||
case strings.HasPrefix(s.Name, ".zdebug_"):
|
||||
suffix = s.Name[8:]
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if _, ok := dat[s.Name[7:]]; !ok {
|
||||
if _, ok := dat[suffix]; !ok {
|
||||
continue
|
||||
}
|
||||
b, err := sectionData(i, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dat[s.Name[7:]] = b
|
||||
dat[suffix] = b
|
||||
}
|
||||
|
||||
d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, nil, dat["str"])
|
||||
|
@ -514,6 +514,34 @@ func TestDWARFRelocations(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompressedDWARF(t *testing.T) {
|
||||
// Test file built with GCC 4.8.4 and as 2.24 using:
|
||||
// gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c
|
||||
f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
dwarf, err := f.DWARF()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
reader := dwarf.Reader()
|
||||
n := 0
|
||||
for {
|
||||
entry, err := reader.Next()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
n++
|
||||
}
|
||||
if n != 18 {
|
||||
t.Fatalf("want %d DWARF entries, got %d", 18, n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoSectionOverlaps(t *testing.T) {
|
||||
// Ensure 6l outputs sections without overlaps.
|
||||
if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" {
|
||||
|
BIN
src/debug/elf/testdata/zdebug-test-gcc484-x86-64.obj
vendored
Normal file
BIN
src/debug/elf/testdata/zdebug-test-gcc484-x86-64.obj
vendored
Normal file
Binary file not shown.
@ -218,7 +218,7 @@ var pkgDeps = map[string][]string{
|
||||
"database/sql": {"L4", "container/list", "database/sql/driver"},
|
||||
"database/sql/driver": {"L4", "time"},
|
||||
"debug/dwarf": {"L4"},
|
||||
"debug/elf": {"L4", "OS", "debug/dwarf"},
|
||||
"debug/elf": {"L4", "OS", "debug/dwarf", "compress/zlib"},
|
||||
"debug/gosym": {"L4"},
|
||||
"debug/macho": {"L4", "OS", "debug/dwarf"},
|
||||
"debug/pe": {"L4", "OS", "debug/dwarf"},
|
||||
|
Loading…
Reference in New Issue
Block a user