mirror of
https://github.com/golang/go
synced 2024-09-30 08:28:34 -06: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{
|
var builddeps = map[string][]string{
|
||||||
"bufio": {"bytes", "errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
|
"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"},
|
"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"},
|
"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": {"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"},
|
"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/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"},
|
"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": {"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"},
|
"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/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"},
|
"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": {"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/race": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
|
||||||
"internal/singleflight": {"internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
|
"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"},
|
"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": {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
|
||||||
"unicode/utf16": {"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"},
|
"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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"compress/zlib"
|
||||||
"debug/dwarf"
|
"debug/dwarf"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
@ -863,6 +864,22 @@ func (f *File) DWARF() (*dwarf.Data, error) {
|
|||||||
return nil, err
|
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 {
|
for _, r := range f.Sections {
|
||||||
if r.Type != SHT_RELA && r.Type != SHT_REL {
|
if r.Type != SHT_RELA && r.Type != SHT_REL {
|
||||||
continue
|
continue
|
||||||
@ -887,17 +904,23 @@ func (f *File) DWARF() (*dwarf.Data, error) {
|
|||||||
// Don't bother loading others.
|
// Don't bother loading others.
|
||||||
var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil}
|
var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil}
|
||||||
for i, s := range f.Sections {
|
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
|
continue
|
||||||
}
|
}
|
||||||
if _, ok := dat[s.Name[7:]]; !ok {
|
if _, ok := dat[suffix]; !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
b, err := sectionData(i, s)
|
b, err := sectionData(i, s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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"])
|
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) {
|
func TestNoSectionOverlaps(t *testing.T) {
|
||||||
// Ensure 6l outputs sections without overlaps.
|
// Ensure 6l outputs sections without overlaps.
|
||||||
if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" {
|
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": {"L4", "container/list", "database/sql/driver"},
|
||||||
"database/sql/driver": {"L4", "time"},
|
"database/sql/driver": {"L4", "time"},
|
||||||
"debug/dwarf": {"L4"},
|
"debug/dwarf": {"L4"},
|
||||||
"debug/elf": {"L4", "OS", "debug/dwarf"},
|
"debug/elf": {"L4", "OS", "debug/dwarf", "compress/zlib"},
|
||||||
"debug/gosym": {"L4"},
|
"debug/gosym": {"L4"},
|
||||||
"debug/macho": {"L4", "OS", "debug/dwarf"},
|
"debug/macho": {"L4", "OS", "debug/dwarf"},
|
||||||
"debug/pe": {"L4", "OS", "debug/dwarf"},
|
"debug/pe": {"L4", "OS", "debug/dwarf"},
|
||||||
|
Loading…
Reference in New Issue
Block a user