]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/link: reject non-package main toplevel.a file, remove dead code
authorRuss Cox <rsc@golang.org>
Thu, 17 Dec 2015 20:10:25 +0000 (15:10 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 17 Dec 2015 20:59:51 +0000 (20:59 +0000)
The test for non-package main top-level inputs is done while parsing
the export data. Issue #13468 happened because we were not parsing
the export data when using compiler-generated archives
(that is, when using go tool compile -pack).

Fix this by parsing the export data even for archives.

However, that turns up a different problem: the export data check
reports (one assumes spurious) skew errors now, because it has
not been run since Go 1.2.
(Go 1.3 was the first release to use go tool compile -pack.)

Since the code hasn't run since Go 1.2, it can't be that important.
Since it doesn't work today, just delete it.

Figuring out how to make this code work with Robert's export
format was one of the largest remaining TODOs for that format.
Now we don't have to.

Fixes #13468 and makes the world a better place.

Change-Id: I40a4b284cf140d49d48b714bd80762d6889acdb9
Reviewed-on: https://go-review.googlesource.com/17976
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/link/internal/ld/go.go
src/cmd/link/internal/ld/lib.go
test/linkmain.go [new file with mode: 0644]
test/linkmain_run.go [new file with mode: 0644]

index efe6dd0ad7cbcf48228e2845dc6ac55e21159f32..28f091010d81f1138974c3b02b2b05254749446a 100644 (file)
@@ -11,7 +11,6 @@ import (
        "cmd/internal/obj"
        "fmt"
        "os"
-       "strconv"
        "strings"
 )
 
@@ -22,37 +21,11 @@ func expandpkg(t0 string, pkg string) string {
        return strings.Replace(t0, `"".`, pkg+".", -1)
 }
 
-// accumulate all type information from .6 files.
-// check for inconsistencies.
-
 // TODO:
 //     generate debugging section in binary.
 //     once the dust settles, try to move some code to
 //             libmach, so that other linkers and ar can share.
 
-/*
- *     package import data
- */
-type Import struct {
-       prefix string // "type", "var", "func", "const"
-       name   string
-       def    string
-       file   string
-}
-
-// importmap records type information about imported symbols to detect inconsistencies.
-// Entries are keyed by qualified symbol name (e.g., "runtime.Callers" or "net/url.Error").
-var importmap = map[string]*Import{}
-
-func lookupImport(name string) *Import {
-       if x, ok := importmap[name]; ok {
-               return x
-       }
-       x := &Import{name: name}
-       importmap[name] = x
-       return x
-}
-
 func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int) {
        var p0, p1 int
 
@@ -68,6 +41,12 @@ func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int)
                return
        }
 
+       // In a __.PKGDEF, we only care about the package name.
+       // Don't read all the export data.
+       if length > 1000 && whence == Pkgdef {
+               length = 1000
+       }
+
        bdata := make([]byte, length)
        if int64(obj.Bread(f, bdata)) != length {
                fmt.Fprintf(os.Stderr, "%s: short pkg read %s\n", os.Args[0], filename)
@@ -95,6 +74,9 @@ func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int)
 
        // second marks end of exports / beginning of local data
        p1 = strings.Index(data[p0:], "\n$$\n")
+       if p1 < 0 && whence == Pkgdef {
+               p1 = len(data) - p0
+       }
        if p1 < 0 {
                fmt.Fprintf(os.Stderr, "%s: cannot find end of exports in %s\n", os.Args[0], filename)
                if Debug['u'] != 0 {
@@ -141,8 +123,6 @@ func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int)
                if pkg == "main" && name != "main" {
                        Exitf("%s: not package main (package %s)", filename, name)
                }
-
-               loadpkgdata(filename, pkg, data[p0:p1])
        }
 
        // __.PKGDEF has no cgo section - those are in the C compiler-generated object files.
@@ -181,195 +161,6 @@ func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int)
        }
 }
 
