if Symaddr(r.Sym) == 0 && (r.Sym.Type != sym.SDYNIMPORT && r.Sym.Type != sym.SUNDEFEXT) {
if r.Sym.File != s.File {
if !isRuntimeDepPkg(s.File) || !isRuntimeDepPkg(r.Sym.File) {
- ctxt.ErrorUnresolved(s, r)
+ ctxt.errorUnresolved(ctxt.Syms.ROLookup, s, r)
}
// runtime and its dependent packages may call to each other.
// they are fine, as they will be laid down together.
continue
}
} else {
- ctxt.ErrorUnresolved(s, r)
+ ctxt.errorUnresolved(ctxt.Syms.ROLookup, s, r)
continue
}
}
// symbol which isn't in .data. However, as .text has the
// same address once loaded, this is possible.
if s.Sect.Seg == &Segdata {
- Xcoffadddynrel(ctxt, s, r)
+ Xcoffadddynrel(target, s, r)
}
}
--- /dev/null
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package ld
+
+import (
+ "cmd/internal/obj"
+ "cmd/link/internal/sym"
+ "sync"
+)
+
+type unresolvedSymKey struct {
+ from *sym.Symbol // Symbol that referenced unresolved "to"
+ to *sym.Symbol // Unresolved symbol referenced by "from"
+}
+
+// ErrorReporter is used to make error reporting thread safe.
+type ErrorReporter struct {
+ unresOnce sync.Once
+ unresSyms map[unresolvedSymKey]bool
+ unresMutex sync.Mutex
+}
+
+type roLookup func(name string, v int) *sym.Symbol
+
+// errorUnresolved prints unresolved symbol error for r.Sym that is referenced from s.
+func (reporter *ErrorReporter) errorUnresolved(lookup roLookup, s *sym.Symbol, r *sym.Reloc) {
+ reporter.unresOnce.Do(func() { reporter.unresSyms = make(map[unresolvedSymKey]bool) })
+
+ k := unresolvedSymKey{from: s, to: r.Sym}
+ reporter.unresMutex.Lock()
+ defer reporter.unresMutex.Unlock()
+ if !reporter.unresSyms[k] {
+ reporter.unresSyms[k] = true
+
+ // Try to find symbol under another ABI.
+ var reqABI, haveABI obj.ABI
+ haveABI = ^obj.ABI(0)
+ reqABI, ok := sym.VersionToABI(int(r.Sym.Version))
+ if ok {
+ for abi := obj.ABI(0); abi < obj.ABICount; abi++ {
+ v := sym.ABIToVersion(abi)
+ if v == -1 {
+ continue
+ }
+ if rs := lookup(r.Sym.Name, v); rs != nil && rs.Type != sym.Sxxx {
+ haveABI = abi
+ }
+ }
+ }
+
+ // Give a special error message for main symbol (see #24809).
+ if r.Sym.Name == "main.main" {
+ Errorf(s, "function main is undeclared in the main package")
+ } else if haveABI != ^obj.ABI(0) {
+ Errorf(s, "relocation target %s not defined for %s (but is defined for %s)", r.Sym.Name, reqABI, haveABI)
+ } else {
+ Errorf(s, "relocation target %s not defined", r.Sym.Name)
+ }
+ }
+}
import (
"bufio"
- "cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loader"
// or for reading that input into the linker.
type Link struct {
Target
+ ErrorReporter
Out *OutBuf
Syms *sym.Symbols
tramps []*sym.Symbol // trampolines
- // unresolvedSymSet is a set of erroneous unresolved references.
- // Used to avoid duplicated error messages.
- unresolvedSymSet map[unresolvedSymKey]bool
-
// Used to implement field tracking.
Reachparent map[*sym.Symbol]*sym.Symbol
directives [][]string
}
-type unresolvedSymKey struct {
- from *sym.Symbol // Symbol that referenced unresolved "to"
- to *sym.Symbol // Unresolved symbol referenced by "from"
-}
-
-// ErrorUnresolved prints unresolved symbol error for r.Sym that is referenced from s.
-func (ctxt *Link) ErrorUnresolved(s *sym.Symbol, r *sym.Reloc) {
- if ctxt.unresolvedSymSet == nil {
- ctxt.unresolvedSymSet = make(map[unresolvedSymKey]bool)
- }
-
- k := unresolvedSymKey{from: s, to: r.Sym}
- if !ctxt.unresolvedSymSet[k] {
- ctxt.unresolvedSymSet[k] = true
-
- // Try to find symbol under another ABI.
- var reqABI, haveABI obj.ABI
- haveABI = ^obj.ABI(0)
- reqABI, ok := sym.VersionToABI(int(r.Sym.Version))
- if ok {
- for abi := obj.ABI(0); abi < obj.ABICount; abi++ {
- v := sym.ABIToVersion(abi)
- if v == -1 {
- continue
- }
- if rs := ctxt.Syms.ROLookup(r.Sym.Name, v); rs != nil && rs.Type != sym.Sxxx {
- haveABI = abi
- }
- }
- }
-
- // Give a special error message for main symbol (see #24809).
- if r.Sym.Name == "main.main" {
- Errorf(s, "function main is undeclared in the main package")
- } else if haveABI != ^obj.ABI(0) {
- Errorf(s, "relocation target %s not defined for %s (but is defined for %s)", r.Sym.Name, reqABI, haveABI)
- } else {
- Errorf(s, "relocation target %s not defined", r.Sym.Name)
- }
- }
-}
-
// The smallest possible offset from the hardware stack pointer to a local
// variable on the stack. Architectures that use a link register save its value
// on the stack in the function prologue and so always have a pointer between
// Xcoffadddynrel adds a dynamic relocation in a XCOFF file.
// This relocation will be made by the loader.
-func Xcoffadddynrel(ctxt *Link, s *sym.Symbol, r *sym.Reloc) bool {
- if ctxt.LinkMode == LinkExternal {
+func Xcoffadddynrel(target *Target, s *sym.Symbol, r *sym.Reloc) bool {
+ if target.IsExternal() {
return true
}
if s.Type <= sym.SPCLNTAB {
if ctxt.IsELF {
return addelfdynrel(ctxt, s, r)
} else if ctxt.HeadType == objabi.Haix {
- return ld.Xcoffadddynrel(ctxt, s, r)
+ return ld.Xcoffadddynrel(&ctxt.Target, s, r)
}
return false
}