]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: support external linking in new reloc implementation
authorCherry Zhang <cherryyz@google.com>
Sun, 26 Apr 2020 05:42:55 +0000 (01:42 -0400)
committerCherry Zhang <cherryyz@google.com>
Wed, 29 Apr 2020 15:31:14 +0000 (15:31 +0000)
Support external linking for the new reloc pass as well, and
enable it on AMD64 and 386.

Change-Id: Ia71aec3d7c14e9d661e0748d2e988f29f220d1e1
Reviewed-on: https://go-review.googlesource.com/c/go/+/230308
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/main.go
src/cmd/link/internal/loader/loader.go

index 187f915a82f7333eeecbe0d3da544dfb18326b0e..d895c62f392815abbc158e5da338b309b9bb9611 100644 (file)
@@ -120,6 +120,20 @@ func trampoline(ctxt *Link, s loader.Sym) {
 
 }
 
+// foldSubSymbolOffset computes the offset of symbol s to its top-level outer
+// symbol. Returns the top-level symbol and the offset.
+// This is used in generating external relocations.
+func foldSubSymbolOffset(ldr *loader.Loader, s loader.Sym) (loader.Sym, int64) {
+       outer := ldr.OuterSym(s)
+       off := int64(0)
+       for outer != 0 {
+               off += ldr.SymValue(s) - ldr.SymValue(outer)
+               s = outer
+               outer = ldr.OuterSym(s)
+       }
+       return s, off
+}
+
 // relocsym resolve relocations in "s", updating the symbol's content
 // in "P".
 // The main loop walks through the list of relocations attached to "s"
@@ -141,6 +155,7 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
        if relocs.Count() == 0 {
                return
        }
+       var extRelocs []loader.ExtReloc
        for ri := 0; ri < relocs.Count(); ri++ {
                r := relocs.At2(ri)
                off := r.Off()
@@ -200,9 +215,14 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
                        err.Errorf(s, "unreachable sym in relocation: %s", ldr.SymName(rs))
                }
 
+               var rr loader.ExtReloc
+               needExtReloc := false // will set to true below in case it is needed
                if target.IsExternal() {
-                       panic("external linking not implemented")
-                       //r.InitExt()
+                       rr.Sym = rs
+                       rr.Type = rt
+                       rr.Off = off
+                       rr.Siz = uint8(siz)
+                       rr.Add = r.Add()
                }
 
                // TODO(mundaym): remove this special case - see issue 14218.
@@ -239,19 +259,19 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
                                err.Errorf(s, "unknown reloc to %v: %d (%s)", ldr.SymName(rs), rt, sym.RelocName(target.Arch, rt))
                        }
                case objabi.R_TLS_LE:
-                       //if target.IsExternal() && target.IsElf() {
-                       //      r.Done = false
-                       //      if r.Sym == nil {
-                       //              r.Sym = syms.Tlsg
-                       //      }
-                       //      r.Xsym = r.Sym
-                       //      r.Xadd = r.Add
-                       //      o = 0
-                       //      if !target.IsAMD64() {
-                       //              o = r.Add
-                       //      }
-                       //      break
-                       //}
+                       if target.IsExternal() && target.IsElf() {
+                               needExtReloc = true
+                               if rr.Sym == 0 {
+                                       rr.Sym = syms.Tlsg2
+                               }
+                               rr.Xsym = rr.Sym
+                               rr.Xadd = rr.Add
+                               o = 0
+                               if !target.IsAMD64() {
+                                       o = rr.Add
+                               }
+                               break
+                       }
 
                        if target.IsElf() && target.IsARM() {
                                // On ELF ARM, the thread pointer is 8 bytes before
@@ -270,19 +290,19 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
                                log.Fatalf("unexpected R_TLS_LE relocation for %v", target.HeadType)
                        }
                case objabi.R_TLS_IE:
