Skip to content

Commit 484fc06

Browse files
committed
cmd/link: don't link sections not named .o
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 90df377 commit 484fc06

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

src/cmd/link/internal/ld/lib.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,13 @@ func loadobjfile(ctxt *Link, lib *sym.Library) {
856856
continue
857857
}
858858

859+
// Skip other special (non-object-file) sections that
860+
// build tools may have added. Such sections must have
861+
// short names so that the suffix is not truncated.
862+
if len(arhdr.name) < 16 && !strings.HasSuffix(arhdr.name, ".o") {
863+
continue
864+
}
865+
859866
pname := fmt.Sprintf("%s(%s)", lib.File, arhdr.name)
860867
l = atolwhex(arhdr.size)
861868
ldobj(ctxt, f, lib, l, pname, lib.File)

src/cmd/link/link_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os"
77
"os/exec"
88
"path/filepath"
9+
"strings"
910
"testing"
1011
)
1112

@@ -70,3 +71,48 @@ func main() {}
7071
t.Fatalf("failed to link main.o: %v, output: %s\n", err, out)
7172
}
7273
}
74+
75+
// TestIssue28429 ensures that the linker does not attempt to link
76+
// sections not named *.o. Such sections may be used by a build system
77+
// to, for example, save facts produced by a modular static analysis
78+
// such as golang.org/x/tools/go/analysis.
79+
func TestIssue28429(t *testing.T) {
80+
testenv.MustHaveGoBuild(t)
81+
82+
tmpdir, err := ioutil.TempDir("", "issue28429-")
83+
if err != nil {
84+
t.Fatalf("failed to create temp dir: %v", err)
85+
}
86+
defer os.RemoveAll(tmpdir)
87+
88+
write := func(name, content string) {
89+
err := ioutil.WriteFile(filepath.Join(tmpdir, name), []byte(content), 0666)
90+
if err != nil {
91+
t.Fatal(err)
92+
}
93+
}
94+
95+
runGo := func(args ...string) {
96+
cmd := exec.Command(testenv.GoToolPath(t), args...)
97+
cmd.Dir = tmpdir
98+
out, err := cmd.CombinedOutput()
99+
if err != nil {
100+
t.Fatalf("'go %s' failed: %v, output: %s",
101+
strings.Join(args, " "), err, out)
102+
}
103+
}
104+
105+
// Compile a main package.
106+
write("main.go", "package main; func main() {}")
107+
runGo("tool", "compile", "-p", "main", "main.go")
108+
runGo("tool", "pack", "c", "main.a", "main.o")
109+
110+
// Add an extra section with a short, non-.o name.
111+
// This simulates an alternative build system.
112+
write(".facts", "this is not an object file")
113+
runGo("tool", "pack", "r", "main.a", ".facts")
114+
115+
// Verify that the linker does not attempt
116+
// to compile the extra section.
117+
runGo("tool", "link", "main.a")
118+
}

0 commit comments

Comments
 (0)