From dde7c770ef44d45b8a9f98bf0f46556f18df2f6e Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 31 May 2019 15:45:06 -0400 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: David Chase --- src/cmd/compile/doc.go | 8 +++++-- src/cmd/compile/internal/gc/noder.go | 32 ++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/doc.go b/src/cmd/compile/doc.go index 5291a8b0eb..5b437d6804 100644 --- a/src/cmd/compile/doc.go +++ b/src/cmd/compile/doc.go @@ -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 diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index e83ae7c5eb..93d355278e 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -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