]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile, cmd/link: weak relocation for ptrTo
authorDavid Crawshaw <crawshaw@golang.org>
Mon, 21 Nov 2016 21:58:55 +0000 (16:58 -0500)
committerDavid Crawshaw <crawshaw@golang.org>
Tue, 22 Nov 2016 03:10:14 +0000 (03:10 +0000)
Introduce R_WEAKADDROFF, a "weak" variation of the R_ADDROFF relocation
that will only reference the type described if it is in some other way
reachable.

Use this for the ptrToThis field in reflect type information where it
is safe to do so (that is, types that don't need to be included for
interface satisfaction, and types that won't cause the compiler to
recursively generate an endless series of ptr-to-ptr-to-ptr-to...
types).

Also fix a small bug in reflect, where StructOf was not clearing the
ptrToThis field of new types.

Fixes #17931

Change-Id: I4d3b53cb9c916c97b3b16e367794eee142247281
Reviewed-on: https://go-review.googlesource.com/33427
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/compile/internal/gc/obj.go
src/cmd/compile/internal/gc/reflect.go
src/cmd/internal/obj/data.go
src/cmd/internal/obj/link.go
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/deadcode.go
src/cmd/link/internal/ld/lib.go
src/reflect/type.go

index a5a2e707f6edd4b2e04b5364b94e7276c4ef55c9..08ed5604dadee55ac40c9b780f2b77de53f46c58 100644 (file)
@@ -354,6 +354,12 @@ func dsymptrOffLSym(s *obj.LSym, off int, x *obj.LSym, xoff int) int {
        return off
 }
 
