Commit 694846a5 authored by Alex Brainman's avatar Alex Brainman

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/22544Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent d954f9c4
...@@ -158,7 +158,11 @@ func NewFile(r io.ReaderAt) (*File, error) { ...@@ -158,7 +158,11 @@ func NewFile(r io.ReaderAt) (*File, error) {
NumberOfLineNumbers: sh.NumberOfLineNumbers, NumberOfLineNumbers: sh.NumberOfLineNumbers,
Characteristics: sh.Characteristics, 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 s.ReaderAt = s.sr
f.Sections[i] = s f.Sections[i] = s
} }
...@@ -173,6 +177,17 @@ func NewFile(r io.ReaderAt) (*File, error) { ...@@ -173,6 +177,17 @@ func NewFile(r io.ReaderAt) (*File, error) {
return f, nil 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. // getString extracts a string from symbol string table.
func getString(section []byte, start int) (string, bool) { func getString(section []byte, start int) (string, bool) {
if start < 0 || start >= len(section) { if start < 0 || start >= len(section) {
......
...@@ -6,6 +6,7 @@ package pe ...@@ -6,6 +6,7 @@ package pe
import ( import (
"debug/dwarf" "debug/dwarf"
"internal/testenv"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
...@@ -307,3 +308,75 @@ func main() { ...@@ -307,3 +308,75 @@ func main() {
} }
t.Fatal("main.main not found") 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)
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment