Commit 6f31abd2 authored by David Crawshaw's avatar David Crawshaw

cmd/compile, cmd/link: weak relocation for ptrTo

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: default avatarIan Lance Taylor <iant@golang.org>
parent aeaa4c3c
...@@ -354,6 +354,12 @@ func dsymptrOffLSym(s *obj.LSym, off int, x *obj.LSym, xoff int) int { ...@@ -354,6 +354,12 @@ func dsymptrOffLSym(s *obj.LSym, off int, x *obj.LSym, xoff int) int {
return off 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) { func gdata(nam *Node, nr *Node, wid int) {
if nam.Op != ONAME { if nam.Op != ONAME {
Fatalf("gdata nam op %v", nam.Op) Fatalf("gdata nam op %v", nam.Op)
......
...@@ -834,9 +834,13 @@ func dcommontype(s *Sym, ot int, t *Type) int { ...@@ -834,9 +834,13 @@ func dcommontype(s *Sym, ot int, t *Type) int {
algsym = dalgsym(t) algsym = dalgsym(t)
} }
sptrWeak := true
var sptr *Sym var sptr *Sym
tptr := ptrto(t) if !t.IsPtr() || t.ptrTo != nil {
if !t.IsPtr() && (t.Sym != nil || methods(tptr) != nil) { tptr := ptrto(t)
if t.Sym != nil || methods(tptr) != nil {
sptrWeak = false
}
sptr = dtypesym(tptr) sptr = dtypesym(tptr)
} }
...@@ -923,10 +927,13 @@ func dcommontype(s *Sym, ot int, t *Type) int { ...@@ -923,10 +927,13 @@ func dcommontype(s *Sym, ot int, t *Type) int {
nsym := dname(p, "", nil, exported) nsym := dname(p, "", nil, exported)
ot = dsymptrOffLSym(Linksym(s), ot, nsym, 0) // str ot = dsymptrOffLSym(Linksym(s), ot, nsym, 0) // str
// ptrToThis
if sptr == nil { if sptr == nil {
ot = duint32(s, ot, 0) ot = duint32(s, ot, 0)
} else if sptrWeak {
ot = dsymptrWeakOffLSym(Linksym(s), ot, Linksym(sptr))
} else { } else {
ot = dsymptrOffLSym(Linksym(s), ot, Linksym(sptr), 0) // ptrToThis ot = dsymptrOffLSym(Linksym(s), ot, Linksym(sptr), 0)
} }
return ot return ot
......
...@@ -145,6 +145,22 @@ func (s *LSym) WriteOff(ctxt *Link, off int64, rsym *LSym, roff int64) { ...@@ -145,6 +145,22 @@ func (s *LSym) WriteOff(ctxt *Link, off int64, rsym *LSym, roff int64) {
r.Add = roff 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. // WriteString writes a string of size siz into s at offset off.
func (s *LSym) WriteString(ctxt *Link, off int64, siz int, str string) { func (s *LSym) WriteString(ctxt *Link, off int64, siz int, str string) {
if siz < len(str) { if siz < len(str) {
......
...@@ -538,6 +538,11 @@ const ( ...@@ -538,6 +538,11 @@ const (
// R_ADDROFF resolves to a 32-bit offset from the beginning of the section // R_ADDROFF resolves to a 32-bit offset from the beginning of the section
// holding the data being relocated to the referenced symbol. // holding the data being relocated to the referenced symbol.
R_ADDROFF 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_SIZE
R_CALL R_CALL
R_CALLARM R_CALLARM
......
...@@ -413,7 +413,7 @@ func relocsym(ctxt *Link, s *Symbol) { ...@@ -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) 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) Errorf(s, "unreachable sym in relocation: %s", r.Sym.Name)
} }
...@@ -588,6 +588,11 @@ func relocsym(ctxt *Link, s *Symbol) { ...@@ -588,6 +588,11 @@ func relocsym(ctxt *Link, s *Symbol) {
} }
o = Symaddr(r.Sym) + r.Add - int64(r.Sym.Sect.Vaddr) 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: case obj.R_ADDROFF:
// The method offset tables using this relocation expect the offset to be relative // 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. // to the start of the first text section, even if there are multiple.
...@@ -748,6 +753,9 @@ func dynrelocsym(ctxt *Link, s *Symbol) { ...@@ -748,6 +753,9 @@ func dynrelocsym(ctxt *Link, s *Symbol) {
continue continue
} }
if !targ.Attr.Reachable() { if !targ.Attr.Reachable() {
if r.Type == obj.R_WEAKADDROFF {
continue
}
Errorf(s, "dynamic relocation to unreachable symbol %s", targ.Name) 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. if r.Sym.Plt == -2 && r.Sym.Got != -2 { // make dynimport JMP table for PE object files.
......
...@@ -308,6 +308,12 @@ func (d *deadcodepass) flood() { ...@@ -308,6 +308,12 @@ func (d *deadcodepass) flood() {
if r.Sym == nil { if r.Sym == nil {
continue 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 { if r.Type != obj.R_METHODOFF {
d.mark(r.Sym, s) d.mark(r.Sym, s)
continue continue
......
...@@ -2033,7 +2033,7 @@ func undefsym(ctxt *Link, s *Symbol) { ...@@ -2033,7 +2033,7 @@ func undefsym(ctxt *Link, s *Symbol) {
if r.Sym.Type == obj.Sxxx || r.Sym.Type == obj.SXREF { if r.Sym.Type == obj.Sxxx || r.Sym.Type == obj.SXREF {
Errorf(s, "undefined: %q", r.Sym.Name) 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) Errorf(s, "relocation target %q", r.Sym.Name)
} }
} }
......
...@@ -2674,6 +2674,7 @@ func StructOf(fields []StructField) Type { ...@@ -2674,6 +2674,7 @@ func StructOf(fields []StructField) Type {
typ.size = size typ.size = size
typ.align = typalign typ.align = typalign
typ.fieldAlign = typalign typ.fieldAlign = typalign
typ.ptrToThis = 0
if len(methods) > 0 { if len(methods) > 0 {
typ.tflag |= tflagUncommon typ.tflag |= tflagUncommon
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment