Skip to content
Snippets Groups Projects
Commit 07ca28d5 authored by Than McIntosh's avatar Than McIntosh
Browse files

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: default avatarCherry Mui <cherryyz@google.com>
parent bcecae2a
No related branches found
No related tags found
No related merge requests found
...@@ -699,12 +699,18 @@ func (l *Loader) checkdup(name string, r *oReader, li uint32, dup Sym) { ...@@ -699,12 +699,18 @@ func (l *Loader) checkdup(name string, r *oReader, li uint32, dup Sym) {
p := r.Data(li) p := r.Data(li)
rdup, ldup := l.toLocal(dup) rdup, ldup := l.toLocal(dup)
pdup := rdup.Data(ldup) pdup := rdup.Data(ldup)
if bytes.Equal(p, pdup) {
return
}
reason := "same length but different contents" reason := "same length but different contents"
if len(p) != len(pdup) { if len(p) != len(pdup) {
reason = fmt.Sprintf("new length %d != old length %d", 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) 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)
......
...@@ -470,10 +470,30 @@ TEXT ·f(SB), NOSPLIT|DUPOK, $0-0 ...@@ -470,10 +470,30 @@ TEXT ·f(SB), NOSPLIT|DUPOK, $0-0
JMP 0(PC) 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) { func TestStrictDup(t *testing.T) {
// Check that -strictdups flag works. // Check that -strictdups flag works.
testenv.MustHaveGoBuild(t) testenv.MustHaveGoBuild(t)
asmfiles := []struct {
fname string
payload string
}{
{"a", testStrictDupAsmSrc1},
{"b", testStrictDupAsmSrc2},
{"c", testStrictDupAsmSrc3},
{"d", testStrictDupAsmSrc4},
}
t.Parallel() t.Parallel()
tmpdir := t.TempDir() tmpdir := t.TempDir()
...@@ -483,15 +503,12 @@ func TestStrictDup(t *testing.T) { ...@@ -483,15 +503,12 @@ func TestStrictDup(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
src = filepath.Join(tmpdir, "a.s") for _, af := range asmfiles {
err = ioutil.WriteFile(src, []byte(testStrictDupAsmSrc1), 0666) src = filepath.Join(tmpdir, af.fname+".s")
if err != nil { err = ioutil.WriteFile(src, []byte(af.payload), 0666)
t.Fatal(err) 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)
} }
src = filepath.Join(tmpdir, "go.mod") src = filepath.Join(tmpdir, "go.mod")
err = ioutil.WriteFile(src, []byte("module teststrictdup\n"), 0666) err = ioutil.WriteFile(src, []byte("module teststrictdup\n"), 0666)
...@@ -503,7 +520,7 @@ func TestStrictDup(t *testing.T) { ...@@ -503,7 +520,7 @@ func TestStrictDup(t *testing.T) {
cmd.Dir = tmpdir cmd.Dir = tmpdir
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { 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")) { if !bytes.Contains(out, []byte("mismatched payload")) {
t.Errorf("unexpected output:\n%s", out) t.Errorf("unexpected output:\n%s", out)
...@@ -515,7 +532,11 @@ func TestStrictDup(t *testing.T) { ...@@ -515,7 +532,11 @@ func TestStrictDup(t *testing.T) {
if err == nil { if err == nil {
t.Errorf("linking with -strictdups=2 did not fail") 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) t.Errorf("unexpected output:\n%s", out)
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment