diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 2075066e31..4b23ecc483 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -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) diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index 4ec03abc85..6ed751abb5 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -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") +}