-                       //if target.IsExternal() && target.IsElf() {
-                       //      r.Done = false
-                       //      if r.Sym == nil {
-                       //              r.Sym = syms.Tlsg
-                       //      }
-                       //      r.Xsym = r.Sym
-                       //      r.Xadd = r.Add
-                       //      o = 0
-                       //      if !target.IsAMD64() {
-                       //              o = r.Add
-                       //      }
-                       //      break
-                       //}
+                       if target.IsExternal() && target.IsElf() {
+                               needExtReloc = true
+                               if rr.Sym == 0 {
+                                       rr.Sym = syms.Tlsg2
+                               }
+                               rr.Xsym = rr.Sym
+                               rr.Xadd = rr.Add
+                               o = 0
+                               if !target.IsAMD64() {
+                                       o = rr.Add
+                               }
+                               break
+                       }
                        if target.IsPIE() && target.IsElf() {
                                // We are linking the final executable, so we
                                // can optimize any TLS IE relocation to LE.
@@ -295,42 +315,38 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
                                log.Fatalf("cannot handle R_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
                        }
                case objabi.R_ADDR:
-                       //if target.IsExternal() && r.Sym.Type != sym.SCONST {
-                       //      r.Done = false
-                       //
-                       //      // set up addend for eventual relocation via outer symbol.
-                       //      rs := r.Sym
-                       //
-                       //      r.Xadd = r.Add
-                       //      for rs.Outer != nil {
-                       //              r.Xadd += Symaddr(rs) - Symaddr(rs.Outer)
-                       //              rs = rs.Outer
-                       //      }
-                       //
-                       //      if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
-                       //              Errorf(s, "missing section for relocation target %s", rs.Name)
-                       //      }
-                       //      r.Xsym = rs
-                       //
-                       //      o = r.Xadd
-                       //      if target.IsElf() {
-                       //              if target.IsAMD64() {
-                       //                      o = 0
-                       //              }
-                       //      } else if target.IsDarwin() {
-                       //              if rs.Type != sym.SHOSTOBJ {
-                       //                      o += Symaddr(rs)
-                       //              }
-                       //      } else if target.IsWindows() {
-                       //              // nothing to do
-                       //      } else if target.IsAIX() {
-                       //              o = Symaddr(r.Sym) + r.Add
-                       //      } else {
-                       //              Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, target.HeadType)
-                       //      }
-                       //
-                       //      break
-                       //}
+                       if target.IsExternal() && rst != sym.SCONST {
+                               needExtReloc = true
+
+                               // set up addend for eventual relocation via outer symbol.
+                               rs := rs
+                               rs, off := foldSubSymbolOffset(ldr, rs)
+                               rr.Xadd = rr.Add + off
+                               rst := ldr.SymType(rs)
+                               if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && rst != sym.SUNDEFEXT && ldr.SymSect(rs) == nil {
+                                       err.Errorf(s, "missing section for relocation target %s", ldr.SymName(rs))
+                               }
+                               rr.Xsym = rs
+
+                               o = rr.Xadd
+                               if target.IsElf() {
+                                       if target.IsAMD64() {
+                                               o = 0
+                                       }
+                               } else if target.IsDarwin() {
+                                       if ldr.SymType(rs) != sym.SHOSTOBJ {
+                                               o += ldr.SymValue(rs)
+                                       }
+                               } else if target.IsWindows() {
+                                       // nothing to do
+                               } else if target.IsAIX() {
+                                       o = ldr.SymValue(rr.Sym) + rr.Add
+                               } else {
+                                       err.Errorf(s, "unhandled pcrel relocation to %s on %v", ldr.SymName(rs), target.HeadType)
+                               }
+
+                               break
+                       }
 
                        // On AIX, a second relocation must be done by the loader,
                        // as section addresses can change once loaded.
@@ -343,6 +359,7 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
                                // symbol which isn't in .data. However, as .text has the
                                // same address once loaded, this is possible.
                                if ldr.SymSect(s).Seg == &Segdata {
+                                       panic("not implemented")
                                        //Xcoffadddynrel(target, ldr, err, s, &r) // XXX
                                }
                        }