-func loadpkgdata(file string, pkg string, data string) {
-       var prefix string
-       var name string
-       var def string
-
-       p := data
-       for parsepkgdata(file, pkg, &p, &prefix, &name, &def) > 0 {
-               x := lookupImport(name)
-               if x.prefix == "" {
-                       x.prefix = prefix
-                       x.def = def
-                       x.file = file
-               } else if x.prefix != prefix {
-                       fmt.Fprintf(os.Stderr, "%s: conflicting definitions for %s\n", os.Args[0], name)
-                       fmt.Fprintf(os.Stderr, "%s:\t%s %s ...\n", x.file, x.prefix, name)
-                       fmt.Fprintf(os.Stderr, "%s:\t%s %s ...\n", file, prefix, name)
-                       nerrors++
-               } else if x.def != def {
-                       fmt.Fprintf(os.Stderr, "%s: conflicting definitions for %s\n", os.Args[0], name)
-                       fmt.Fprintf(os.Stderr, "%s:\t%s %s %s\n", x.file, x.prefix, name, x.def)
-                       fmt.Fprintf(os.Stderr, "%s:\t%s %s %s\n", file, prefix, name, def)
-                       nerrors++
-               }
-       }
-}
-
-func parsepkgdata(file string, pkg string, pp *string, prefixp *string, namep *string, defp *string) int {
-       // skip white space
-       p := *pp
-
-loop:
-       for len(p) > 0 && (p[0] == ' ' || p[0] == '\t' || p[0] == '\n') {
-               p = p[1:]
-       }
-       if len(p) == 0 || strings.HasPrefix(p, "$$\n") {
-               return 0
-       }
-
-       // prefix: (var|type|func|const)
-       prefix := p
-
-       if len(p) < 7 {
-               return -1
-       }
-       if strings.HasPrefix(p, "var ") {
-               p = p[4:]
-       } else if strings.HasPrefix(p, "type ") {
-               p = p[5:]
-       } else if strings.HasPrefix(p, "func ") {
-               p = p[5:]
-       } else if strings.HasPrefix(p, "const ") {
-               p = p[6:]
-       } else if strings.HasPrefix(p, "import ") {
-               p = p[7:]
-               for len(p) > 0 && p[0] != ' ' {
-                       p = p[1:]
-               }
-               p = p[1:]
-               line := p
-               for len(p) > 0 && p[0] != '\n' {
-                       p = p[1:]
-               }
-               if len(p) == 0 {
-                       fmt.Fprintf(os.Stderr, "%s: %s: confused in import line\n", os.Args[0], file)
-                       nerrors++
-                       return -1
-               }
-               line = line[:len(line)-len(p)]
-               line = strings.TrimSuffix(line, " // indirect")
-               path, err := strconv.Unquote(line)
-               if err != nil {
-                       fmt.Fprintf(os.Stderr, "%s: %s: confused in import path: %q\n", os.Args[0], file, line)
-                       nerrors++
-                       return -1
-               }
-               p = p[1:]
-               imported(pkg, path)
-               goto loop
-       } else {
-               fmt.Fprintf(os.Stderr, "%s: %s: confused in pkg data near <<%.40s>>\n", os.Args[0], file, prefix)
-               nerrors++
-               return -1
-       }
-
-       prefix = prefix[:len(prefix)-len(p)-1]
-
-       // name: a.b followed by space
-       name := p
-
-       inquote := false
-       for len(p) > 0 {
-               if p[0] == ' ' && !inquote {
-                       break
-               }
-
-               if p[0] == '\\' {
-                       p = p[1:]
-               } else if p[0] == '"' {
-                       inquote = !inquote
-               }
-
-               p = p[1:]
-       }
-
-       if len(p) == 0 {
-               return -1
-       }
-       name = name[:len(name)-len(p)]
-       p = p[1:]
-
-       // def: free form to new line
-       def := p
-
-       for len(p) > 0 && p[0] != '\n' {
-               p = p[1:]
-       }
-       if len(p) == 0 {
-               return -1
-       }
-       def = def[:len(def)-len(p)]
-       var defbuf *bytes.Buffer
-       p = p[1:]
-
-       // include methods on successive lines in def of named type
-       var meth string
-       for parsemethod(&p, &meth) > 0 {
-               if defbuf == nil {
-                       defbuf = new(bytes.Buffer)
-                       defbuf.WriteString(def)
-               }
-               defbuf.WriteString("\n\t")
-               defbuf.WriteString(meth)
-       }
-       if defbuf != nil {
-               def = defbuf.String()
-       }
-
-       name = expandpkg(name, pkg)
-       def = expandpkg(def, pkg)
-
-       // done
-       *pp = p
-
-       *prefixp = prefix
-       *namep = name
-       *defp = def
-       return 1
-}
-
-func parsemethod(pp *string, methp *string) int {
-       // skip white space
-       p := *pp
-
-       for len(p) > 0 && (p[0] == ' ' || p[0] == '\t') {
-               p = p[1:]
-       }
-       if len(p) == 0 {
-               return 0
-       }
-
-       // might be a comment about the method
-       if strings.HasPrefix(p, "//") {
-               goto useline
-       }
-
-       // if it says "func (", it's a method
-       if strings.HasPrefix(p, "func (") {
-               goto useline
-       }
-       return 0
-
-       // definition to end of line
-useline:
-       *methp = p
-
-       for len(p) > 0 && p[0] != '\n' {
-               p = p[1:]
-       }
-       if len(p) == 0 {
-               fmt.Fprintf(os.Stderr, "%s: lost end of line in method definition\n", os.Args[0])
-               *pp = ""
-               return -1
-       }
-
-       *methp = (*methp)[:len(*methp)-len(p)]
-       *pp = p[1:]
-       return 1
-}
-
 func loadcgo(file string, pkg string, p string) {
        var next string
        var q string
index acbb2ac883875998694651ec0a82e856a38da4c1..5bb206afa80bcdfbf1237f560b4a117ce6d78dc7 100644 (file)
@@ -809,9 +809,7 @@ func objfile(lib *Library) {
 
        off += l
 
-       if Debug['u'] != 0 {
-               ldpkg(f, pkg, atolwhex(arhdr.size), lib.File, Pkgdef)
-       }
+       ldpkg(f, pkg, atolwhex(arhdr.size), lib.File, Pkgdef)
 
        /*
         * load all the object files from the archive now.
diff --git a/test/linkmain.go b/test/linkmain.go
new file mode 100644 (file)
index 0000000..dcfbf50
--- /dev/null
@@ -0,0 +1,12 @@
+// +build ignore
+
+// Copyright 2015 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.
+
+// For linkmain_run.go.
+
+package notmain
+
+func main() {
+}
diff --git a/test/linkmain_run.go b/test/linkmain_run.go
new file mode 100644 (file)
index 0000000..a5d2c79
--- /dev/null
@@ -0,0 +1,65 @@
+// +build !nacl
+// run
+
+// Copyright 2014 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.
+
+// Run the sinit test.
+
+package main
+
+import (
+       "fmt"
+       "os"
+       "os/exec"
+       "strings"
+)
+
+func cleanup() {
+       os.Remove("linkmain.o")
+       os.Remove("linkmain.a")
+       os.Remove("linkmain1.o")
+       os.Remove("linkmain1.a")
+       os.Remove("linkmain.exe")
+}
+
+func run(cmdline string) {
+       args := strings.Fields(cmdline)
+       cmd := exec.Command(args[0], args[1:]...)
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               fmt.Printf("$ %s\n", strings.Join(args, " "))
+               fmt.Println(string(out))
+               fmt.Println(err)
+               cleanup()
+               os.Exit(1)
+       }
+}
+
+func runFail(args ...string) {
+       cmd := exec.Command(args[0], args[1:]...)
+       out, err := cmd.CombinedOutput()
+       if err == nil {
+               fmt.Printf("$ %s\n", strings.Join(args, " "))
+               fmt.Println(string(out))
+               fmt.Println("SHOULD HAVE FAILED!")
+               cleanup()
+               os.Exit(1)
+       }
+}
+
+func main() {
+       // helloworld.go is package main
+       run("go tool compile -o linkmain.o helloworld.go")
+       run("go tool compile -pack -o linkmain.a helloworld.go")
+       run("go tool link -o linkmain.exe linkmain.o")
+       run("go tool link -o linkmain.exe linkmain.a")
+
+       // linkmain.go is not
+       run("go tool compile -o linkmain.o linkmain.go")
+       run("go tool compile -pack -o linkmain.a linkmain.go")
+       runFail("go tool link -o linkmain.exe linkmain1.o")
+       runFail("go tool link -o linkmain.exe linkmain1.a")
+       cleanup()
+}