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)
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)
}
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
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) {
// 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
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)
}
}
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.
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.
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
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)
}
}
typ.size = size
typ.align = typalign
typ.fieldAlign = typalign
+ typ.ptrToThis = 0
if len(methods) > 0 {
typ.tflag |= tflagUncommon
}