]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: don't link sections not named .o
authorAlan Donovan <adonovan@google.com>
Wed, 31 Oct 2018 17:18:17 +0000 (13:18 -0400)
committerAlan Donovan <adonovan@google.com>
Fri, 2 Nov 2018 00:23:21 +0000 (00:23 +0000)
For many build systems, modular static analysis is most conveniently
implemented by saving analysis facts (which are analogous to export
data) in an additional section in the archive file, similar to
__PKGDEF. See golang.org/x/tools/go/analysis for an overview.

Because such sections are not object files, the linker must not
attempt to link them. This change causes the linker to skip special
sections whose name does not end with .o (and is short enough not to
be truncated).

Fixes #28429

Change-Id: I830852decf868cb017263308b114f72838032993
Reviewed-on: https://go-review.googlesource.com/c/146297
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/link/internal/ld/lib.go
src/cmd/link/link_test.go

index 2075066e31b3c76264f97b5bb0f11a69126bdc09..4b23ecc4834bde3c32ce5750aae0ecf69839b8db 100644 (file)
@@ -856,6 +856,13 @@ func loadobjfile(ctxt *Link, lib *sym.Library) {
                        continue
                }
 
+               // Skip other special (non-object-file) sections that
+               // build tools may have added. Such sections must have
+               // short names so that the suffix is not truncated.
+               if len(arhdr.name) < 16 && !strings.HasSuffix(arhdr.name, ".o") {
+                       continue
+               }
+
                pname := fmt.Sprintf("%s(%s)", lib.File, arhdr.name)
                l = atolwhex(arhdr.size)
                ldobj(ctxt, f, lib, l, pname, lib.File)
index 4ec03abc8587151bcc2c4ead5e9b80700e146f65..6ed751abb5f792ddc36a75cf572839e8446fe3cb 100644 (file)
@@ -6,6 +6,7 @@ import (
        "os"
        "os/exec"
        "path/filepath"
+       "strings"
        "testing"
 )
 
@@ -70,3 +71,48 @@ func main() {}
                t.Fatalf("failed to link main.o: %v, output: %s\n", err, out)
        }
 }
+
+// TestIssue28429 ensures that the linker does not attempt to link
+// sections not named *.o. Such sections may be used by a build system
+// to, for example, save facts produced by a modular static analysis
+// such as golang.org/x/tools/go/analysis.
+func TestIssue28429(t *testing.T) {
+       testenv.MustHaveGoBuild(t)
+
+       tmpdir, err := ioutil.TempDir("", "issue28429-")
+       if err != nil {
+               t.Fatalf("failed to create temp dir: %v", err)
+       }
+       defer os.RemoveAll(tmpdir)
+
+       write := func(name, content string) {
+               err := ioutil.WriteFile(filepath.Join(tmpdir, name), []byte(content), 0666)
+               if err != nil {
+                       t.Fatal(err)
+               }
+       }
+
+       runGo := func(args ...string) {
+               cmd := exec.Command(testenv.GoToolPath(t), args...)
+               cmd.Dir = tmpdir
+               out, err := cmd.CombinedOutput()
+               if err != nil {
+                       t.Fatalf("'go %s' failed: %v, output: %s",
+                               strings.Join(args, " "), err, out)
+               }
+       }
+
+       // Compile a main package.
+       write("main.go", "package main; func main() {}")
+       runGo("tool", "compile", "-p", "main", "main.go")
+       runGo("tool", "pack", "c", "main.a", "main.o")
+
+       // Add an extra section with a short, non-.o name.
+       // This simulates an alternative build system.
+       write(".facts", "this is not an object file")
+       runGo("tool", "pack", "r", "main.a", ".facts")
+
+       // Verify that the linker does not attempt
+       // to compile the extra section.
+       runGo("tool", "link", "main.a")
+}