@@ -363,36 +380,36 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
                                err.Errorf(s, "missing DWARF section for relocation target %s", ldr.SymName(rs))
                        }
 
-                       //if target.IsExternal() {
-                       //      r.Done = false
-                       //
-                       //      // On most platforms, the external linker needs to adjust DWARF references
-                       //      // as it combines DWARF sections. However, on Darwin, dsymutil does the
-                       //      // DWARF linking, and it understands how to follow section offsets.
-                       //      // Leaving in the relocation records confuses it (see
-                       //      // https://golang.org/issue/22068) so drop them for Darwin.
-                       //      if target.IsDarwin() {
-                       //              r.Done = true
-                       //      }
-                       //
-                       //      // PE code emits IMAGE_REL_I386_SECREL and IMAGE_REL_AMD64_SECREL
-                       //      // for R_DWARFSECREF relocations, while R_ADDR is replaced with
-                       //      // IMAGE_REL_I386_DIR32, IMAGE_REL_AMD64_ADDR64 and IMAGE_REL_AMD64_ADDR32.
-                       //      // Do not replace R_DWARFSECREF with R_ADDR for windows -
-                       //      // let PE code emit correct relocations.
-                       //      if !target.IsWindows() {
-                       //              r.Type = objabi.R_ADDR
-                       //      }
-                       //
-                       //      r.Xsym = r.Sym.Sect.Sym
-                       //      r.Xadd = r.Add + Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr)
-                       //
-                       //      o = r.Xadd
-                       //      if target.IsElf() && target.IsAMD64() {
-                       //              o = 0
-                       //      }
-                       //      break
-                       //}
+                       if target.IsExternal() {
+                               needExtReloc = true
+
+                               // On most platforms, the external linker needs to adjust DWARF references
+                               // as it combines DWARF sections. However, on Darwin, dsymutil does the
+                               // DWARF linking, and it understands how to follow section offsets.
+                               // Leaving in the relocation records confuses it (see
+                               // https://golang.org/issue/22068) so drop them for Darwin.
+                               if target.IsDarwin() {
+                                       needExtReloc = false
+                               }
+
+                               // PE code emits IMAGE_REL_I386_SECREL and IMAGE_REL_AMD64_SECREL
+                               // for R_DWARFSECREF relocations, while R_ADDR is replaced with
+                               // IMAGE_REL_I386_DIR32, IMAGE_REL_AMD64_ADDR64 and IMAGE_REL_AMD64_ADDR32.
+                               // Do not replace R_DWARFSECREF with R_ADDR for windows -
+                               // let PE code emit correct relocations.
+                               if !target.IsWindows() {
+                                       rr.Type = objabi.R_ADDR
+                               }
+
+                               rr.Xsym = loader.Sym(ldr.SymSect(rr.Sym).Sym2)
+                               rr.Xadd = rr.Add + ldr.SymValue(rr.Sym) - int64(ldr.SymSect(rr.Sym).Vaddr)
+
+                               o = rr.Xadd
+                               if target.IsElf() && target.IsAMD64() {
+                                       o = 0
+                               }
+                               break
+                       }
                        o = ldr.SymValue(rs) + r.Add() - int64(ldr.SymSect(rs).Vaddr)
                case objabi.R_WEAKADDROFF, objabi.R_METHODOFF:
                        if !ldr.AttrReachable(rs) {
@@ -415,78 +432,74 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
 
                // r.Sym() can be 0 when CALL $(constant) is transformed from absolute PC to relative PC call.
                case objabi.R_GOTPCREL:
-                       //if target.IsDynlinkingGo() && target.IsDarwin() && r.Sym != nil && r.Sym.Type != sym.SCONST {
-                       //      r.Done = false
-                       //      r.Xadd = r.Add
-                       //      r.Xadd -= int64(r.Siz) // relative to address after the relocated chunk
-                       //      r.Xsym = r.Sym
-                       //
-                       //      o = r.Xadd
-                       //      o += int64(r.Siz)
-                       //      break
-                       //}
+                       if target.IsDynlinkingGo() && target.IsDarwin() && rs != 0 && rst != sym.SCONST {
+                               needExtReloc = true
+                               rr.Xadd = rr.Add
+                               rr.Xadd -= int64(rr.Siz) // relative to address after the relocated chunk
+                               rr.Xsym = rr.Sym
+
+                               o = rr.Xadd
+                               o += int64(rr.Siz)
+                               break
+                       }
                        fallthrough
                case objabi.R_CALL, objabi.R_PCREL:
-                       //if target.IsExternal() && r.Sym != nil && r.Sym.Type == sym.SUNDEFEXT {
-                       //      // pass through to the external linker.
-                       //      r.Done = false
-                       //      r.Xadd = 0
-                       //      if target.IsElf() {
-                       //              r.Xadd -= int64(r.Siz)
-                       //      }
-                       //      r.Xsym = r.Sym
-                       //      o = 0
-                       //      break
-                       //}
-                       //if target.IsExternal() && r.Sym != nil && r.Sym.Type != sym.SCONST && (r.Sym.Sect != s.Sect || r.Type == objabi.R_GOTPCREL) {
-                       //      r.Done = false
-                       //
-                       //      // set up addend for eventual relocation via outer symbol.
-                       //      rs := r.Sym
-                       //
-                       //      r.Xadd = r.Add
-                       //      for rs.Outer != nil {
-                       //              r.Xadd += Symaddr(rs) - Symaddr(rs.Outer)
-                       //              rs = rs.Outer
-                       //      }
-                       //
-                       //      r.Xadd -= int64(r.Siz) // relative to address after the relocated chunk
-                       //      if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
-                       //              Errorf(s, "missing section for relocation target %s", rs.Name)
-                       //      }
-                       //      r.Xsym = rs
-                       //
-                       //      o = r.Xadd
-                       //      if target.IsElf() {
-                       //              if target.IsAMD64() {
-                       //                      o = 0
-                       //              }
-                       //      } else if target.IsDarwin() {
-                       //              if r.Type == objabi.R_CALL {
-                       //                      if target.IsExternal() && rs.Type == sym.SDYNIMPORT {
-                       //                              if target.IsAMD64() {
-                       //                                      // AMD64 dynamic relocations are relative to the end of the relocation.
-                       //                                      o += int64(r.Siz)
-                       //                              }
-                       //                      } else {
-                       //                              if rs.Type != sym.SHOSTOBJ {
-                       //                                      o += int64(uint64(Symaddr(rs)) - rs.Sect.Vaddr)
-                       //                              }
-                       //                              o -= int64(r.Off) // relative to section offset, not symbol
-                       //                      }
-                       //              } else {
-                       //                      o += int64(r.Siz)
-                       //              }
-                       //      } else if target.IsWindows() && target.IsAMD64() { // only amd64 needs PCREL
-                       //              // PE/COFF's PC32 relocation uses the address after the relocated
-                       //              // bytes as the base. Compensate by skewing the addend.
-                       //              o += int64(r.Siz)
-                       //      } else {
-                       //              Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, target.HeadType)
-                       //      }
-                       //
-                       //      break
-                       //}
+                       if target.IsExternal() && rs != 0 && rst == sym.SUNDEFEXT {
+                               // pass through to the external linker.
+                               needExtReloc = true
+                               rr.Xadd = 0
+                               if target.IsElf() {
+                                       rr.Xadd -= int64(rr.Siz)
+                               }
+                               rr.Xsym = rr.Sym
+                               o = 0
+                               break
+                       }
+                       if target.IsExternal() && rs != 0 && rst != sym.SCONST && (ldr.SymSect(rs) != ldr.SymSect(s) || rt == objabi.R_GOTPCREL) {
+                               needExtReloc = true
+
+                               // set up addend for eventual relocation via outer symbol.
+                               rs := rs
+                               rs, off := foldSubSymbolOffset(ldr, rs)
+                               rr.Xadd = rr.Add + off
+                               rr.Xadd -= int64(rr.Siz) // relative to address after the relocated chunk
+                               rst := ldr.SymType(rs)
+                               if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
+                                       err.Errorf(s, "missing section for relocation target %s", ldr.SymName(rs))
+                               }
+                               rr.Xsym = rs
+
+                               o = rr.Xadd
+                               if target.IsElf() {
+                                       if target.IsAMD64() {
+                                               o = 0
+                                       }
+                               } else if target.IsDarwin() {
+                                       if rr.Type == objabi.R_CALL {
+                                               if target.IsExternal() && rst == sym.SDYNIMPORT {
+                                                       if target.IsAMD64() {
+                                                               // AMD64 dynamic relocations are relative to the end of the relocation.
+                                                               o += int64(rr.Siz)
+                                                       }
+                                               } else {
+                                                       if rst != sym.SHOSTOBJ {
+                                                               o += int64(uint64(ldr.SymValue(rs)) - ldr.SymSect(rs).Vaddr)
+                                                       }
+                                                       o -= int64(rr.Off) // relative to section offset, not symbol
+                                               }
+                                       } else {
+                                               o += int64(rr.Siz)
+                                       }
+                               } else if target.IsWindows() && target.IsAMD64() { // only amd64 needs PCREL
+                                       // PE/COFF's PC32 relocation uses the address after the relocated
+                                       // bytes as the base. Compensate by skewing the addend.
+                                       o += int64(rr.Siz)
+                               } else {
+                                       err.Errorf(s, "unhandled pcrel relocation to %s on %v", ldr.SymName(rs), target.HeadType)
+                               }
+
+                               break
+                       }
 
                        o = 0
                        if rs != 0 {
@@ -504,9 +517,9 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
                        if !target.IsExternal() {
                                err.Errorf(s, "find XCOFF R_REF with internal linking")
                        }
-                       //r.Xsym = r.Sym
-                       //r.Xadd = r.Add
-                       //r.Done = false
+                       needExtReloc = true
+                       rr.Xsym = rr.Sym
+                       rr.Xadd = rr.Add
 
                        // This isn't a real relocation so it must not update
                        // its offset value.
@@ -548,6 +561,13 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
                case 8:
                        target.Arch.ByteOrder.PutUint64(P[off:], uint64(o))
                }