+func dsymptrWeakOffLSym(s *obj.LSym, off int, x *obj.LSym) int {
+       s.WriteWeakOff(Ctxt, int64(off), x, 0)
+       off += 4
+       return off
+}
+
 func gdata(nam *Node, nr *Node, wid int) {
        if nam.Op != ONAME {
                Fatalf("gdata nam op %v", nam.Op)
index ed1733ee2359e9f5a4d7b6da2f57aa44fdadf9ba..4f9d92ed8a1333adbdc178332d8c275b919f988f 100644 (file)
@@ -834,9 +834,13 @@ func dcommontype(s *Sym, ot int, t *Type) int {
                algsym = dalgsym(t)
        }
 
+       sptrWeak := true
        var sptr *Sym
-       tptr := ptrto(t)
-       if !t.IsPtr() && (t.Sym != nil || methods(tptr) != nil) {
+       if !t.IsPtr() || t.ptrTo != nil {
+               tptr := ptrto(t)
+               if t.Sym != nil || methods(tptr) != nil {
+                       sptrWeak = false
+               }
                sptr = dtypesym(tptr)
        }
 
@@ -923,10 +927,13 @@ func dcommontype(s *Sym, ot int, t *Type) int {
 
        nsym := dname(p, "", nil, exported)
        ot = dsymptrOffLSym(Linksym(s), ot, nsym, 0) // str
+       // ptrToThis
        if sptr == nil {
                ot = duint32(s, ot, 0)
+       } else if sptrWeak {
+               ot = dsymptrWeakOffLSym(Linksym(s), ot, Linksym(sptr))
        } else {
-               ot = dsymptrOffLSym(Linksym(s), ot, Linksym(sptr), 0) // ptrToThis
+               ot = dsymptrOffLSym(Linksym(s), ot, Linksym(sptr), 0)
        }
 
        return ot
index 0ccb053fdc66e8576a7d514b3d2cdbe866ba971d..d5565f24dcfc65e6783a4d67c4cddce2f997d74a 100644 (file)
@@ -145,6 +145,22 @@ func (s *LSym) WriteOff(ctxt *Link, off int64, rsym *LSym, roff int64) {
        r.Add = roff
 }
 
+// WriteWeakOff writes a weak 4 byte offset to rsym+roff into s at offset off.
+// After linking the 4 bytes stored at s+off will be
+// rsym+roff-(start of section that s is in).
+func (s *LSym) WriteWeakOff(ctxt *Link, off int64, rsym *LSym, roff int64) {
+       s.prepwrite(ctxt, off, 4)
+       r := Addrel(s)
+       r.Off = int32(off)
+       if int64(r.Off) != off {
+               ctxt.Diag("WriteOff: off overflow %d in %s", off, s.Name)
+       }
+       r.Siz = 4
+       r.Sym = rsym
+       r.Type = R_WEAKADDROFF
+       r.Add = roff
+}
+
 // WriteString writes a string of size siz into s at offset off.
 func (s *LSym) WriteString(ctxt *Link, off int64, siz int, str string) {
        if siz < len(str) {
index f2874bafbcbb4d090c986094251f232e6d1d591b..2ab2aec9263ff70361111b00b8323286678a22c9 100644 (file)
@@ -538,6 +538,11 @@ const (
        // R_ADDROFF resolves to a 32-bit offset from the beginning of the section
        // holding the data being relocated to the referenced symbol.
        R_ADDROFF
+       // R_WEAKADDROFF resolves just like R_ADDROFF but is a weak relocation.
+       // A weak relocation does not make the symbol it refers to reachable,
+       // and is only honored by the linker if the symbol is in some other way
+       // reachable.
+       R_WEAKADDROFF
        R_SIZE
        R_CALL
        R_CALLARM
index de043305d0c525e847759d3e748ce32fb4f381fc..eaf6aa20808b0a288354a8195d6ca84931899886 100644 (file)
@@ -413,7 +413,7 @@ func relocsym(ctxt *Link, s *Symbol) {
                                Errorf(s, "unhandled relocation for %s (type %d rtype %d)", r.Sym.Name, r.Sym.Type, r.Type)
                        }
                }
-               if r.Sym != nil && r.Sym.Type != obj.STLSBSS && !r.Sym.Attr.Reachable() {
+               if r.Sym != nil && r.Sym.Type != obj.STLSBSS && r.Type != obj.R_WEAKADDROFF && !r.Sym.Attr.Reachable() {
                        Errorf(s, "unreachable sym in relocation: %s", r.Sym.Name)
                }
 
@@ -588,6 +588,11 @@ func relocsym(ctxt *Link, s *Symbol) {
                        }
                        o = Symaddr(r.Sym) + r.Add - int64(r.Sym.Sect.Vaddr)
 
+               case obj.R_WEAKADDROFF:
+                       if !r.Sym.Attr.Reachable() {
+                               continue
+                       }
+                       fallthrough
                case obj.R_ADDROFF:
                        // The method offset tables using this relocation expect the offset to be relative
                        // to the start of the first text section, even if there are multiple.
@@ -748,6 +753,9 @@ func dynrelocsym(ctxt *Link, s *Symbol) {
                                continue
                        }
                        if !targ.Attr.Reachable() {
+                               if r.Type == obj.R_WEAKADDROFF {
+                                       continue
+                               }
                                Errorf(s, "dynamic relocation to unreachable symbol %s", targ.Name)
                        }
                        if r.Sym.Plt == -2 && r.Sym.Got != -2 { // make dynimport JMP table for PE object files.
index c0c0c6bcf435a701a7ff72d1bfe3e2795bf1340b..ae516818f5a404ede12ac5f391f2a979b28ce7e6 100644 (file)
@@ -308,6 +308,12 @@ func (d *deadcodepass) flood() {
                        if r.Sym == nil {
                                continue
                        }
+                       if r.Type == obj.R_WEAKADDROFF {
+                               // An R_WEAKADDROFF relocation is not reason
+                               // enough to mark the pointed-to symbol as
+                               // reachable.
+                               continue
+                       }
                        if r.Type != obj.R_METHODOFF {
                                d.mark(r.Sym, s)
                                continue
index e4c34750c771aa16782a0786779f7249e65f6d1d..fb321905e15d7bc3c97f20fbfde551a300cd5dce 100644 (file)
@@ -2033,7 +2033,7 @@ func undefsym(ctxt *Link, s *Symbol) {
                if r.Sym.Type == obj.Sxxx || r.Sym.Type == obj.SXREF {
                        Errorf(s, "undefined: %q", r.Sym.Name)
                }
-               if !r.Sym.Attr.Reachable() {
+               if !r.Sym.Attr.Reachable() && r.Type != obj.R_WEAKADDROFF {
                        Errorf(s, "relocation target %q", r.Sym.Name)
                }
        }
index 28276a5ac0c01d543ff674f6747d5ca2b127725f..4985ba81653eaa79e2bced2734fdbc4575679824 100644 (file)
@@ -2674,6 +2674,7 @@ func StructOf(fields []StructField) Type {
        typ.size = size
        typ.align = typalign
        typ.fieldAlign = typalign
+       typ.ptrToThis = 0
        if len(methods) > 0 {
                typ.tflag |= tflagUncommon
        }