From 315e5c99d868bffad5ac75871e486d6f3a625f23 Mon Sep 17 00:00:00 2001 From: Alex Brainman Date: Mon, 6 Jul 2015 15:52:33 +1000 Subject: [PATCH] debug/pe: truncate pe sections to their size in memory Section.Data returns disk section data, but those are rounded up to some predefined value. Processing these as is confuses dwarf parser because of garbage at the end. Truncate Section.Data as per memory section description. Sometimes dwarf sections have memory section size of 0 (for pe object files). Keep those to their disk size. Fixes #11608 Change-Id: I8de0a2271201a24aa9ac8dac44f1e9c8a9285183 Reviewed-on: https://go-review.googlesource.com/11950 Reviewed-by: Ian Lance Taylor --- src/debug/pe/file.go | 3 + src/debug/pe/file_test.go | 116 ++++++++++++++++++++++++++++++-------- 2 files changed, 94 insertions(+), 25 deletions(-) diff --git a/src/debug/pe/file.go b/src/debug/pe/file.go index 844dffc888..3df4ae7368 100644 --- a/src/debug/pe/file.go +++ b/src/debug/pe/file.go @@ -310,6 +310,9 @@ func (f *File) DWARF() (*dwarf.Data, error) { if err != nil && uint32(len(b)) < s.Size { return nil, err } + if 0 < s.VirtualSize && s.VirtualSize < s.Size { + b = b[:s.VirtualSize] + } dat[i] = b } diff --git a/src/debug/pe/file_test.go b/src/debug/pe/file_test.go index 0d73969bca..316a569ede 100644 --- a/src/debug/pe/file_test.go +++ b/src/debug/pe/file_test.go @@ -5,24 +5,30 @@ package pe import ( + "debug/dwarf" + "io/ioutil" + "os" + "os/exec" + "path/filepath" "reflect" + "runtime" "testing" ) type fileTest struct { - file string - hdr FileHeader - opthdr interface{} - sections []*SectionHeader - symbols []*Symbol + file string + hdr FileHeader + opthdr interface{} + sections []*SectionHeader + symbols []*Symbol + hasNoDwarfInfo bool } var fileTests = []fileTest{ { - "testdata/gcc-386-mingw-obj", - FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104}, - nil, - []*SectionHeader{ + file: "testdata/gcc-386-mingw-obj", + hdr: FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104}, + sections: []*SectionHeader{ {".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020}, {".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264}, {".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328}, @@ -36,7 +42,7 @@ var fileTests = []fileTest{ {".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832}, {".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832}, }, - []*Symbol{ + symbols: []*Symbol{ {".file", 0x0, -2, 0x0, 0x67}, {"_main", 0x0, 1, 0x20, 0x2}, {".text", 0x0, 1, 0x0, 0x3}, @@ -56,9 +62,9 @@ var fileTests = []fileTest{ }, }, { - "testdata/gcc-386-mingw-exec", - FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107}, - &OptionalHeader32{ + file: "testdata/gcc-386-mingw-exec", + hdr: FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107}, + opthdr: &OptionalHeader32{ 0x10b, 0x2, 0x38, 0xe00, 0x1a00, 0x200, 0x1160, 0x1000, 0x2000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x10000, 0x400, 0x14abb, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10, [16]DataDirectory{ {0x0, 0x0}, @@ -79,7 +85,7 @@ var fileTests = []fileTest{ {0x0, 0x0}, }, }, - []*SectionHeader{ + sections: []*SectionHeader{ {".text", 0xcd8, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060}, {".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040}, {".rdata", 0x120, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040}, @@ -96,13 +102,11 @@ var fileTests = []fileTest{ {".debug_frame", 0x34, 0xe000, 0x200, 0x3800, 0x0, 0x0, 0x0, 0x0, 0x42300000}, {".debug_loc", 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000}, }, - []*Symbol{}, }, { - "testdata/gcc-amd64-mingw-obj", - FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4}, - nil, - []*SectionHeader{ + file: "testdata/gcc-amd64-mingw-obj", + hdr: FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4}, + sections: []*SectionHeader{ {".text", 0x0, 0x0, 0x30, 0x104, 0x15c, 0x0, 0x3, 0x0, 0x60500020}, {".data", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500040}, {".bss", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500080}, @@ -110,7 +114,7 @@ var fileTests = []fileTest{ {".xdata", 0x0, 0x0, 0xc, 0x144, 0x0, 0x0, 0x0, 0x0, 0x40300040}, {".pdata", 0x0, 0x0, 0xc, 0x150, 0x17a, 0x0, 0x3, 0x0, 0x40300040}, }, - []*Symbol{ + symbols: []*Symbol{ {".file", 0x0, -2, 0x0, 0x67}, {"main", 0x0, 1, 0x20, 0x2}, {".text", 0x0, 1, 0x0, 0x3}, @@ -122,11 +126,12 @@ var fileTests = []fileTest{ {"__main", 0x0, 0, 0x20, 0x2}, {"puts", 0x0, 0, 0x20, 0x2}, }, + hasNoDwarfInfo: true, }, { - "testdata/gcc-amd64-mingw-exec", - FileHeader{0x8664, 0x11, 0x53e4364f, 0x39600, 0x6fc, 0xf0, 0x27}, - &OptionalHeader64{ + file: "testdata/gcc-amd64-mingw-exec", + hdr: FileHeader{0x8664, 0x11, 0x53e4364f, 0x39600, 0x6fc, 0xf0, 0x27}, + opthdr: &OptionalHeader64{ 0x20b, 0x2, 0x16, 0x6a00, 0x2400, 0x1600, 0x14e0, 0x1000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x0, 0x0, 0x5, 0x2, 0x0, 0x45000, 0x600, 0x46f19, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10, [16]DataDirectory{ {0x0, 0x0}, @@ -146,7 +151,7 @@ var fileTests = []fileTest{ {0x0, 0x0}, {0x0, 0x0}, }}, - []*SectionHeader{ + sections: []*SectionHeader{ {".text", 0x6860, 0x1000, 0x6a00, 0x600, 0x0, 0x0, 0x0, 0x0, 0x60500020}, {".data", 0xe0, 0x8000, 0x200, 0x7000, 0x0, 0x0, 0x0, 0x0, 0xc0500040}, {".rdata", 0x6b0, 0x9000, 0x800, 0x7200, 0x0, 0x0, 0x0, 0x0, 0x40600040}, @@ -165,7 +170,6 @@ var fileTests = []fileTest{ {".debug_loc", 0x13240, 0x30000, 0x13400, 0x25600, 0x0, 0x0, 0x0, 0x0, 0x42100040}, {".debug_ranges", 0xa70, 0x44000, 0xc00, 0x38a00, 0x0, 0x0, 0x0, 0x0, 0x42100040}, }, - []*Symbol{}, }, } @@ -231,6 +235,12 @@ func TestOpen(t *testing.T) { t.Errorf("open %s, symbol %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want) } } + if !tt.hasNoDwarfInfo { + _, err = f.DWARF() + if err != nil { + t.Errorf("fetching %s dwarf details failed: %v", tt.file, err) + } + } } } @@ -241,3 +251,59 @@ func TestOpenFailure(t *testing.T) { t.Errorf("open %s: succeeded unexpectedly", filename) } } + +func TestDWARF(t *testing.T) { + if runtime.GOOS != "windows" { + t.Skip("skipping windows only test") + } + + tmpdir, err := ioutil.TempDir("", "TestDWARF") + if err != nil { + t.Fatal("TempDir failed: ", err) + } + defer os.RemoveAll(tmpdir) + + prog := ` +package main +func main() { +} +` + src := filepath.Join(tmpdir, "a.go") + exe := filepath.Join(tmpdir, "a.exe") + err = ioutil.WriteFile(src, []byte(prog), 0644) + output, err := exec.Command("go", "build", "-o", exe, src).CombinedOutput() + if err != nil { + t.Fatalf("building test executable failed: %s %s", err, output) + } + + f, err := Open(exe) + if err != nil { + t.Fatal(err) + } + defer f.Close() + + d, err := f.DWARF() + if err != nil { + t.Fatal(err) + } + + // look for main.main + r := d.Reader() + for { + e, err := r.Next() + if err != nil { + t.Fatal("r.Next:", err) + } + if e == nil { + break + } + if e.Tag == dwarf.TagSubprogram { + for _, f := range e.Field { + if f.Attr == dwarf.AttrName && e.Val(dwarf.AttrName) == "main.main" { + return + } + } + } + } + t.Fatal("main.main not found") +} -- 2.50.0