]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: convert dwarfcompress to using the loader
authorCherry Zhang <cherryyz@google.com>
Sat, 25 Apr 2020 18:17:10 +0000 (14:17 -0400)
committerCherry Zhang <cherryyz@google.com>
Tue, 28 Apr 2020 18:36:18 +0000 (18:36 +0000)
Change-Id: I34f806b54e8e0985a30ef38ea4324352aabfc845
Reviewed-on: https://go-review.googlesource.com/c/go/+/229995
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/data2.go
src/cmd/link/internal/ld/dwarf2.go
src/cmd/link/internal/ld/errors.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/main.go

index 40d07199fa251faecdb3fa0da4ff01034ea3d92c..1fd048e10dc5c9dfc1014fecc542298cd68de9ca 100644 (file)
@@ -120,139 +120,139 @@ func trampoline(ctxt *Link, s loader.Sym) {
 
 }
 
-// relocsym resolve relocations in "s". The main loop walks through
-// the list of relocations attached to "s" and resolves them where
-// applicable. Relocations are often architecture-specific, requiring
-// calls into the 'archreloc' and/or 'archrelocvariant' functions for
-// the architecture. When external linking is in effect, it may not be
-// possible to completely resolve the address/offset for a symbol, in
-// which case the goal is to lay the groundwork for turning a given
-// relocation into an external reloc (to be applied by the external
-// linker). For more on how relocations work in general, see
+// relocsym resolve relocations in "s", updating the symbol's content
+// in "P".
+// The main loop walks through the list of relocations attached to "s"
+// and resolves them where applicable. Relocations are often
+// architecture-specific, requiring calls into the 'archreloc' and/or
+// 'archrelocvariant' functions for the architecture. When external
+// linking is in effect, it may not be  possible to completely resolve
+// the address/offset for a symbol, in which case the goal is to lay
+// the groundwork for turning a given relocation into an external reloc
+// (to be applied by the external linker). For more on how relocations
+// work in general, see
 //
 //  "Linkers and Loaders", by John R. Levine (Morgan Kaufmann, 1999), ch. 7
 //
 // This is a performance-critical function for the linker; be careful
 // to avoid introducing unnecessary allocations in the main loop.
