cmd/compile, cmd/link: produce unlinkable object when compile without -p

CL 391014 requires the compiler to be invoked with the -p flag, to
specify the package path. People are used to run "go tool compile"
from the command line with the -p flag. This is mostly for simple
testing, or debugging the compiler. The produced object file is
almost never intended to be linked.

This CL makes the compiler allow "go tool compile" without the -p
flag again. It will produce an unlinkable object. If the linker
sees such an object it will error out.

Change-Id: I7bdb162c3cad61dadd5c456d903b92493a3df20f
Reviewed-on: https://go-review.googlesource.com/c/go/+/394217
Trust: Cherry Mui <cherryyz@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Cherry Mui 2022-03-21 13:45:50 -04:00
parent 63ea27e9e0
commit e853464055
5 changed files with 41 additions and 1 deletions

View file

@ -16,6 +16,7 @@ import (
"runtime"
"strings"
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/sys"
)
@ -202,7 +203,7 @@ func ParseFlags() {
}
if *Flag.LowerP == "" {
log.Fatalf("-p is required")
*Flag.LowerP = obj.UnlinkablePkg
}
if Flag.LowerO == "" {

View file

@ -283,6 +283,7 @@ const (
ObjFlagShared = 1 << iota // this object is built with -shared
ObjFlagNeedNameExpansion // the linker needs to expand `"".` to package path in symbol names
ObjFlagFromAssembly // object is from asm src, not go
ObjFlagUnlinkable // unlinkable package (linker will emit an error)
)
// Sym.Flag
@ -869,3 +870,4 @@ func (r *Reader) Flags() uint32 {
func (r *Reader) Shared() bool { return r.Flags()&ObjFlagShared != 0 }
func (r *Reader) NeedNameExpansion() bool { return r.Flags()&ObjFlagNeedNameExpansion != 0 }
func (r *Reader) FromAssembly() bool { return r.Flags()&ObjFlagFromAssembly != 0 }
func (r *Reader) Unlinkable() bool { return r.Flags()&ObjFlagUnlinkable != 0 }

View file

@ -23,6 +23,8 @@ import (
"strings"
)
const UnlinkablePkg = "<unlinkable>" // invalid package path, used when compiled without -p flag
// Entry point of writing new object file.
func WriteObjFile(ctxt *Link, b *bio.Writer) {
@ -45,6 +47,9 @@ func WriteObjFile(ctxt *Link, b *bio.Writer) {
if ctxt.Flag_shared {
flags |= goobj.ObjFlagShared
}
if w.pkgpath == UnlinkablePkg {
flags |= goobj.ObjFlagUnlinkable
}
if w.pkgpath == "" {
flags |= goobj.ObjFlagNeedNameExpansion
}

View file

@ -2083,6 +2083,10 @@ func (l *Loader) Preload(localSymVersion int, f *bio.Reader, lib *sym.Library, u
objidx: uint32(len(l.objs)),
}
if r.Unlinkable() {
log.Fatalf("link: unlinkable object (from package %s) - compiler requires -p flag", lib.Pkg)
}
// Autolib
lib.Autolib = append(lib.Autolib, r.Autolib()...)

View file

@ -1059,3 +1059,31 @@ func TestLargeReloc(t *testing.T) {
}
}
}
func TestUnlinkableObj(t *testing.T) {
// Test that the linker emits an error with unlinkable object.
testenv.MustHaveGoBuild(t)
t.Parallel()
tmpdir := t.TempDir()
src := filepath.Join(tmpdir, "x.go")
obj := filepath.Join(tmpdir, "x.o")
err := ioutil.WriteFile(src, []byte("package main\nfunc main() {}\n"), 0666)
if err != nil {
t.Fatalf("failed to write source file: %v", err)
}
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", obj, src) // without -p
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("compile failed: %v. output:\n%s", err, out)
}
cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", obj)
out, err = cmd.CombinedOutput()
if err == nil {
t.Fatalf("link did not fail")
}
if !bytes.Contains(out, []byte("unlinkable object")) {
t.Errorf("did not see expected error message. out:\n%s", out)
}
}