+
+               if needExtReloc {
+                       extRelocs = append(extRelocs, rr)
+               }
+       }
+       if len(extRelocs) != 0 {
+               ldr.SetExtRelocs(s, extRelocs)
        }
 }
 
@@ -557,6 +577,9 @@ func (ctxt *Link) reloc() {
        ldr := ctxt.loader
        reporter := &ctxt.ErrorReporter
        syms := &ctxt.ArchSyms
+       if ctxt.IsExternal() {
+               ldr.InitExtRelocs()
+       }
        wg.Add(3)
        go func() {
                if !ctxt.IsWasm() { // On Wasm, text relocations are applied in Asmb2.
index 1484ade313c762e9473ddd7a350aadb48e4e84d2..2cac61c08cc45eeff1891b5ca7fab62620fc43e0 100644 (file)
@@ -326,14 +326,14 @@ func Main(arch *sys.Arch, theArch Arch) {
        ctxt.loader.InitOutData()
        thearch.Asmb(ctxt, ctxt.loader)
 
-       newreloc := ctxt.IsInternal() && (ctxt.IsAMD64() || ctxt.Is386())
+       newreloc := ctxt.IsAMD64() || ctxt.Is386()
        if newreloc {
                bench.Start("reloc")
                ctxt.reloc()
                bench.Start("loadlibfull")
                // We don't need relocations at this point.
-               // An exception is Windows, see pe.go:addPEBaseRelocSym
-               needReloc := ctxt.IsWindows()
+               // An exception is internal linking on Windows, see pe.go:addPEBaseRelocSym
+               needReloc := ctxt.IsWindows() && ctxt.IsInternal()
                ctxt.loadlibfull(symGroupType, needReloc) // XXX do it here for now
        } else {
                bench.Start("loadlibfull")
index 4fcdc1a661feddf8c33cf90b07d2c54181dbb89a..e3dec5feee4c63ecbfa2549d04b453ccc3a88dcb 100644 (file)
@@ -49,6 +49,17 @@ type Reloc struct {
        Sym  Sym              // global index of symbol the reloc addresses
 }
 
+// ExtReloc contains the payload for an external relocation.
+type ExtReloc struct {
+       Off  int32            // offset to rewrite
+       Siz  uint8            // number of bytes to rewrite: 0, 1, 2, or 4
+       Type objabi.RelocType // the relocation type
+       Sym  Sym              // global index of symbol the reloc addresses
+       Add  int64            // addend
+       Xsym Sym
+       Xadd int64
+}
+
 // Reloc2 holds a "handle" to access a relocation record from an
 // object file.
 type Reloc2 struct {
@@ -216,7 +227,8 @@ type Loader struct {
        sects    []*sym.Section // sections
        symSects []uint16       // symbol's section, index to sects array
 
-       outdata [][]byte // symbol's data in the output buffer
+       outdata   [][]byte     // symbol's data in the output buffer
+       extRelocs [][]ExtReloc // symbol's external relocations
 
        itablink map[Sym]struct{} // itablink[j] defined if j is go.itablink.*
 
@@ -1108,6 +1120,16 @@ func (l *Loader) InitOutData() {
        l.outdata = make([][]byte, l.extStart)
 }
 
+// SetExtRelocs sets the section of the i-th symbol. i is global index.
+func (l *Loader) SetExtRelocs(i Sym, relocs []ExtReloc) {
+       l.extRelocs[i] = relocs
+}
+
+// InitExtRelocs initialize the slice used to store external relocations.
+func (l *Loader) InitExtRelocs() {
+       l.extRelocs = make([][]ExtReloc, l.NSym())
+}
+
 // SymAlign returns the alignment for a symbol.
 func (l *Loader) SymAlign(i Sym) int32 {
        // If an alignment has been recorded, return that.
@@ -2072,6 +2094,8 @@ func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols, needReloc bool) {
                        l.convertRelocations(i, &relocs, s, false)
                }
 
+               l.convertExtRelocs(s, i)
+
                // Copy data
                s.P = pp.data
 
@@ -2632,6 +2656,8 @@ func loadObjFull(l *Loader, r *oReader, needReloc bool) {
                        l.convertRelocations(gi, &relocs, s, false)
                }
 
+               l.convertExtRelocs(s, gi)
+
                // Aux symbol info
                auxs := r.Auxs(i)
                for j := range auxs {
@@ -2697,6 +2723,33 @@ func (l *Loader) convertRelocations(symIdx Sym, src *Relocs, dst *sym.Symbol, st
        }
 }
 
+// Convert external relocations to sym.Relocs on symbol dst.
+func (l *Loader) convertExtRelocs(dst *sym.Symbol, src Sym) {
+       if int(src) >= len(l.extRelocs) {
+               return
+       }
+       relocs := l.extRelocs[src]
+       if len(relocs) == 0 {
+               return
+       }
+       if len(dst.R) != 0 {
+               panic("bad")
+       }
+       dst.R = make([]sym.Reloc, len(relocs))
+       for i := range dst.R {
+               sr := &relocs[i]
+               r := &dst.R[i]
+               r.InitExt()
+               r.Off = sr.Off
+               r.Siz = sr.Siz
+               r.Type = sr.Type
+               r.Sym = l.Syms[sr.Sym]
+               r.Add = sr.Add
+               r.Xsym = l.Syms[sr.Xsym]
+               r.Xadd = sr.Xadd
+       }
+}
+
 // relocId is essentially a <S,R> tuple identifying the Rth
 // relocation of symbol S.
 type relocId struct {