mirror of
https://github.com/Binject/debug
synced 2026-06-08 10:28:33 +00: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:
+26
-3
@@ -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
Binary file not shown.
Reference in New Issue
Block a user