Skip to content

Commit 440b440

Browse files
aarzilliderekparker
authored andcommitted
proc: support GNU compressed debug sections (go1.11 support)
Go1.11 switched to the zlib-gnu compression format for debug sections. Change proc and and a test in dwarf/line to support this change. Also deletes some dead code from pkg/proc/bininfo.go that hadn't been used in a long time.
1 parent de7b8c6 commit 440b440

File tree

4 files changed

+157
-184
lines changed

4 files changed

+157
-184
lines changed

pkg/dwarf/godwarf/sections.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package godwarf
2+
3+
import (
4+
"bytes"
5+
"compress/zlib"
6+
"debug/elf"
7+
"debug/macho"
8+
"debug/pe"
9+
"encoding/binary"
10+
"fmt"
11+
"io"
12+
)
13+
14+
// GetDebugSectionElf returns the data contents of the specified debug
15+
// section, decompressing it if it is compressed.
16+
// For example GetDebugSectionElf("line") will return the contents of
17+
// .debug_line, if .debug_line doesn't exist it will try to return the
18+
// decompressed contents of .zdebug_line.
19+
func GetDebugSectionElf(f *elf.File, name string) ([]byte, error) {
20+
sec := f.Section(".debug_" + name)
21+
if sec != nil {
22+
return sec.Data()
23+
}
24+
sec = f.Section(".zdebug_" + name)
25+
if sec == nil {
26+
return nil, fmt.Errorf("could not find .debug_%s section", name)
27+
}
28+
b, err := sec.Data()
29+
if err != nil {
30+
return nil, err
31+
}
32+
return decompressMaybe(b)
33+
}
34+
35+
// GetDebugSectionPE returns the data contents of the specified debug
36+
// section, decompressing it if it is compressed.
37+
// For example GetDebugSectionPE("line") will return the contents of
38+
// .debug_line, if .debug_line doesn't exist it will try to return the
39+
// decompressed contents of .zdebug_line.
40+
func GetDebugSectionPE(f *pe.File, name string) ([]byte, error) {
41+
sec := f.Section(".debug_" + name)
42+
if sec != nil {
43+
return peSectionData(sec)
44+
}
45+
sec = f.Section(".zdebug_" + name)
46+
if sec == nil {
47+
return nil, fmt.Errorf("could not find .debug_%s section", name)
48+
}
49+
b, err := peSectionData(sec)
50+
if err != nil {
51+
return nil, err
52+
}
53+
return decompressMaybe(b)
54+
}
55+
56+
func peSectionData(sec *pe.Section) ([]byte, error) {
57+
b, err := sec.Data()
58+
if err != nil {
59+
return nil, err
60+
}
61+
if 0 < sec.VirtualSize && sec.VirtualSize < sec.Size {
62+
b = b[:sec.VirtualSize]
63+
}
64+
return b, nil
65+
}
66+
67+
// GetDebugSectionMacho returns the data contents of the specified debug
68+
// section, decompressing it if it is compressed.
69+
// For example GetDebugSectionMacho("line") will return the contents of
70+
// __debug_line, if __debug_line doesn't exist it will try to return the
71+
// decompressed contents of __zdebug_line.
72+
func GetDebugSectionMacho(f *macho.File, name string) ([]byte, error) {
73+
sec := f.Section("__debug_" + name)
74+
if sec != nil {
75+
return sec.Data()
76+
}
77+
sec = f.Section("__zdebug_" + name)
78+
if sec == nil {
79+
return nil, fmt.Errorf("could not find .debug_%s section", name)
80+
}
81+
b, err := sec.Data()
82+
if err != nil {
83+
return nil, err
84+
}
85+
return decompressMaybe(b)
86+
}
87+
88+
func decompressMaybe(b []byte) ([]byte, error) {
89+
if len(b) < 12 || string(b[:4]) != "ZLIB" {
90+
// not compressed
91+
return b, nil
92+
}
93+
94+
dlen := binary.BigEndian.Uint64(b[4:12])
95+
dbuf := make([]byte, dlen)
96+
r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
97+
if err != nil {
98+
return nil, err
99+
}
100+
if _, err := io.ReadFull(r, dbuf); err != nil {
101+
return nil, err
102+
}
103+
if err := r.Close(); err != nil {
104+
return nil, err
105+
}
106+
return dbuf, nil
107+
}

pkg/dwarf/line/line_parser_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"testing"
1515
"time"
1616

17+
"github.com/derekparker/delve/pkg/dwarf/godwarf"
1718
"github.com/pkg/profile"
1819
)
1920

@@ -34,24 +35,23 @@ func grabDebugLineSection(p string, t *testing.T) []byte {
3435

3536
ef, err := elf.NewFile(f)
3637
if err == nil {
37-
data, _ := ef.Section(".debug_line").Data()
38+
data, _ := godwarf.GetDebugSectionElf(ef, "line")
3839
return data
3940
}
4041

4142
pf, err := pe.NewFile(f)
4243
if err == nil {
43-
sec := pf.Section(".debug_line")
44-
data, _ := sec.Data()
45-
if 0 < sec.VirtualSize && sec.VirtualSize < sec.Size {
46-
return data[:sec.VirtualSize]
47-
}
44+
data, _ := godwarf.GetDebugSectionPE(pf, "line")
4845
return data
4946
}
5047

51-
mf, _ := macho.NewFile(f)
52-
data, _ := mf.Section("__debug_line").Data()
48+
mf, err := macho.NewFile(f)
49+
if err == nil {
50+
data, _ := godwarf.GetDebugSectionMacho(mf, "line")
51+
return data
52+
}
5353

54-
return data
54+
return nil
5555
}
5656

5757
const (

0 commit comments

Comments
 (0)