aboutsummaryrefslogtreecommitdiff
path: root/src/debug
diff options
context:
space:
mode:
authorAlex Brainman <alex.brainman@gmail.com>2016-04-28 15:19:11 +1000
committerAlex Brainman <alex.brainman@gmail.com>2016-04-29 02:58:42 +0000
commit694846a548f23cebb9b913999fa4fa6756e2c545 (patch)
treecb88c5896ae4843f5f58f5ce3cc1b23dee8abc4a /src/debug
parentd954f9c4d19bbe459ad4a6de95af47349da1d40b (diff)
downloadgo-694846a548f23cebb9b913999fa4fa6756e2c545.tar.xz
debug/pe: .bss section must contain only zeros
.bss section has no data stored in PE file. But when .bss section data is used by the linker it is assumed that its every byte is set to zero. (*Section).Data returns garbage at this moment. Change (*Section).Data so it returns slice filled with 0s. Updates #15345 Change-Id: I1fa5138244a9447e1d59dec24178b1dd0fd4c5d7 Reviewed-on: https://go-review.googlesource.com/22544 Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/debug')
-rw-r--r--src/debug/pe/file.go17
-rw-r--r--src/debug/pe/file_test.go73
2 files changed, 89 insertions, 1 deletions
diff --git a/src/debug/pe/file.go b/src/debug/pe/file.go
index 1cd84d5727..ef4ae352fe 100644
--- a/src/debug/pe/file.go
+++ b/src/debug/pe/file.go
@@ -158,7 +158,11 @@ func NewFile(r io.ReaderAt) (*File, error) {
NumberOfLineNumbers: sh.NumberOfLineNumbers,
Characteristics: sh.Characteristics,
}
- s.sr = io.NewSectionReader(r, int64(s.SectionHeader.Offset), int64(s.SectionHeader.Size))
+ r2 := r
+ if sh.PointerToRawData == 0 { // .bss must have all 0s
+ r2 = zeroReaderAt{}
+ }
+ s.sr = io.NewSectionReader(r2, int64(s.SectionHeader.Offset), int64(s.SectionHeader.Size))
s.ReaderAt = s.sr
f.Sections[i] = s
}
@@ -173,6 +177,17 @@ func NewFile(r io.ReaderAt) (*File, error) {
return f, nil
}
+// zeroReaderAt is ReaderAt that reads 0s.
+type zeroReaderAt struct{}
+
+// ReadAt writes len(p) 0s into p.
+func (w zeroReaderAt) ReadAt(p []byte, off int64) (n int, err error) {
+ for i := range p {
+ p[i] = 0
+ }
+ return len(p), nil
+}
+
// getString extracts a string from symbol string table.
func getString(section []byte, start int) (string, bool) {
if start < 0 || start >= len(section) {
diff --git a/src/debug/pe/file_test.go b/src/debug/pe/file_test.go
index 7367b982e2..12059b5eff 100644
--- a/src/debug/pe/file_test.go
+++ b/src/debug/pe/file_test.go
@@ -6,6 +6,7 @@ package pe
import (
"debug/dwarf"
+ "internal/testenv"
"io/ioutil"
"os"
"os/exec"
@@ -307,3 +308,75 @@ func main() {
}
t.Fatal("main.main not found")
}
+
+func TestBSSHasZeros(t *testing.T) {
+ testenv.MustHaveExec(t)
+
+ if runtime.GOOS != "windows" {
+ t.Skip("skipping windows only test")
+ }
+ gccpath, err := exec.LookPath("gcc")
+ if err != nil {
+ t.Skip("skipping test: gcc is missing")
+ }
+
+ tmpdir, err := ioutil.TempDir("", "TestBSSHasZeros")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ srcpath := filepath.Join(tmpdir, "a.c")
+ src := `
+#include <stdio.h>
+
+int zero = 0;
+
+int
+main(void)
+{
+ printf("%d\n", zero);
+ return 0;
+}
+`
+ err = ioutil.WriteFile(srcpath, []byte(src), 0644)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ objpath := filepath.Join(tmpdir, "a.obj")
+ cmd := exec.Command(gccpath, "-c", srcpath, "-o", objpath)
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("failed to build object file: %v - %v", err, string(out))
+ }
+
+ f, err := Open(objpath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+
+ var bss *Section
+ for _, sect := range f.Sections {
+ if sect.Name == ".bss" {
+ bss = sect
+ break
+ }
+ }
+ if bss == nil {
+ t.Fatal("could not find .bss section")
+ }
+ data, err := bss.Data()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(data) == 0 {
+ t.Fatalf("%s file .bss section cannot be empty", objpath)
+ }
+ for _, b := range data {
+ if b != 0 {
+ t.Fatalf(".bss section has non zero bytes: %v", data)
+ }
+ }
+}