1
0
mirror of https://github.com/golang/go synced 2024-10-02 06:18:32 -06:00

cmd/compile: do not write slices/strings > 2g

The linker will refuse to work on objects larger than
2e9 bytes (see issue #9862 for why).

With this change, the compiler gives a useful error
message explaining this, instead of leaving it to the
linker to give a cryptic message later.

Fixes #1700.

Change-Id: I3933ce08ef846721ece7405bdba81dff644cb004
Reviewed-on: https://go-review.googlesource.com/74330
Reviewed-by: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Jeff R. Allen 2017-11-08 09:43:56 +01:00 committed by Robert Griesemer
parent 8fc64a3060
commit d7ac9bb992
4 changed files with 20 additions and 9 deletions

View File

@ -9,6 +9,7 @@ import (
"cmd/internal/bio"
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/src"
"crypto/sha256"
"fmt"
"io"
@ -330,7 +331,7 @@ func dbvec(s *obj.LSym, off int, bv bvec) int {
return off
}
func stringsym(s string) (data *obj.LSym) {
func stringsym(pos src.XPos, s string) (data *obj.LSym) {
var symname string
if len(s) > 100 {
// Huge strings are hashed to avoid long names in object files.
@ -351,7 +352,7 @@ func stringsym(s string) (data *obj.LSym) {
if !symdata.SeenGlobl() {
// string data
off := dsname(symdata, 0, s)
off := dsname(symdata, 0, s, pos, "string")
ggloblsym(symdata, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
}
@ -367,7 +368,7 @@ func slicebytes(nam *Node, s string, len int) {
sym.Def = asTypesNode(newname(sym))
lsym := sym.Linksym()
off := dsname(lsym, 0, s)
off := dsname(lsym, 0, s, nam.Pos, "slice")
ggloblsym(lsym, int32(off), obj.NOPTR|obj.LOCAL)
if nam.Op != ONAME {
@ -380,7 +381,15 @@ func slicebytes(nam *Node, s string, len int) {
duintptr(nsym, off, uint64(len))
}
func dsname(s *obj.LSym, off int, t string) int {
func dsname(s *obj.LSym, off int, t string, pos src.XPos, what string) int {
// Objects that are too large will cause the data section to overflow right away,
// causing a cryptic error message by the linker. Check for oversize objects here
// and provide a useful error message instead.
if int64(len(t)) > 2e9 {
yyerrorl(pos, "%v with length %v is too big", what, len(t))
return 0
}
s.WriteString(Ctxt, int64(off), len(t), t)
return off + len(t)
}
@ -445,7 +454,7 @@ func gdata(nam *Node, nr *Node, wid int) {
}
case string:
symdata := stringsym(u)
symdata := stringsym(nam.Pos, u)
s.WriteAddr(Ctxt, nam.Xoffset, Widthptr, symdata, 0)
s.WriteInt(Ctxt, nam.Xoffset+int64(Widthptr), Widthptr, int64(len(u)))

View File

@ -5067,7 +5067,7 @@ func (e *ssafn) StringData(s string) interface{} {
if e.strings == nil {
e.strings = make(map[string]interface{})
}
data := stringsym(s)
data := stringsym(e.curfn.Pos, s)
e.strings[s] = data
return data
}

View File

@ -1744,7 +1744,7 @@ opswitch:
// Emit string symbol now to avoid emitting
// any concurrently during the backend.
if s, ok := n.Val().U.(string); ok {
_ = stringsym(s)
_ = stringsym(n.Pos, s)
}
}

View File

@ -1008,11 +1008,13 @@ func (d bySizeAndName) Less(i, j int) bool {
return s1.name < s2.name
}
const cutoff int64 = 2e9 // 2 GB (or so; looks better in errors than 2^31)
// cutoff is the maximum data section size permitted by the linker
// (see issue #9862).
const cutoff = 2e9 // 2 GB (or so; looks better in errors than 2^31)
func checkdatsize(ctxt *Link, datsize int64, symn sym.SymKind) {
if datsize > cutoff {
Errorf(nil, "too much data in section %v (over %d bytes)", symn, cutoff)
Errorf(nil, "too much data in section %v (over %v bytes)", symn, cutoff)
}
}