]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj: use correct symbol size for Hashed64 classification
authorCherry Zhang <cherryyz@google.com>
Thu, 22 Oct 2020 14:05:44 +0000 (10:05 -0400)
committerCherry Zhang <cherryyz@google.com>
Thu, 22 Oct 2020 18:16:29 +0000 (18:16 +0000)
Use sym.Size, instead of len(sym.P), to decide whether a
content-addressable symbol is "short" and hashed as Hashed64.
So we don't dedup a small symbol with a gigantic almost-zero
symbol.

Fixes #42140.

Change-Id: Ic65869e1eaf51947517b3ece49c8b0be1b94bb75
Reviewed-on: https://go-review.googlesource.com/c/go/+/264337
Trust: Cherry Zhang <cherryyz@google.com>
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/internal/obj/sym.go
src/cmd/link/link_test.go

index 0182773f8e454b8cd4675408ce362f48145a4917..4515bdd0d3a20cd8e3e6ee53d1d5b6046f54f5ad 100644 (file)
@@ -205,7 +205,7 @@ func (ctxt *Link) NumberSyms() {
                // if Pkgpath is unknown, cannot hash symbols with relocations, as it
                // may reference named symbols whose names are not fully expanded.
                if s.ContentAddressable() && (ctxt.Pkgpath != "" || len(s.R) == 0) {
-                       if len(s.P) <= 8 && len(s.R) == 0 && !strings.HasPrefix(s.Name, "type.") {
+                       if s.Size <= 8 && len(s.R) == 0 && !strings.HasPrefix(s.Name, "type.") {
                                // We can use short hash only for symbols without relocations.
                                // Don't use short hash for type symbols, as they need special handling.
                                s.PkgIdx = goobj.PkgIdxHashed64
index 968da4837db41d204cb178dc87080bb8ae45b805..204410e9768135682b169b8ec281ae47c76b0ffc 100644 (file)
@@ -820,3 +820,56 @@ func TestReadOnly(t *testing.T) {
                t.Errorf("running test program did not fail. output:\n%s", out)
        }
 }
+
+const testIssue38554Src = `
+package main
+
+type T [10<<20]byte
+
+//go:noinline
+func f() T {
+       return T{} // compiler will make a large stmp symbol, but not used.
+}
+
+func main() {
+       x := f()
+       println(x[1])
+}
+`
+
+func TestIssue38554(t *testing.T) {
+       testenv.MustHaveGoBuild(t)
+
+       t.Parallel()
+
+       tmpdir, err := ioutil.TempDir("", "TestIssue38554")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer os.RemoveAll(tmpdir)
+
+       src := filepath.Join(tmpdir, "x.go")
+       err = ioutil.WriteFile(src, []byte(testIssue38554Src), 0666)
+       if err != nil {
+               t.Fatalf("failed to write source file: %v", err)
+       }
+       exe := filepath.Join(tmpdir, "x.exe")
+       cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, src)
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("build failed: %v\n%s", err, out)
+       }
+
+       fi, err := os.Stat(exe)
+       if err != nil {
+               t.Fatalf("failed to stat output file: %v", err)
+       }
+
+       // The test program is not much different from a helloworld, which is
+       // typically a little over 1 MB. We allow 5 MB. If the bad stmp is live,
+       // it will be over 10 MB.
+       const want = 5 << 20
+       if got := fi.Size(); got > want {
+               t.Errorf("binary too big: got %d, want < %d", got, want)
+       }
+}