"cmd/internal/obj"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
- "fmt"
- "os"
"sync"
)
// ErrorReporter is used to make error reporting thread safe.
type ErrorReporter struct {
+ loader.ErrorReporter
unresOnce sync.Once
unresSyms map[unresolvedSymKey]bool
unresMutex sync.Mutex
}
}
}
-
-// Errorf method logs an error message.
-//
-// If more than 20 errors have been printed, exit with an error.
-//
-// Logging an error means that on exit cmd/link will delete any
-// output file and return a non-zero error code.
-// TODO: consolidate the various different versions of Errorf (
-// function, Link method, and ErrorReporter method).
-func (reporter *ErrorReporter) Errorf(s loader.Sym, format string, args ...interface{}) {
- if s != 0 && reporter.SymName != nil {
- sn := reporter.SymName(s)
- format = sn + ": " + format
- } else {
- format = fmt.Sprintf("sym %d: %s", s, format)
- }
- format += "\n"
- fmt.Fprintf(os.Stderr, format, args...)
- afterErrorAction()
-}
default:
log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
}
- ctxt.loader = loader.NewLoader(flags, elfsetstring)
+ ctxt.loader = loader.NewLoader(flags, elfsetstring, &ctxt.ErrorReporter.ErrorReporter)
ctxt.ErrorReporter.SymName = func(s loader.Sym) string {
return ctxt.loader.SymName(s)
}
import (
"cmd/internal/objabi"
"cmd/internal/sys"
+ "cmd/link/internal/loader"
"cmd/link/internal/sym"
"log"
"runtime"
)
func linknew(arch *sys.Arch) *Link {
+ ler := loader.ErrorReporter{AfterErrorAction: afterErrorAction}
ctxt := &Link{
- Target: Target{Arch: arch},
- Syms: sym.NewSymbols(),
- outSem: make(chan int, 2*runtime.GOMAXPROCS(0)),
- Out: NewOutBuf(arch),
- LibraryByPkg: make(map[string]*sym.Library),
- numelfsym: 1,
+ Target: Target{Arch: arch},
+ Syms: sym.NewSymbols(),
+ outSem: make(chan int, 2*runtime.GOMAXPROCS(0)),
+ Out: NewOutBuf(arch),
+ LibraryByPkg: make(map[string]*sym.Library),
+ numelfsym: 1,
+ ErrorReporter: ErrorReporter{ErrorReporter: ler},
}
if objabi.GOARCH != arch.Name {
// Logging an error means that on exit cmd/link will delete any
// output file and return a non-zero error code.
func (ctxt *Link) Errorf(s loader.Sym, format string, args ...interface{}) {
- if s != 0 && ctxt.loader != nil {
- sn := ctxt.loader.SymName(s)
- format = sn + ": " + format
- } else {
- format = fmt.Sprintf("sym %d: %s", s, format)
+ if ctxt.loader != nil {
+ ctxt.loader.Errorf(s, format, args)
+ return
}
+ // Note: this is not expected to happen very often.
+ format = fmt.Sprintf("sym %d: %s", s, format)
format += "\n"
fmt.Fprintf(os.Stderr, format, args...)
afterErrorAction()
elfsetstring elfsetstringFunc
+ errorReporter *ErrorReporter
+
SymLookup func(name string, ver int) *sym.Symbol
}
FlagStrictDups = 1 << iota
)
-func NewLoader(flags uint32, elfsetstring elfsetstringFunc) *Loader {
+func NewLoader(flags uint32, elfsetstring elfsetstringFunc, reporter *ErrorReporter) *Loader {
nbuiltin := goobj2.NBuiltin()
- return &Loader{
+ ldr := &Loader{
start: make(map[*oReader]Sym),
objs: []objIdx{{}}, // reserve index 0 for nil symbol
objSyms: []objSym{{}}, // reserve index 0 for nil symbol
builtinSyms: make([]Sym, nbuiltin),
flags: flags,
elfsetstring: elfsetstring,
+ errorReporter: reporter,
sects: []*sym.Section{nil}, // reserve index 0 for nil section
}
+ reporter.ldr = ldr
+ return ldr
}
// Add object file r, return the start index.
return textp2
}
+// ErrorReporter is a helper class for reporting errors.
+type ErrorReporter struct {
+ ldr *Loader
+ AfterErrorAction func()
+}
+
+// Errorf method logs an error message.
+//
+// After each error, the error actions function will be invoked; this
+// will either terminate the link immediately (if -h option given)
+// or it will keep a count and exit if more than 20 errors have been printed.
+//
+// Logging an error means that on exit cmd/link will delete any
+// output file and return a non-zero error code.
+//
+func (reporter *ErrorReporter) Errorf(s Sym, format string, args ...interface{}) {
+ if s != 0 && reporter.ldr.SymName(s) != "" {
+ format = reporter.ldr.SymName(s) + ": " + format
+ } else {
+ format = fmt.Sprintf("sym %d: %s", s, format)
+ }
+ format += "\n"
+ fmt.Fprintf(os.Stderr, format, args...)
+ reporter.AfterErrorAction()
+}
+
+// GetErrorReporter returns the loader's associated error reporter.
+func (l *Loader) GetErrorReporter() *ErrorReporter {
+ return l.errorReporter
+}
+
+// Errorf method logs an error message. See ErrorReporter.Errorf for details.
+func (l *Loader) Errorf(s Sym, format string, args ...interface{}) {
+ l.errorReporter.Errorf(s, format, args)
+}
+
// For debugging.
func (l *Loader) Dump() {
fmt.Println("objs")
return s
}
-func TestAddMaterializedSymbol(t *testing.T) {
+func mkLoader() *Loader {
edummy := func(s *sym.Symbol, str string, off int) {}
- ldr := NewLoader(0, edummy)
+ er := ErrorReporter{}
+ ldr := NewLoader(0, edummy, &er)
+ er.ldr = ldr
+ return ldr
+}
+
+func TestAddMaterializedSymbol(t *testing.T) {
+ ldr := mkLoader()
dummyOreader := oReader{version: -1, syms: make([]Sym, 100)}
or := &dummyOreader
type addFunc func(l *Loader, s Sym, s2 Sym) Sym
func TestAddDataMethods(t *testing.T) {
- edummy := func(s *sym.Symbol, str string, off int) {}
- ldr := NewLoader(0, edummy)
+ ldr := mkLoader()
dummyOreader := oReader{version: -1, syms: make([]Sym, 100)}
or := &dummyOreader
}
func TestOuterSub(t *testing.T) {
- edummy := func(s *sym.Symbol, str string, off int) {}
- ldr := NewLoader(0, edummy)
+ ldr := mkLoader()
dummyOreader := oReader{version: -1, syms: make([]Sym, 100)}
or := &dummyOreader