aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThan McIntosh <thanm@google.com>2021-06-08 19:45:41 -0400
committerThan McIntosh <thanm@google.com>2021-06-09 02:18:24 +0000
commit07ca28d529e1afb64a9f6f068214c05ee9772d34 (patch)
treee6d1f21355b7dfff02d7c4f8b6da9efb09bfb6be
parentbcecae2af6ee43abebf84411385d538ec4e7d0ea (diff)
downloadgo-07ca28d529e1afb64a9f6f068214c05ee9772d34.tar.gz
go-07ca28d529e1afb64a9f6f068214c05ee9772d34.zip
cmd/link: fix bug in -strictdups checking of BSS symbols
The linker's -strictdups debugging option was not properly checking for cases where you have two dupok BSS symbols with different length (the check examined data length and content, but not symbol size). Updates #46653. Change-Id: I3844f25ef76dd6e4a84ffd5caed5d19a1b1a57c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/326210 Trust: Than McIntosh <thanm@google.com> Run-TryBot: Than McIntosh <thanm@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
-rw-r--r--src/cmd/link/internal/loader/loader.go12
-rw-r--r--src/cmd/link/link_test.go43
2 files changed, 41 insertions, 14 deletions
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index 1b71a66c6f..efca824d98 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -699,12 +699,18 @@ func (l *Loader) checkdup(name string, r *oReader, li uint32, dup Sym) {
p := r.Data(li)
rdup, ldup := l.toLocal(dup)
pdup := rdup.Data(ldup)
- if bytes.Equal(p, pdup) {
- return
- }
reason := "same length but different contents"
if len(p) != len(pdup) {
reason = fmt.Sprintf("new length %d != old length %d", len(p), len(pdup))
+ } else if bytes.Equal(p, pdup) {
+ // For BSS symbols, we need to check size as well, see issue 46653.
+ szdup := l.SymSize(dup)
+ sz := int64(r.Sym(li).Siz())
+ if szdup == sz {
+ return
+ }
+ reason = fmt.Sprintf("different sizes: new size %d != old size %d",
+ sz, szdup)
}
fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.unit.Lib, name, rdup.unit.Lib, reason)
diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go
index 4d6bc76aca..7230054bed 100644
--- a/src/cmd/link/link_test.go
+++ b/src/cmd/link/link_test.go
@@ -470,10 +470,30 @@ TEXT ·f(SB), NOSPLIT|DUPOK, $0-0
JMP 0(PC)
`
+const testStrictDupAsmSrc3 = `
+#include "textflag.h"
+GLOBL ·rcon(SB), RODATA|DUPOK, $64
+`
+
+const testStrictDupAsmSrc4 = `
+#include "textflag.h"
+GLOBL ·rcon(SB), RODATA|DUPOK, $32
+`
+
func TestStrictDup(t *testing.T) {
// Check that -strictdups flag works.
testenv.MustHaveGoBuild(t)
+ asmfiles := []struct {
+ fname string
+ payload string
+ }{
+ {"a", testStrictDupAsmSrc1},
+ {"b", testStrictDupAsmSrc2},
+ {"c", testStrictDupAsmSrc3},
+ {"d", testStrictDupAsmSrc4},
+ }
+
t.Parallel()
tmpdir := t.TempDir()
@@ -483,15 +503,12 @@ func TestStrictDup(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- src = filepath.Join(tmpdir, "a.s")
- err = ioutil.WriteFile(src, []byte(testStrictDupAsmSrc1), 0666)
- if err != nil {
- t.Fatal(err)
- }
- src = filepath.Join(tmpdir, "b.s")
- err = ioutil.WriteFile(src, []byte(testStrictDupAsmSrc2), 0666)
- if err != nil {
- t.Fatal(err)
+ for _, af := range asmfiles {
+ src = filepath.Join(tmpdir, af.fname+".s")
+ err = ioutil.WriteFile(src, []byte(af.payload), 0666)
+ if err != nil {
+ t.Fatal(err)
+ }
}
src = filepath.Join(tmpdir, "go.mod")
err = ioutil.WriteFile(src, []byte("module teststrictdup\n"), 0666)
@@ -503,7 +520,7 @@ func TestStrictDup(t *testing.T) {
cmd.Dir = tmpdir
out, err := cmd.CombinedOutput()
if err != nil {
- t.Errorf("linking with -strictdups=1 failed: %v", err)
+ t.Errorf("linking with -strictdups=1 failed: %v\n%s", err, string(out))
}
if !bytes.Contains(out, []byte("mismatched payload")) {
t.Errorf("unexpected output:\n%s", out)
@@ -515,7 +532,11 @@ func TestStrictDup(t *testing.T) {
if err == nil {
t.Errorf("linking with -strictdups=2 did not fail")
}
- if !bytes.Contains(out, []byte("mismatched payload")) {
+ // NB: on amd64 we get the 'new length' error, on arm64 the 'different
+ // contents' error.
+ if !(bytes.Contains(out, []byte("mismatched payload: new length")) ||
+ bytes.Contains(out, []byte("mismatched payload: same length but different contents"))) ||
+ !bytes.Contains(out, []byte("mismatched payload: different sizes")) {
t.Errorf("unexpected output:\n%s", out)
}
}