]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile, cmd/link: produce unlinkable object when compile without -p
authorCherry Mui <cherryyz@google.com>
Mon, 21 Mar 2022 17:45:50 +0000 (13:45 -0400)
committerCherry Mui <cherryyz@google.com>
Tue, 22 Mar 2022 19:38:35 +0000 (19:38 +0000)
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>

src/cmd/compile/internal/base/flag.go
src/cmd/internal/goobj/objfile.go
src/cmd/internal/obj/objfile.go
src/cmd/link/internal/loader/loader.go
src/cmd/link/link_test.go

index 0b04f62e1c105d147f639c0a7f49d2b08a2f0857..0056f83059e0c1ff661cf6499027e61ce8f9744c 100644 (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 == "" {
index 976505839240bd868d96abeca1c26379ba4b8607..ff225bedd773d6b9905472401d5bbbcaace18e08 100644 (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 }
index 560e8e24c458aa3a722aa4a13940fb7d59801737..e7bc45ccdf088e3c6bd2ac02c306c079e621e3bb 100644 (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
        }
index dfaad10143be5de936f6c02fea74c7892dccb02a..6f2d41aa789ec1d4782c3a1547ac8337a011b8c8 100644 (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()...)
 
index 0492feaf0d6c74a5933f27b86688d4fa5bc155c6..41da9276067d4b994392cb7214c43e9f08afab27 100644 (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)
+       }
+}