]> Cypherpunks repositories - gostls13.git/commitdiff
debug/pe: .bss section must contain only zeros
authorAlex Brainman <alex.brainman@gmail.com>
Thu, 28 Apr 2016 05:19:11 +0000 (15:19 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Fri, 29 Apr 2016 02:58:42 +0000 (02:58 +0000)
.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>

src/debug/pe/file.go
src/debug/pe/file_test.go

index 1cd84d5727761e482518b0566138d9051bd1312f..ef4ae352fee29d6b9aabd8ad3a06b8d714358e12 100644 (file)
@@ -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) {
index 7367b982e23b6f3a1d1e5836e160180430714c00..12059b5effeb299a214ee989c1aa560ec5dc2d80 100644 (file)
@@ -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)
+               }
+       }
+}