aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Randall <khr@google.com>2018-11-26 10:48:56 -0800
committerKeith Randall <khr@golang.org>2018-11-26 20:00:59 +0000
commitca3749230b5a7d43b3292226fdb2b6f3de5d653b (patch)
tree228f42320e098e6cc90844b87a566523b8c35897
parent9ab2ffe8e92f9660cbde1a18921ae864c64f280b (diff)
downloadgo-ca3749230b5a7d43b3292226fdb2b6f3de5d653b.tar.xz
cmd/compile: allow bodyless function if it is linkname'd
In assembly free packages (aka "complete" or "pure go"), allow bodyless functions if they are linkname'd to something else. Presumably the thing the function is linkname'd to has a definition. If not, the linker will complain. And linkname is unsafe, so we expect users to know what they are doing. Note this handles only one direction, where the linkname directive is in the local package. If the linkname directive is in the remote package, this CL won't help. (See os/signal/sig.s for an example.) Fixes #23311 Change-Id: I824361b4b582ee05976d94812e5b0e8b0f7a18a6 Reviewed-on: https://go-review.googlesource.com/c/151318 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
-rw-r--r--src/cmd/compile/internal/gc/noder.go13
-rw-r--r--test/fixedbugs/issue23311.dir/main.go (renamed from src/runtime/testdata/testprog/empty.s)11
-rw-r--r--test/fixedbugs/issue23311.go (renamed from src/internal/syscall/unix/empty.s)4
3 files changed, 25 insertions, 3 deletions
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index b9849e7a84..23c9539b0a 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -497,7 +497,18 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node {
}
} else {
if pure_go || strings.HasPrefix(f.funcname(), "init.") {
- yyerrorl(f.Pos, "missing function body")
+ // Linknamed functions are allowed to have no body. Hopefully
+ // the linkname target has a body. See issue 23311.
+ isLinknamed := false
+ for _, n := range p.linknames {
+ if f.funcname() == n.local {
+ isLinknamed = true
+ break
+ }
+ }
+ if !isLinknamed {
+ yyerrorl(f.Pos, "missing function body")
+ }
}
}
diff --git a/src/runtime/testdata/testprog/empty.s b/test/fixedbugs/issue23311.dir/main.go
index c5aa6f8a54..fa4cf76b89 100644
--- a/src/runtime/testdata/testprog/empty.s
+++ b/test/fixedbugs/issue23311.dir/main.go
@@ -2,4 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This exists solely so we can linkname in symbols from runtime.
+package main
+
+import _ "unsafe" // for linkname
+
+//go:linkname f runtime.GC
+func f()
+
+func main() {
+ f()
+}
diff --git a/src/internal/syscall/unix/empty.s b/test/fixedbugs/issue23311.go
index 717189c658..128cf9d06a 100644
--- a/src/internal/syscall/unix/empty.s
+++ b/test/fixedbugs/issue23311.go
@@ -1,5 +1,7 @@
+// compiledir
+
// Copyright 2018 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.
-// This exists solely so we can linkname in symbols from syscall.
+package ignored