cmd/link: use sym.Symbol in addpersrc
addpersrc is called very late, after we have converted to
sym.Symbols and various fields in loader representation have been
dropped. Use the Symbol representation there.
Fixes #39658.
Change-Id: I616e838655b6f01554644171317e2cc5cefabf39
Reviewed-on: https://go-review.googlesource.com/c/go/+/238779
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go
index 362d2fd..c9cb25d 100644
--- a/src/cmd/link/internal/ld/pe.go
+++ b/src/cmd/link/internal/ld/pe.go
@@ -1470,6 +1470,7 @@
}
rsrcsym = sym
+ ctxt.loader.SetAttrReachable(rsrcsym, true)
}
func addpersrc(ctxt *Link) {
@@ -1477,18 +1478,18 @@
return
}
- data := ctxt.loader.Data(rsrcsym)
+ rsrc := ctxt.loader.Syms[rsrcsym]
+ data := rsrc.P
size := len(data)
h := pefile.addSection(".rsrc", size, size)
h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA
h.checkOffset(ctxt.Out.Offset())
// relocation
- relocs := ctxt.loader.Relocs(rsrcsym)
- for i := 0; i < relocs.Count(); i++ {
- r := relocs.At2(i)
- p := data[r.Off():]
- val := uint32(int64(h.virtualAddress) + r.Add())
+ for ri := range rsrc.R {
+ r := &rsrc.R[ri]
+ p := data[r.Off:]
+ val := uint32(int64(h.virtualAddress) + r.Add)
// 32-bit little-endian
p[0] = byte(val)
diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go
index 5ff9912..dc7adcb 100644
--- a/src/cmd/link/link_test.go
+++ b/src/cmd/link/link_test.go
@@ -746,3 +746,37 @@
t.Errorf("did not see expected error message. out:\n%s", out)
}
}
+
+func TestPErsrc(t *testing.T) {
+ // Test that PE rsrc section is handled correctly (issue 39658).
+ testenv.MustHaveGoBuild(t)
+
+ if runtime.GOARCH != "amd64" || runtime.GOOS != "windows" {
+ t.Skipf("this is a windows/amd64-only test")
+ }
+
+ tmpdir, err := ioutil.TempDir("", "TestPErsrc")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ pkgdir := filepath.Join("testdata", "testPErsrc")
+ exe := filepath.Join(tmpdir, "a.exe")
+ cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe)
+ cmd.Dir = pkgdir
+ // cmd.Env = append(os.Environ(), "GOOS=windows", "GOARCH=amd64") // uncomment if debugging in a cross-compiling environment
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("building failed: %v, output:\n%s", err, out)
+ }
+
+ // Check that the binary contains the rsrc data
+ b, err := ioutil.ReadFile(exe)
+ if err != nil {
+ t.Fatalf("reading output failed: %v", err)
+ }
+ if !bytes.Contains(b, []byte("Hello Gophers!")) {
+ t.Fatalf("binary does not contain expected content")
+ }
+}
diff --git a/src/cmd/link/testdata/testPErsrc/main.go b/src/cmd/link/testdata/testPErsrc/main.go
new file mode 100644
index 0000000..5eb66fb
--- /dev/null
+++ b/src/cmd/link/testdata/testPErsrc/main.go
@@ -0,0 +1,19 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that a PE rsrc section is handled correctly (issue 39658).
+//
+// rsrc.syso is created with:
+// windres -i a.rc -o rsrc.syso -O coff
+// on windows-amd64-2016 builder, where a.rc is a text file with
+// the following content:
+//
+// resname RCDATA {
+// "Hello Gophers!\0",
+// "This is a test.\0",
+// }
+
+package main
+
+func main() {}
diff --git a/src/cmd/link/testdata/testPErsrc/rsrc.syso b/src/cmd/link/testdata/testPErsrc/rsrc.syso
new file mode 100644
index 0000000..0d9699d
--- /dev/null
+++ b/src/cmd/link/testdata/testPErsrc/rsrc.syso
Binary files differ