Commit dde7c770 authored by Austin Clements's avatar Austin Clements

cmd/compile: make the second argument to go:linkname optional

The //go:linkname directive can be used to make a symbol accessible to
another package (when it wouldn't normally be). Sometimes you want to
do this without actually changing the symbol's object file symbol
name; for example, in gccgo this makes unexported symbols non-static,
and in gc this provides ABI0 wrappers for Go symbols so they can be
called from assembly in other packages. Currently, this results in
stutter like

   //go:linkname entersyscall runtime.entersyscall

This CL makes the second argument to go:linkname optional for the case
where the intent is simply to expose the symbol rather than to rename
it in the object file.

Updates #31230.

Change-Id: Id06d9c4b2ec3d8e27f9b8a0d65212ab8048d734f
Reviewed-on: https://go-review.googlesource.com/c/go/+/179861
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent b402bd44
......@@ -216,11 +216,15 @@ not include a stack overflow check. This is most commonly used by low-level
runtime sources invoked at times when it is unsafe for the calling goroutine to be
preempted.
//go:linkname localname importpath.name
//go:linkname localname [importpath.name]
The //go:linkname directive instructs the compiler to use ``importpath.name'' as the
object file symbol name for the variable or function declared as ``localname'' in the
source code. Because this directive can subvert the type system and package
source code.
If the ``importpath.name'' argument is omitted, the directive uses the
symbol's default object file symbol name and only has the effect of making
the symbol accessible to other packages.
Because this directive can subvert the type system and package
modularity, it is only enabled in files that have imported "unsafe".
*/
package main
......@@ -244,10 +244,21 @@ func (p *noder) node() {
xtop = append(xtop, p.decls(p.file.DeclList)...)
for _, n := range p.linknames {
if imported_unsafe {
lookup(n.local).Linkname = n.remote
} else {
if !imported_unsafe {
p.yyerrorpos(n.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
continue
}
s := lookup(n.local)
if n.remote != "" {
s.Linkname = n.remote
} else {
// Use the default object symbol name if the
// user didn't provide one.
if myimportpath == "" {
p.yyerrorpos(n.pos, "//go:linkname requires linkname argument or -p compiler flag")
} else {
s.Linkname = objabi.PathToPrefix(myimportpath) + "." + n.local
}
}
}
......@@ -1476,11 +1487,20 @@ func (p *noder) pragma(pos syntax.Pos, text string) syntax.Pragma {
case strings.HasPrefix(text, "go:linkname "):
f := strings.Fields(text)
if len(f) != 3 {
p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname linkname"})
if !(2 <= len(f) && len(f) <= 3) {
p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname [linkname]"})
break
}
p.linknames = append(p.linknames, linkname{pos, f[1], f[2]})
// The second argument is optional. If omitted, we use
// the default object symbol name for this and
// linkname only serves to mark this symbol as
// something that may be referenced via the object
// symbol name from another package.
var target string
if len(f) == 3 {
target = f[2]
}
p.linknames = append(p.linknames, linkname{pos, f[1], target})
case strings.HasPrefix(text, "go:cgo_import_dynamic "):
// This is permitted for general use because Solaris
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment