Skip to content

Commit aa4d92b

Browse files
committed
cmd/link: skip symbol references when looking for missing symbols
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 <[email protected]> Run-TryBot: Austin Clements <[email protected]> Reviewed-by: Austin Clements <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 1dbcbcf commit aa4d92b

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

src/cmd/link/internal/ld/link.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ func (ctxt *Link) ErrorUnresolved(s *sym.Symbol, r *sym.Reloc) {
136136
if v == -1 {
137137
continue
138138
}
139-
if rs := ctxt.Syms.ROLookup(r.Sym.Name, v); rs != nil && rs.Type != sym.Sxxx {
139+
if rs := ctxt.Syms.ROLookup(r.Sym.Name, v); rs != nil && rs.Type != sym.Sxxx && rs.Type != sym.SXREF {
140140
haveABI = abi
141141
}
142142
}

src/cmd/link/link_test.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,93 @@ main.x: relocation target main.zero not defined
172172
}
173173
}
174174

175+
func TestIssue33979(t *testing.T) {
176+
testenv.MustHaveGoBuild(t)
177+
testenv.MustHaveCGO(t)
178+
179+
// Skip test on platforms that do not support cgo internal linking.
180+
switch runtime.GOARCH {
181+
case "mips", "mipsle", "mips64", "mips64le":
182+
t.Skipf("Skipping on %s/%s", runtime.GOOS, runtime.GOARCH)
183+
}
184+
if runtime.GOOS == "aix" {
185+
t.Skipf("Skipping on %s/%s", runtime.GOOS, runtime.GOARCH)
186+
}
187+
188+
tmpdir, err := ioutil.TempDir("", "unresolved-")
189+
if err != nil {
190+
t.Fatalf("failed to create temp dir: %v", err)
191+
}
192+
defer os.RemoveAll(tmpdir)
193+
194+
write := func(name, content string) {
195+
err := ioutil.WriteFile(filepath.Join(tmpdir, name), []byte(content), 0666)
196+
if err != nil {
197+
t.Fatal(err)
198+
}
199+
}
200+
201+
run := func(name string, args ...string) string {
202+
cmd := exec.Command(name, args...)
203+
cmd.Dir = tmpdir
204+
out, err := cmd.CombinedOutput()
205+
if err != nil {
206+
t.Fatalf("'go %s' failed: %v, output: %s", strings.Join(args, " "), err, out)
207+
}
208+
return string(out)
209+
}
210+
runGo := func(args ...string) string {
211+
return run(testenv.GoToolPath(t), args...)
212+
}
213+
214+
// Test object with undefined reference that was not generated
215+
// by Go, resulting in an SXREF symbol being loaded during linking.
216+
// Because of issue #33979, the SXREF symbol would be found during
217+
// error reporting, resulting in confusing error messages.
218+
219+
write("main.go", `package main
220+
func main() {
221+
x()
222+
}
223+
func x()
224+
`)
225+
// The following assembly must work on all architectures.
226+
write("x.s", `
227+
TEXT ·x(SB),0,$0
228+
CALL foo(SB)
229+
RET
230+
`)
231+
write("x.c", `
232+
void undefined();
233+
234+
void foo() {
235+
undefined();
236+
}
237+
`)
238+
239+
cc := strings.TrimSpace(runGo("env", "CC"))
240+
cflags := strings.Fields(runGo("env", "GOGCCFLAGS"))
241+
242+
// Compile, assemble and pack the Go and C code.
243+
runGo("tool", "asm", "-gensymabis", "-o", "symabis", "x.s")
244+
runGo("tool", "compile", "-symabis", "symabis", "-p", "main", "-o", "x1.o", "main.go")
245+
runGo("tool", "asm", "-o", "x2.o", "x.s")
246+
run(cc, append(cflags, "-c", "-o", "x3.o", "x.c")...)
247+
runGo("tool", "pack", "c", "x.a", "x1.o", "x2.o", "x3.o")
248+
249+
// Now attempt to link using the internal linker.
250+
cmd := exec.Command(testenv.GoToolPath(t), "tool", "link", "-linkmode=internal", "x.a")
251+
cmd.Dir = tmpdir
252+
out, err := cmd.CombinedOutput()
253+
if err == nil {
254+
t.Fatalf("expected link to fail, but it succeeded")
255+
}
256+
re := regexp.MustCompile(`(?m)^main\(.*text\): relocation target undefined not defined$`)
257+
if !re.Match(out) {
258+
t.Fatalf("got:\n%q\nwant:\n%s", out, re)
259+
}
260+
}
261+
175262
func TestBuildForTvOS(t *testing.T) {
176263
testenv.MustHaveCGO(t)
177264
testenv.MustHaveGoBuild(t)

0 commit comments

Comments
 (0)