-// TODO: This function is called in parallel. When the Loader wavefront
-// reaches here, calls into the loader need to be parallel as well.
-func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *ArchSyms, s *sym.Symbol) {
-       if len(s.R) == 0 {
+func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *ArchSyms, s loader.Sym, P []byte) {
+       relocs := ldr.Relocs(s)
+       if relocs.Count() == 0 {
                return
        }
-       if target.IsWasm() && s.Attr.ReadOnly() {
-               // The symbol's content is backed by read-only memory.
-               // Copy it to writable memory to apply relocations.
-               // Only need to do this on Wasm. On other platforms we
-               // apply relocations to the output buffer, which is
-               // always writeable.
-               s.P = append([]byte(nil), s.P...)
-               // No need to unset AttrReadOnly because it will not be used.
-       }
-       for ri := int32(0); ri < int32(len(s.R)); ri++ {
-               r := &s.R[ri]
-               if r.Done {
-                       // Relocation already processed by an earlier phase.
-                       continue
+       for ri := 0; ri < relocs.Count(); ri++ {
+               r := relocs.At2(ri)
+               off := r.Off()
+               siz := int32(r.Siz())
+               rs := r.Sym()
+               if rs != 0 {
+                       rs = ldr.ResolveABIAlias(rs)
                }
-               r.Done = true
-               off := r.Off
-               siz := int32(r.Siz)
-               if off < 0 || off+siz > int32(len(s.P)) {
+               rt := r.Type()
+               if off < 0 || off+siz > int32(len(P)) {
                        rname := ""
-                       if r.Sym != nil {
-                               rname = r.Sym.Name
+                       if rs != 0 {
+                               rname = ldr.SymName(rs)
                        }
-                       Errorf(s, "invalid relocation %s: %d+%d not in [%d,%d)", rname, off, siz, 0, len(s.P))
+                       err.Errorf(s, "invalid relocation %s: %d+%d not in [%d,%d)", rname, off, siz, 0, len(P))
                        continue
                }
 
-               if r.Sym != nil && ((r.Sym.Type == sym.Sxxx && !r.Sym.Attr.VisibilityHidden()) || r.Sym.Type == sym.SXREF) {
+               var rst sym.SymKind
+               if rs != 0 {
+                       rst = ldr.SymType(rs)
+               }
+
+               if rs != 0 && ((rst == sym.Sxxx && !ldr.AttrVisibilityHidden(rs)) || rst == sym.SXREF) {
                        // When putting the runtime but not main into a shared library
                        // these symbols are undefined and that's OK.
                        if target.IsShared() || target.IsPlugin() {
-                               if r.Sym.Name == "main.main" || (!target.IsPlugin() && r.Sym.Name == "main..inittask") {
-                                       r.Sym.Type = sym.SDYNIMPORT
-                               } else if strings.HasPrefix(r.Sym.Name, "go.info.") {
+                               if ldr.SymName(rs) == "main.main" || (!target.IsPlugin() && ldr.SymName(rs) == "main..inittask") {
+                                       sb := ldr.MakeSymbolUpdater(rs)
+                                       sb.SetType(sym.SDYNIMPORT)
+                               } else if strings.HasPrefix(ldr.SymName(rs), "go.info.") {
                                        // Skip go.info symbols. They are only needed to communicate
                                        // DWARF info between the compiler and linker.
                                        continue
                                }
                        } else {
-                               err.errorUnresolved(s, r)
+                               err.errorUnresolved(ldr, s, rs)
                                continue
                        }
                }
 
-               if r.Type >= objabi.ElfRelocOffset {
+               if rt >= objabi.ElfRelocOffset {
                        continue
                }
-               if r.Siz == 0 { // informational relocation - no work to do
+               if siz == 0 { // informational relocation - no work to do
                        continue
                }
 
                // We need to be able to reference dynimport symbols when linking against
                // shared libraries, and Solaris, Darwin and AIX need it always
-               if !target.IsSolaris() && !target.IsDarwin() && !target.IsAIX() && r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT && !target.IsDynlinkingGo() && !r.Sym.Attr.SubSymbol() {
-                       if !(target.IsPPC64() && target.IsExternal() && r.Sym.Name == ".TOC.") {
-                               Errorf(s, "unhandled relocation for %s (type %d (%s) rtype %d (%s))", r.Sym.Name, r.Sym.Type, r.Sym.Type, r.Type, sym.RelocName(target.Arch, r.Type))
+               if !target.IsSolaris() && !target.IsDarwin() && !target.IsAIX() && rs != 0 && rst == sym.SDYNIMPORT && !target.IsDynlinkingGo() && !ldr.AttrSubSymbol(rs) {
+                       if !(target.IsPPC64() && target.IsExternal() && ldr.SymName(rs) == ".TOC.") {
+                               err.Errorf(s, "unhandled relocation for %s (type %d (%s) rtype %d (%s))", ldr.SymName(rs), rst, rst, rt, sym.RelocName(target.Arch, rt))
                        }
                }
-               if r.Sym != nil && r.Sym.Type != sym.STLSBSS && r.Type != objabi.R_WEAKADDROFF && !r.Sym.Attr.Reachable() {
-                       Errorf(s, "unreachable sym in relocation: %s", r.Sym.Name)
+               if rs != 0 && rst != sym.STLSBSS && rt != objabi.R_WEAKADDROFF && rt != objabi.R_METHODOFF && !ldr.AttrReachable(rs) {
+                       err.Errorf(s, "unreachable sym in relocation: %s", ldr.SymName(rs))
                }
 
                if target.IsExternal() {
-                       r.InitExt()
+                       panic("external linking not implemented")
+                       //r.InitExt()
                }
 
                // TODO(mundaym): remove this special case - see issue 14218.
-               if target.IsS390X() {
-                       switch r.Type {
-                       case objabi.R_PCRELDBL:
-                               r.InitExt()
-                               r.Type = objabi.R_PCREL
-                               r.Variant = sym.RV_390_DBL
-                       case objabi.R_CALL:
-                               r.InitExt()
-                               r.Variant = sym.RV_390_DBL
-                       }
-               }
+               //if target.IsS390X() {
+               //      switch r.Type {
+               //      case objabi.R_PCRELDBL:
+               //              r.InitExt()
+               //              r.Type = objabi.R_PCREL
+               //              r.Variant = sym.RV_390_DBL
+               //      case objabi.R_CALL:
+               //              r.InitExt()
+               //              r.Variant = sym.RV_390_DBL
+               //      }
+               //}
 
                var o int64
-               switch r.Type {
+               switch rt {
                default:
-                       switch siz {
-                       default:
-                               Errorf(s, "bad reloc size %#x for %s", uint32(siz), r.Sym.Name)
-                       case 1:
-                               o = int64(s.P[off])
-                       case 2:
-                               o = int64(target.Arch.ByteOrder.Uint16(s.P[off:]))
-                       case 4:
-                               o = int64(target.Arch.ByteOrder.Uint32(s.P[off:]))
-                       case 8:
-                               o = int64(target.Arch.ByteOrder.Uint64(s.P[off:]))
-                       }
-                       if offset, ok := thearch.Archreloc(target, syms, r, s, o); ok {
-                               o = offset
-                       } else {
-                               Errorf(s, "unknown reloc to %v: %d (%s)", r.Sym.Name, r.Type, sym.RelocName(target.Arch, r.Type))
-                       }
+                       panic("not implemented")
+                       //switch siz {
+                       //default:
+                       //      err.Errorf(s, "bad reloc size %#x for %s", uint32(siz), ldr.SymName(rs))
+                       //case 1:
+                       //      o = int64(P[off])
+                       //case 2:
+                       //      o = int64(target.Arch.ByteOrder.Uint16(P[off:]))
+                       //case 4:
+                       //      o = int64(target.Arch.ByteOrder.Uint32(P[off:]))
+                       //case 8:
+                       //      o = int64(target.Arch.ByteOrder.Uint64(P[off:]))
+                       //}
+                       //if out, ok := thearch.Archreloc(ldr, target, syms, &r, s, o); ok {
+                       //      o = out
+                       //} else {
+                       //      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() {
+                       //      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.IsElf() && target.IsARM() {
                                // On ELF ARM, the thread pointer is 8 bytes before
@@ -262,96 +262,94 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
                                // ELF on ARM (or maybe Glibc on ARM); it is not
                                // related to the fact that our own TLS storage happens
                                // to take up 8 bytes.
-                               o = 8 + r.Sym.Value
+                               o = 8 + ldr.SymValue(rs)
                        } else if target.IsElf() || target.IsPlan9() || target.IsDarwin() {
-                               o = int64(syms.Tlsoffset) + r.Add
+                               o = int64(syms.Tlsoffset) + r.Add()
                        } else if target.IsWindows() {
-                               o = r.Add
+                               o = r.Add()
                        } else {
                                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.IsPIE() && target.IsElf() {
-                               // We are linking the final executable, so we
-                               // can optimize any TLS IE relocation to LE.
-                               if thearch.TLSIEtoLE == nil {
-                                       log.Fatalf("internal linking of TLS IE not supported on %v", target.Arch.Family)
-                               }
-                               thearch.TLSIEtoLE(s, int(off), int(r.Siz))
-                               o = int64(syms.Tlsoffset)
-                               // TODO: o += r.Add when !target.IsAmd64()?
-                               // Why do we treat r.Add differently on AMD64?
-                               // Is the external linker using Xadd at all?
-                       } else {
-                               log.Fatalf("cannot handle R_TLS_IE (sym %s) when linking internally", s.Name)
-                       }
+                       panic("not implemented")
+                       //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.IsPIE() && target.IsElf() {
+                       //      // We are linking the final executable, so we
+                       //      // can optimize any TLS IE relocation to LE.
+                       //      if thearch.TLSIEtoLE == nil {
+                       //              log.Fatalf("internal linking of TLS IE not supported on %v", target.Arch.Family)
+                       //      }
+                       //      thearch.TLSIEtoLE(ldr, s, int(off), int(siz))
+                       //      o = int64(syms.Tlsoffset)
+                       //} else {
+                       //      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() && 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
+                       //}
 
                        // On AIX, a second relocation must be done by the loader,
                        // as section addresses can change once loaded.
                        // The "default" symbol address is still needed by the loader so
                        // the current relocation can't be skipped.
-                       if target.IsAIX() && r.Sym.Type != sym.SDYNIMPORT {
+                       if target.IsAIX() && rst != sym.SDYNIMPORT {
                                // It's not possible to make a loader relocation in a
                                // symbol which is not inside .data section.
                                // FIXME: It should be forbidden to have R_ADDR from a
                                // symbol which isn't in .data. However, as .text has the
                                // same address once loaded, this is possible.
-                               if s.Sect.Seg == &Segdata {
-                                       Xcoffadddynrel(target, ldr, s, r)
+                               if ldr.SymSect(s).Seg == &Segdata {
+                                       //Xcoffadddynrel(target, ldr, err, s, &r) // XXX
                                }
                        }
 
-                       o = Symaddr(r.Sym) + r.Add
+                       o = ldr.SymValue(rs) + r.Add()
 
                        // On amd64, 4-byte offsets will be sign-extended, so it is impossible to
                        // access more than 2GB of static data; fail at link time is better than
@@ -359,217 +357,198 @@ func relocsym(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *Arch
                        // Instead of special casing only amd64, we treat this as an error on all
                        // 64-bit architectures so as to be future-proof.
                        if int32(o) < 0 && target.Arch.PtrSize > 4 && siz == 4 {
-                               Errorf(s, "non-pc-relative relocation address for %s is too big: %#x (%#x + %#x)", r.Sym.Name, uint64(o), Symaddr(r.Sym), r.Add)
+                               err.Errorf(s, "non-pc-relative relocation address for %s is too big: %#x (%#x + %#x)", ldr.SymName(rs), uint64(o), ldr.SymValue(rs), r.Add())
                                errorexit()
                        }
                case objabi.R_DWARFSECREF:
-                       if r.Sym.Sect == nil {
-                               Errorf(s, "missing DWARF section for relocation target %s", r.Sym.Name)
-                       }
-
-                       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
-                       }
-                       o = Symaddr(r.Sym) + r.Add - int64(r.Sym.Sect.Vaddr)
-               case objabi.R_WEAKADDROFF:
-                       if !r.Sym.Attr.Reachable() {
+                       if ldr.SymSect(rs) == nil {
+                               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
+                       //}
+                       o = ldr.SymValue(rs) + r.Add() - int64(ldr.SymSect(rs).Vaddr)
+               case objabi.R_WEAKADDROFF, objabi.R_METHODOFF:
+                       if !ldr.AttrReachable(rs) {
                                continue
                        }
                        fallthrough
                case objabi.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.
-                       if r.Sym.Sect.Name == ".text" {
-                               o = Symaddr(r.Sym) - int64(Segtext.Sections[0].Vaddr) + r.Add
+                       if ldr.SymSect(rs).Name == ".text" {
+                               o = ldr.SymValue(rs) - int64(Segtext.Sections[0].Vaddr) + r.Add()
                        } else {
-                               o = Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr) + r.Add
+                               o = ldr.SymValue(rs) - int64(ldr.SymSect(rs).Vaddr) + r.Add()
                        }
 
                case objabi.R_ADDRCUOFF:
                        // debug_range and debug_loc elements use this relocation type to get an
                        // offset from the start of the compile unit.
-                       o = Symaddr(r.Sym) + r.Add - Symaddr(ldr.Syms[r.Sym.Unit.Textp2[0]])
+                       o = ldr.SymValue(rs) + r.Add() - ldr.SymValue(loader.Sym(ldr.SymUnit(rs).Textp2[0]))
 
-                       // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
+               // 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() && 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
+                       //}
                        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() && 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
+                       //}
 
                        o = 0
-                       if r.Sym != nil {
-                               o += Symaddr(r.Sym)
+                       if rs != 0 {
+                               o = ldr.SymValue(rs)
                        }
 
-                       o += r.Add - (s.Value + int64(r.Off) + int64(r.Siz))
+                       o += r.Add() - (ldr.SymValue(s) + int64(off) + int64(siz))
                case objabi.R_SIZE:
-                       o = r.Sym.Size + r.Add
+                       o = ldr.SymSize(rs) + r.Add()
 
                case objabi.R_XCOFFREF:
                        if !target.IsAIX() {
-                               Errorf(s, "find XCOFF R_REF on non-XCOFF files")
+                               err.Errorf(s, "find XCOFF R_REF on non-XCOFF files")
                        }
                        if !target.IsExternal() {
-                               Errorf(s, "find XCOFF R_REF with internal linking")
+                               err.Errorf(s, "find XCOFF R_REF with internal linking")
                        }
-                       r.Xsym = r.Sym
-                       r.Xadd = r.Add
-                       r.Done = false
+                       //r.Xsym = r.Sym
+                       //r.Xadd = r.Add
+                       //r.Done = false
 
                        // This isn't a real relocation so it must not update
                        // its offset value.
                        continue
 
                case objabi.R_DWARFFILEREF:
-                       // The final file index is saved in r.Add in dwarf.go:writelines.
-                       o = r.Add
+                       // We don't renumber files in dwarf.go:writelines anymore.
+                       continue
                }
 
-               if target.IsPPC64() || target.IsS390X() {
-                       r.InitExt()
-                       if r.Variant != sym.RV_NONE {
-                               o = thearch.Archrelocvariant(target, syms, r, s, o)
-                       }
-               }
+               //if target.IsPPC64() || target.IsS390X() {
+               //      r.InitExt()
+               //      if r.Variant != sym.RV_NONE {
+               //              o = thearch.Archrelocvariant(ldr, target, syms, &r, s, o)
+               //      }
+               //}
 
-               if false {
-                       nam := "<nil>"
-                       var addr int64
-                       if r.Sym != nil {
-                               nam = r.Sym.Name
-                               addr = Symaddr(r.Sym)
-                       }
-                       xnam := "<nil>"
-                       if r.Xsym != nil {
-                               xnam = r.Xsym.Name
-                       }
-                       fmt.Printf("relocate %s %#x (%#x+%#x, size %d) => %s %#x +%#x (xsym: %s +%#x) [type %d (%s)/%d, %x]\n", s.Name, s.Value+int64(off), s.Value, r.Off, r.Siz, nam, addr, r.Add, xnam, r.Xadd, r.Type, sym.RelocName(target.Arch, r.Type), r.Variant, o)
-               }
                switch siz {
                default:
-                       Errorf(s, "bad reloc size %#x for %s", uint32(siz), r.Sym.Name)
-                       fallthrough
-
-                       // TODO(rsc): Remove.
+                       err.Errorf(s, "bad reloc size %#x for %s", uint32(siz), ldr.SymName(rs))
                case 1:
-                       s.P[off] = byte(int8(o))
+                       P[off] = byte(int8(o))
                case 2:
                        if o != int64(int16(o)) {
-                               Errorf(s, "relocation address for %s is too big: %#x", r.Sym.Name, o)
+                               err.Errorf(s, "relocation address for %s is too big: %#x", ldr.SymName(rs), o)
                        }
-                       i16 := int16(o)
-                       target.Arch.ByteOrder.PutUint16(s.P[off:], uint16(i16))
+                       target.Arch.ByteOrder.PutUint16(P[off:], uint16(o))
                case 4:
-                       if r.Type == objabi.R_PCREL || r.Type == objabi.R_CALL {
+                       if rt == objabi.R_PCREL || rt == objabi.R_CALL {
                                if o != int64(int32(o)) {
-                                       Errorf(s, "pc-relative relocation address for %s is too big: %#x", r.Sym.Name, o)
+                                       err.Errorf(s, "pc-relative relocation address for %s is too big: %#x", ldr.SymName(rs), o)
                                }
                        } else {
                                if o != int64(int32(o)) && o != int64(uint32(o)) {
-                                       Errorf(s, "non-pc-relative relocation address for %s is too big: %#x", r.Sym.Name, uint64(o))
+                                       err.Errorf(s, "non-pc-relative relocation address for %s is too big: %#x", ldr.SymName(rs), uint64(o))
                                }
                        }
-
-                       fl := int32(o)
-                       target.Arch.ByteOrder.PutUint32(s.P[off:], uint32(fl))
+                       target.Arch.ByteOrder.PutUint32(P[off:], uint32(o))
                case 8:
-                       target.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o))
+                       target.Arch.ByteOrder.PutUint64(P[off:], uint64(o))
                }
        }
 }
@@ -584,21 +563,21 @@ func (ctxt *Link) reloc() {
        go func() {
                if !ctxt.IsWasm() { // On Wasm, text relocations are applied in Asmb2.
                        for _, s := range ctxt.Textp {
-                               relocsym(target, ldr, reporter, syms, s)
+                               relocsym2(target, ldr, reporter, syms, s)
                        }
                }
                wg.Done()
        }()
        go func() {
                for _, s := range ctxt.datap {
-                       relocsym(target, ldr, reporter, syms, s)
+                       relocsym2(target, ldr, reporter, syms, s)
                }
                wg.Done()
        }()
        go func() {
                for _, si := range dwarfp {
                        for _, s := range si.syms {
-                               relocsym(target, ldr, reporter, syms, s)
+                               relocsym2(target, ldr, reporter, syms, s)
                        }
                }
                wg.Done()
@@ -2478,10 +2457,11 @@ func (ctxt *Link) AddTramp(s *loader.SymbolBuilder) {
 
 // compressSyms compresses syms and returns the contents of the
 // compressed section. If the section would get larger, it returns nil.
-func compressSyms(ctxt *Link, syms []*sym.Symbol) []byte {
+func compressSyms(ctxt *Link, syms []loader.Sym) []byte {
+       ldr := ctxt.loader
        var total int64
        for _, sym := range syms {
-               total += sym.Size
+               total += ldr.SymSize(sym)
        }
 
        var buf bytes.Buffer
@@ -2501,23 +2481,22 @@ func compressSyms(ctxt *Link, syms []*sym.Symbol) []byte {
                log.Fatalf("NewWriterLevel failed: %s", err)
        }
        target := &ctxt.Target
-       ldr := ctxt.loader
        reporter := &ctxt.ErrorReporter
        archSyms := &ctxt.ArchSyms
        for _, s := range syms {
-               // s.P may be read-only. Apply relocations in a
+               // Symbol data may be read-only. Apply relocations in a
                // temporary buffer, and immediately write it out.
-               oldP := s.P
-               wasReadOnly := s.Attr.ReadOnly()
-               if len(s.R) != 0 && wasReadOnly {
-                       relocbuf = append(relocbuf[:0], s.P...)
-                       s.P = relocbuf
-               }
-               relocsym(target, ldr, reporter, archSyms, s)
-               if _, err := z.Write(s.P); err != nil {
+               P := ldr.Data(s)
+               relocs := ldr.Relocs(s)
+               if relocs.Count() != 0 {
+                       relocbuf = append(relocbuf[:0], P...)
+                       P = relocbuf
+               }
+               relocsym(target, ldr, reporter, archSyms, s, P)
+               if _, err := z.Write(P); err != nil {
                        log.Fatalf("compression failed: %s", err)
                }
-               for i := s.Size - int64(len(s.P)); i > 0; {
+               for i := ldr.SymSize(s) - int64(len(P)); i > 0; {
                        b := zeros[:]
                        if i < int64(len(b)) {
                                b = b[:i]
@@ -2528,15 +2507,6 @@ func compressSyms(ctxt *Link, syms []*sym.Symbol) []byte {
                        }
                        i -= int64(n)
                }
-               // Restore s.P if a temporary buffer was used. If compression
-               // is not beneficial, we'll go back to use the uncompressed
-               // contents, in which case we still need s.P.
-               if len(s.R) != 0 && wasReadOnly {
-                       s.P = oldP
-                       for i := range s.R {
-                               s.R[i].Done = false
-                       }
-               }
        }
        if err := z.Close(); err != nil {
                log.Fatalf("compression failed: %s", err)
index 033fe75068e96442b1e75a3a7ef4d7b408c210ed..79badd5fdd19aa4d11e2ff0e43cece24d2000a01 100644 (file)
@@ -5,7 +5,11 @@
 package ld
 
 import (
+       "cmd/internal/objabi"
+       "cmd/link/internal/loader"
        "cmd/link/internal/sym"
+       "fmt"
+       "log"
        "strings"
 )
 
@@ -49,3 +53,442 @@ func symalign(s *sym.Symbol) int32 {
        s.Align = align
        return align
 }
+
+func relocsym2(target *Target, ldr *loader.Loader, err *ErrorReporter, syms *ArchSyms, s *sym.Symbol) {
+       if len(s.R) == 0 {
+               return
+       }
+       if target.IsWasm() && s.Attr.ReadOnly() {
+               // The symbol's content is backed by read-only memory.
+               // Copy it to writable memory to apply relocations.
+               // Only need to do this on Wasm. On other platforms we
+               // apply relocations to the output buffer, which is
+               // always writeable.
+               s.P = append([]byte(nil), s.P...)
+               // No need to unset AttrReadOnly because it will not be used.
+       }
+       for ri := int32(0); ri < int32(len(s.R)); ri++ {
+               r := &s.R[ri]
+               if r.Done {
+                       // Relocation already processed by an earlier phase.
+                       continue
+               }
+               r.Done = true
+               off := r.Off
+               siz := int32(r.Siz)
+               if off < 0 || off+siz > int32(len(s.P)) {
+                       rname := ""
+                       if r.Sym != nil {
+                               rname = r.Sym.Name
+                       }
+                       Errorf(s, "invalid relocation %s: %d+%d not in [%d,%d)", rname, off, siz, 0, len(s.P))
+                       continue
+               }
+
+               if r.Sym != nil && ((r.Sym.Type == sym.Sxxx && !r.Sym.Attr.VisibilityHidden()) || r.Sym.Type == sym.SXREF) {
+                       // When putting the runtime but not main into a shared library
+                       // these symbols are undefined and that's OK.
+                       if target.IsShared() || target.IsPlugin() {
+                               if r.Sym.Name == "main.main" || (!target.IsPlugin() && r.Sym.Name == "main..inittask") {
+                                       r.Sym.Type = sym.SDYNIMPORT
+                               } else if strings.HasPrefix(r.Sym.Name, "go.info.") {
+                                       // Skip go.info symbols. They are only needed to communicate
+                                       // DWARF info between the compiler and linker.
+                                       continue
+                               }
+                       } else {
+                               err.errorUnresolved2(s, r)
+                               continue
+                       }
+               }
+
+               if r.Type >= objabi.ElfRelocOffset {
+                       continue
+               }
+               if r.Siz == 0 { // informational relocation - no work to do
+                       continue
+               }
+
+               // We need to be able to reference dynimport symbols when linking against
+               // shared libraries, and Solaris, Darwin and AIX need it always
+               if !target.IsSolaris() && !target.IsDarwin() && !target.IsAIX() && r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT && !target.IsDynlinkingGo() && !r.Sym.Attr.SubSymbol() {
+                       if !(target.IsPPC64() && target.IsExternal() && r.Sym.Name == ".TOC.") {
+                               Errorf(s, "unhandled relocation for %s (type %d (%s) rtype %d (%s))", r.Sym.Name, r.Sym.Type, r.Sym.Type, r.Type, sym.RelocName(target.Arch, r.Type))
+                       }
+               }
+               if r.Sym != nil && r.Sym.Type != sym.STLSBSS && r.Type != objabi.R_WEAKADDROFF && !r.Sym.Attr.Reachable() {
+                       Errorf(s, "unreachable sym in relocation: %s", r.Sym.Name)
+               }
+
+               if target.IsExternal() {
+                       r.InitExt()
+               }
+
+               // TODO(mundaym): remove this special case - see issue 14218.
+               if target.IsS390X() {
+                       switch r.Type {
+                       case objabi.R_PCRELDBL:
+                               r.InitExt()
+                               r.Type = objabi.R_PCREL
+                               r.Variant = sym.RV_390_DBL
+                       case objabi.R_CALL:
+                               r.InitExt()
+                               r.Variant = sym.RV_390_DBL
+                       }
+               }
+
+               var o int64
+               switch r.Type {
+               default:
+                       switch siz {
+                       default:
+                               Errorf(s, "bad reloc size %#x for %s", uint32(siz), r.Sym.Name)
+                       case 1:
+                               o = int64(s.P[off])
+                       case 2:
+                               o = int64(target.Arch.ByteOrder.Uint16(s.P[off:]))
+                       case 4:
+                               o = int64(target.Arch.ByteOrder.Uint32(s.P[off:]))
+                       case 8:
+                               o = int64(target.Arch.ByteOrder.Uint64(s.P[off:]))
+                       }
+                       if offset, ok := thearch.Archreloc(target, syms, r, s, o); ok {
+                               o = offset
+                       } else {
+                               Errorf(s, "unknown reloc to %v: %d (%s)", r.Sym.Name, r.Type, sym.RelocName(target.Arch, r.Type))
+                       }
+               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.IsElf() && target.IsARM() {
+                               // On ELF ARM, the thread pointer is 8 bytes before
+                               // the start of the thread-local data block, so add 8
+                               // to the actual TLS offset (r->sym->value).
+                               // This 8 seems to be a fundamental constant of
+                               // ELF on ARM (or maybe Glibc on ARM); it is not
+                               // related to the fact that our own TLS storage happens
+                               // to take up 8 bytes.
+                               o = 8 + r.Sym.Value
+                       } else if target.IsElf() || target.IsPlan9() || target.IsDarwin() {
+                               o = int64(syms.Tlsoffset) + r.Add
+                       } else if target.IsWindows() {
+                               o = r.Add
+                       } else {
+                               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.IsPIE() && target.IsElf() {
+                               // We are linking the final executable, so we
+                               // can optimize any TLS IE relocation to LE.
+                               if thearch.TLSIEtoLE == nil {
+                                       log.Fatalf("internal linking of TLS IE not supported on %v", target.Arch.Family)
+                               }
+                               thearch.TLSIEtoLE(s, int(off), int(r.Siz))
+                               o = int64(syms.Tlsoffset)
+                               // TODO: o += r.Add when !target.IsAmd64()?
+                               // Why do we treat r.Add differently on AMD64?
+                               // Is the external linker using Xadd at all?
+                       } else {
+                               log.Fatalf("cannot handle R_TLS_IE (sym %s) when linking internally", s.Name)
+                       }
+               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
+                       }
+
+                       // On AIX, a second relocation must be done by the loader,
+                       // as section addresses can change once loaded.
+                       // The "default" symbol address is still needed by the loader so
+                       // the current relocation can't be skipped.
+                       if target.IsAIX() && r.Sym.Type != sym.SDYNIMPORT {
+                               // It's not possible to make a loader relocation in a
+                               // symbol which is not inside .data section.
+                               // FIXME: It should be forbidden to have R_ADDR from a
+                               // symbol which isn't in .data. However, as .text has the
+                               // same address once loaded, this is possible.
+                               if s.Sect.Seg == &Segdata {
+                                       Xcoffadddynrel(target, ldr, s, r)
+                               }
+                       }
+
+                       o = Symaddr(r.Sym) + r.Add
+
+                       // On amd64, 4-byte offsets will be sign-extended, so it is impossible to
+                       // access more than 2GB of static data; fail at link time is better than
+                       // fail at runtime. See https://golang.org/issue/7980.
+                       // Instead of special casing only amd64, we treat this as an error on all
+                       // 64-bit architectures so as to be future-proof.
+                       if int32(o) < 0 && target.Arch.PtrSize > 4 && siz == 4 {
+                               Errorf(s, "non-pc-relative relocation address for %s is too big: %#x (%#x + %#x)", r.Sym.Name, uint64(o), Symaddr(r.Sym), r.Add)
+                               errorexit()
+                       }
+               case objabi.R_DWARFSECREF:
+                       if r.Sym.Sect == nil {
+                               Errorf(s, "missing DWARF section for relocation target %s", r.Sym.Name)
+                       }
+
+                       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
+                       }
+                       o = Symaddr(r.Sym) + r.Add - int64(r.Sym.Sect.Vaddr)
+               case objabi.R_WEAKADDROFF:
+                       if !r.Sym.Attr.Reachable() {
+                               continue
+                       }
+                       fallthrough
+               case objabi.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.
+                       if r.Sym.Sect.Name == ".text" {
+                               o = Symaddr(r.Sym) - int64(Segtext.Sections[0].Vaddr) + r.Add
+                       } else {
+                               o = Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr) + r.Add
+                       }
+
+               case objabi.R_ADDRCUOFF:
+                       // debug_range and debug_loc elements use this relocation type to get an
+                       // offset from the start of the compile unit.
+                       o = Symaddr(r.Sym) + r.Add - Symaddr(ldr.Syms[r.Sym.Unit.Textp2[0]])
+
+                       // r->sym can be null 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
+                       }
+                       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
+                       }
+
+                       o = 0
+                       if r.Sym != nil {
+                               o += Symaddr(r.Sym)
+                       }
+
+                       o += r.Add - (s.Value + int64(r.Off) + int64(r.Siz))
+               case objabi.R_SIZE:
+                       o = r.Sym.Size + r.Add
+
+               case objabi.R_XCOFFREF:
+                       if !target.IsAIX() {
+                               Errorf(s, "find XCOFF R_REF on non-XCOFF files")
+                       }
+                       if !target.IsExternal() {
+                               Errorf(s, "find XCOFF R_REF with internal linking")
+                       }
+                       r.Xsym = r.Sym
+                       r.Xadd = r.Add
+                       r.Done = false
+
+                       // This isn't a real relocation so it must not update
+                       // its offset value.
+                       continue
+
+               case objabi.R_DWARFFILEREF:
+                       // The final file index is saved in r.Add in dwarf.go:writelines.
+                       o = r.Add
+               }
+
+               if target.IsPPC64() || target.IsS390X() {
+                       r.InitExt()
+                       if r.Variant != sym.RV_NONE {
+                               o = thearch.Archrelocvariant(target, syms, r, s, o)
+                       }
+               }
+
+               if false {
+                       nam := "<nil>"
+                       var addr int64
+                       if r.Sym != nil {
+                               nam = r.Sym.Name
+                               addr = Symaddr(r.Sym)
+                       }
+                       xnam := "<nil>"
+                       if r.Xsym != nil {
+                               xnam = r.Xsym.Name
+                       }
+                       fmt.Printf("relocate %s %#x (%#x+%#x, size %d) => %s %#x +%#x (xsym: %s +%#x) [type %d (%s)/%d, %x]\n", s.Name, s.Value+int64(off), s.Value, r.Off, r.Siz, nam, addr, r.Add, xnam, r.Xadd, r.Type, sym.RelocName(target.Arch, r.Type), r.Variant, o)
+               }
+               switch siz {
+               default:
+                       Errorf(s, "bad reloc size %#x for %s", uint32(siz), r.Sym.Name)
+                       fallthrough
+
+                       // TODO(rsc): Remove.
+               case 1:
+                       s.P[off] = byte(int8(o))
+               case 2:
+                       if o != int64(int16(o)) {
+                               Errorf(s, "relocation address for %s is too big: %#x", r.Sym.Name, o)
+                       }
+                       i16 := int16(o)
+                       target.Arch.ByteOrder.PutUint16(s.P[off:], uint16(i16))
+               case 4:
+                       if r.Type == objabi.R_PCREL || r.Type == objabi.R_CALL {
+                               if o != int64(int32(o)) {
+                                       Errorf(s, "pc-relative relocation address for %s is too big: %#x", r.Sym.Name, o)
+                               }
+                       } else {
+                               if o != int64(int32(o)) && o != int64(uint32(o)) {
+                                       Errorf(s, "non-pc-relative relocation address for %s is too big: %#x", r.Sym.Name, uint64(o))
+                               }
+                       }
+
+                       fl := int32(o)
+                       target.Arch.ByteOrder.PutUint32(s.P[off:], uint32(fl))
+               case 8:
+                       target.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o))
+               }
+       }
+}
+
index 4bd52f5105d327a0b907325c4ebee0423006c5fc..336122800b374d48899921ba5e00f78b3990a21b 100644 (file)
@@ -101,20 +101,20 @@ func dwarfcompress(ctxt *Link) {
        type compressedSect struct {
                index      int
                compressed []byte
-               syms       []*sym.Symbol
+               syms       []loader.Sym
        }
 
-       supported := ctxt.IsELF || ctxt.HeadType == objabi.Hwindows || ctxt.HeadType == objabi.Hdarwin
-       if !ctxt.compressDWARF || !supported || ctxt.LinkMode != LinkInternal {
+       supported := ctxt.IsELF || ctxt.IsWindows() || ctxt.IsDarwin()
+       if !ctxt.compressDWARF || !supported || ctxt.IsExternal() {
                return
        }
 
        var compressedCount int
        resChannel := make(chan compressedSect)
-       for i := range dwarfp {
-               go func(resIndex int, syms []*sym.Symbol) {
+       for i := range dwarfp2 {
+               go func(resIndex int, syms []loader.Sym) {
                        resChannel <- compressedSect{resIndex, compressSyms(ctxt, syms), syms}
-               }(compressedCount, dwarfp[i].syms)
+               }(compressedCount, dwarfp2[i].syms)
                compressedCount++
        }
        res := make([]compressedSect, compressedCount)
@@ -123,46 +123,55 @@ func dwarfcompress(ctxt *Link) {
                res[r.index] = r
        }
 
-       var newDwarfp []dwarfSecInfo2
+       ldr := ctxt.loader
+       var newDwarfp []dwarfSecInfo
        Segdwarf.Sections = Segdwarf.Sections[:0]
        for _, z := range res {
                s := z.syms[0]
                if z.compressed == nil {
                        // Compression didn't help.
-                       ds := dwarfSecInfo2{syms: z.syms}
+                       ds := dwarfSecInfo{syms: z.syms}
                        newDwarfp = append(newDwarfp, ds)
-                       Segdwarf.Sections = append(Segdwarf.Sections, s.Sect)
+                       Segdwarf.Sections = append(Segdwarf.Sections, ldr.SymSect(s))
                } else {
-                       compressedSegName := ".zdebug_" + s.Sect.Name[len(".debug_"):]
+                       compressedSegName := ".zdebug_" + ldr.SymSect(s).Name[len(".debug_"):]
                        sect := addsection(ctxt.loader, ctxt.Arch, &Segdwarf, compressedSegName, 04)
+                       sect.Align = 1
                        sect.Length = uint64(len(z.compressed))
-                       newSym := ctxt.Syms.Lookup(compressedSegName, 0)
-                       newSym.P = z.compressed
-                       newSym.Size = int64(len(z.compressed))
-                       newSym.Sect = sect
-                       ds := dwarfSecInfo2{syms: []*sym.Symbol{newSym}}
+                       newSym := ldr.CreateSymForUpdate(compressedSegName, 0)
+                       newSym.SetReachable(true)
+                       newSym.SetData(z.compressed)
+                       newSym.SetSize(int64(len(z.compressed)))
+                       ldr.SetSymSect(newSym.Sym(), sect)
+                       ds := dwarfSecInfo{syms: []loader.Sym{newSym.Sym()}}
                        newDwarfp = append(newDwarfp, ds)
+
+                       // compressed symbols are no longer needed.
+                       for _, s := range z.syms {
+                               ldr.SetAttrReachable(s, false)
+                       }
                }
        }
-       dwarfp = newDwarfp
+       dwarfp2 = newDwarfp
 
        // Re-compute the locations of the compressed DWARF symbols
        // and sections, since the layout of these within the file is
        // based on Section.Vaddr and Symbol.Value.
        pos := Segdwarf.Vaddr
        var prevSect *sym.Section
-       for _, si := range dwarfp {
+       for _, si := range dwarfp2 {
                for _, s := range si.syms {
-                       s.Value = int64(pos)
-                       if s.Sect != prevSect {
-                               s.Sect.Vaddr = uint64(s.Value)
-                               prevSect = s.Sect
+                       ldr.SetSymValue(s, int64(pos))
+                       sect := ldr.SymSect(s)
+                       if sect != prevSect {
+                               sect.Vaddr = uint64(pos)
+                               prevSect = sect
                        }
-                       if s.Sub != nil {
-                               log.Fatalf("%s: unexpected sub-symbols", s)
+                       if ldr.SubSym(s) != 0 {
+                               log.Fatalf("%s: unexpected sub-symbols", ldr.SymName(s))
                        }
-                       pos += uint64(s.Size)
-                       if ctxt.HeadType == objabi.Hwindows {
+                       pos += uint64(ldr.SymSize(s))
+                       if ctxt.IsWindows() {
                                pos = uint64(Rnd(int64(pos), PEFILEALIGN))
                        }
                }
index 61289b4798a1027cde011368035b8a9376bd06e7..c2c191d05845eb3dc41e112543ce5110893c13dc 100644 (file)
@@ -11,6 +11,11 @@ import (
 )
 
 type unresolvedSymKey struct {
+       from loader.Sym // Symbol that referenced unresolved "to"
+       to   loader.Sym // Unresolved symbol referenced by "from"
+}
+
+type unresolvedSymKey2 struct {
        from *sym.Symbol // Symbol that referenced unresolved "to"
        to   *sym.Symbol // Unresolved symbol referenced by "from"
 }
@@ -23,20 +28,59 @@ type ErrorReporter struct {
        loader.ErrorReporter
        unresOnce  sync.Once
        unresSyms  map[unresolvedSymKey]bool
+       unresSyms2 map[unresolvedSymKey2]bool
        unresMutex sync.Mutex
        lookup     lookupFn
        SymName    symNameFn
 }
 
-// errorUnresolved prints unresolved symbol error for r.Sym that is referenced from s.
-func (reporter *ErrorReporter) errorUnresolved(s *sym.Symbol, r *sym.Reloc) {
+// errorUnresolved prints unresolved symbol error for rs that is referenced from s.
+func (reporter *ErrorReporter) errorUnresolved(ldr *loader.Loader, s, rs loader.Sym) {
        reporter.unresOnce.Do(func() { reporter.unresSyms = make(map[unresolvedSymKey]bool) })
 
-       k := unresolvedSymKey{from: s, to: r.Sym}
+       k := unresolvedSymKey{from: s, to: rs}
        reporter.unresMutex.Lock()
        defer reporter.unresMutex.Unlock()
        if !reporter.unresSyms[k] {
                reporter.unresSyms[k] = true
+               name := ldr.SymName(rs)
+
+               // Try to find symbol under another ABI.
+               var reqABI, haveABI obj.ABI
+               haveABI = ^obj.ABI(0)
+               reqABI, ok := sym.VersionToABI(ldr.SymVersion(rs))
+               if ok {
+                       for abi := obj.ABI(0); abi < obj.ABICount; abi++ {
+                               v := sym.ABIToVersion(abi)
+                               if v == -1 {
+                                       continue
+                               }
+                               if rs1 := ldr.Lookup(name, v); rs1 != 0 && ldr.SymType(rs1) != sym.Sxxx && ldr.SymType(rs1) != sym.SXREF {
+                                       haveABI = abi
+                               }
+                       }
+               }
+
+               // Give a special error message for main symbol (see #24809).
+               if name == "main.main" {
+                       reporter.Errorf(s, "function main is undeclared in the main package")
+               } else if haveABI != ^obj.ABI(0) {
+                       reporter.Errorf(s, "relocation target %s not defined for %s (but is defined for %s)", name, reqABI, haveABI)
+               } else {
+                       reporter.Errorf(s, "relocation target %s not defined", name)
+               }
+       }
+}
+
+// errorUnresolved2 prints unresolved symbol error for r.Sym that is referenced from s.
+func (reporter *ErrorReporter) errorUnresolved2(s *sym.Symbol, r *sym.Reloc) {
+       reporter.unresOnce.Do(func() { reporter.unresSyms2 = make(map[unresolvedSymKey2]bool) })
+
+       k := unresolvedSymKey2{from: s, to: r.Sym}
+       reporter.unresMutex.Lock()
+       defer reporter.unresMutex.Unlock()
+       if !reporter.unresSyms2[k] {
+               reporter.unresSyms2[k] = true
 
                // Try to find symbol under another ABI.
                var reqABI, haveABI obj.ABI
index a43aff22ee8c36c5475a72679347b4cb8d759b98..7264f9383e89cc2575e695366b310391ee5a2a4b 100644 (file)
@@ -2897,7 +2897,7 @@ func (ctxt *Link) loadlibfull(symGroupType []sym.SymKind) {
                if t != sym.Sxxx {
                        s := ctxt.loader.Syms[i]
                        if s == nil {
-                               panic(fmt.Sprintf("nil sym for symGroupType t=%s entry %d", t.String(), i))
+                               continue // in dwarfcompress we drop compressed DWARF symbols
                        }
                        s.Type = t
                }
index 14856c160f7537607320616370e4f422b918c79b..6c5a18c3595676032e10791c268e271256a49c05 100644 (file)
@@ -302,12 +302,12 @@ func Main(arch *sys.Arch, theArch Arch) {
        ctxt.dodata2(symGroupType)
        bench.Start("address")
        order := ctxt.address()
-       bench.Start("loadlibfull")
-       ctxt.loadlibfull(symGroupType) // XXX do it here for now
        bench.Start("dwarfcompress")
        dwarfcompress(ctxt)
        bench.Start("layout")
        filesize := ctxt.layout(order)
+       bench.Start("loadlibfull")
+       ctxt.loadlibfull(symGroupType) // XXX do it here for now
 
        // Write out the output file.
        // It is split into two parts (Asmb and Asmb2). The first