Skip to content

Commit

Permalink
cmd/link: skip symbol references when looking for missing symbols
Browse files Browse the repository at this point in the history
ErrorUnresolved attempts to find the missing symbol in another ABI,
in order to provide more friendly error messages. However, in doing so
it checks the same ABI and can find the symbol reference for the symbol
that it is currently reporting the unresolved error for. Avoid this by
ignoring SXREF symbols, which is the same behaviour used when linking
is performed.

Fixes #33979

Change-Id: I9bfc40146dec2666d25e93d3bcd1984da5c71215
Reviewed-on: https://go-review.googlesource.com/c/go/+/220917
Run-TryBot: Than McIntosh <thanm@google.com>
Run-TryBot: Austin Clements <austin@google.com>
Reviewed-by: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
  • Loading branch information
4a6f656c committed Apr 2, 2020
1 parent 1dbcbcf commit aa4d92b
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/cmd/link/internal/ld/link.go
Expand Up @@ -136,7 +136,7 @@ func (ctxt *Link) ErrorUnresolved(s *sym.Symbol, r *sym.Reloc) {
if v == -1 {
continue
}
if rs := ctxt.Syms.ROLookup(r.Sym.Name, v); rs != nil && rs.Type != sym.Sxxx {
if rs := ctxt.Syms.ROLookup(r.Sym.Name, v); rs != nil && rs.Type != sym.Sxxx && rs.Type != sym.SXREF {
haveABI = abi
}
}
Expand Down
87 changes: 87 additions & 0 deletions src/cmd/link/link_test.go
Expand Up @@ -172,6 +172,93 @@ main.x: relocation target main.zero not defined
}
}

func TestIssue33979(t *testing.T) {
testenv.MustHaveGoBuild(t)
testenv.MustHaveCGO(t)

// Skip test on platforms that do not support cgo internal linking.
switch runtime.GOARCH {
case "mips", "mipsle", "mips64", "mips64le":
t.Skipf("Skipping on %s/%s", runtime.GOOS, runtime.GOARCH)
}
if runtime.GOOS == "aix" {
t.Skipf("Skipping on %s/%s", runtime.GOOS, runtime.GOARCH)
}

tmpdir, err := ioutil.TempDir("", "unresolved-")
if err != nil {
t.Fatalf("failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpdir)

write := func(name, content string) {
err := ioutil.WriteFile(filepath.Join(tmpdir, name), []byte(content), 0666)
if err != nil {
t.Fatal(err)
}
}

run := func(name string, args ...string) string {
cmd := exec.Command(name, args...)
cmd.Dir = tmpdir
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("'go %s' failed: %v, output: %s", strings.Join(args, " "), err, out)
}
return string(out)
}
runGo := func(args ...string) string {
return run(testenv.GoToolPath(t), args...)
}

// Test object with undefined reference that was not generated
// by Go, resulting in an SXREF symbol being loaded during linking.
// Because of issue #33979, the SXREF symbol would be found during
// error reporting, resulting in confusing error messages.

write("main.go", `package main
func main() {
x()
}
func x()
`)
// The following assembly must work on all architectures.
write("x.s", `
TEXT ·x(SB),0,$0
CALL foo(SB)
RET
`)
write("x.c", `
void undefined();
void foo() {
undefined();
}
`)

cc := strings.TrimSpace(runGo("env", "CC"))
cflags := strings.Fields(runGo("env", "GOGCCFLAGS"))

// Compile, assemble and pack the Go and C code.
runGo("tool", "asm", "-gensymabis", "-o", "symabis", "x.s")
runGo("tool", "compile", "-symabis", "symabis", "-p", "main", "-o", "x1.o", "main.go")
runGo("tool", "asm", "-o", "x2.o", "x.s")
run(cc, append(cflags, "-c", "-o", "x3.o", "x.c")...)
runGo("tool", "pack", "c", "x.a", "x1.o", "x2.o", "x3.o")

// Now attempt to link using the internal linker.
cmd := exec.Command(testenv.GoToolPath(t), "tool", "link", "-linkmode=internal", "x.a")
cmd.Dir = tmpdir
out, err := cmd.CombinedOutput()
if err == nil {
t.Fatalf("expected link to fail, but it succeeded")
}
re := regexp.MustCompile(`(?m)^main\(.*text\): relocation target undefined not defined$`)
if !re.Match(out) {
t.Fatalf("got:\n%q\nwant:\n%s", out, re)
}
}

func TestBuildForTvOS(t *testing.T) {
testenv.MustHaveCGO(t)
testenv.MustHaveGoBuild(t)
Expand Down

0 comments on commit aa4d92b

Please sign in to comment.