diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go index 877fa8979e..ccb8493737 100644 --- a/src/cmd/link/internal/ld/link.go +++ b/src/cmd/link/internal/ld/link.go @@ -173,27 +173,22 @@ type Shlib struct { // Link holds the context for writing object code from a compiler // or for reading that input into the linker. type Link struct { + Symbols + Arch *sys.Arch Debugvlog int Bso *bufio.Writer Loaded bool // set after all inputs have been loaded as symbols - // Symbol lookup based on name and indexed by version. - Hash []map[string]*Symbol - - Allsym []*Symbol - Tlsg *Symbol - Libdir []string - Library []*Library - Shlibs []Shlib - Tlsoffset int - - Version int - Textp []*Symbol - Filesyms []*Symbol - Moduledata *Symbol - SymbolBatch []Symbol + Tlsg *Symbol + Libdir []string + Library []*Library + Shlibs []Shlib + Tlsoffset int + Textp []*Symbol + Filesyms []*Symbol + Moduledata *Symbol } // The smallest possible offset from the hardware stack pointer to a local @@ -213,11 +208,6 @@ func (ctxt *Link) FixedFrameSize() int64 { } } -func (l *Link) IncVersion() { - l.Version++ - l.Hash = append(l.Hash, make(map[string]*Symbol)) -} - func (l *Link) Logf(format string, args ...interface{}) { fmt.Fprintf(l.Bso, format, args...) l.Bso.Flush() diff --git a/src/cmd/link/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go index 88b82e62e1..4cdbac49df 100644 --- a/src/cmd/link/internal/ld/sym.go +++ b/src/cmd/link/internal/ld/sym.go @@ -39,13 +39,15 @@ import ( func linknew(arch *sys.Arch) *Link { ctxt := &Link{ - Hash: []map[string]*Symbol{ - // preallocate about 2mb for hash of - // non static symbols - make(map[string]*Symbol, 100000), + Symbols: Symbols{ + hash: []map[string]*Symbol{ + // preallocate about 2mb for hash of + // non static symbols + make(map[string]*Symbol, 100000), + }, + Allsym: make([]*Symbol, 0, 100000), }, - Allsym: make([]*Symbol, 0, 100000), - Arch: arch, + Arch: arch, } if obj.GOARCH != arch.Name { @@ -132,36 +134,14 @@ func (ctxt *Link) computeTLSOffset() { } func linknewsym(ctxt *Link, name string, v int) *Symbol { - batch := ctxt.SymbolBatch - if len(batch) == 0 { - batch = make([]Symbol, 1000) - } - s := &batch[0] - ctxt.SymbolBatch = batch[1:] - - s.Dynid = -1 - s.Plt = -1 - s.Got = -1 - s.Name = name - s.Version = int16(v) - ctxt.Allsym = append(ctxt.Allsym, s) - - return s + return ctxt.newsym(name, v) } func Linklookup(ctxt *Link, name string, v int) *Symbol { - m := ctxt.Hash[v] - s := m[name] - if s != nil { - return s - } - s = linknewsym(ctxt, name, v) - s.Extname = s.Name - m[name] = s - return s + return ctxt.Lookup(name, v) } // read-only lookup func Linkrlookup(ctxt *Link, name string, v int) *Symbol { - return ctxt.Hash[v][name] + return ctxt.ROLookup(name, v) } diff --git a/src/cmd/link/internal/ld/symbols.go b/src/cmd/link/internal/ld/symbols.go new file mode 100644 index 0000000000..d190a8c1ca --- /dev/null +++ b/src/cmd/link/internal/ld/symbols.go @@ -0,0 +1,90 @@ +// Derived from Inferno utils/6l/l.h and related files. +// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/l.h +// +// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. +// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) +// Portions Copyright © 1997-1999 Vita Nuova Limited +// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) +// Portions Copyright © 2004,2006 Bruce Ellis +// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) +// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others +// Portions Copyright © 2009 The Go Authors. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package ld + +type Symbols struct { + symbolBatch []Symbol + + // Symbol lookup based on name and indexed by version. + hash []map[string]*Symbol + + Allsym []*Symbol + + Version int +} + +func (syms *Symbols) newsym(name string, v int) *Symbol { + batch := syms.symbolBatch + if len(batch) == 0 { + batch = make([]Symbol, 1000) + } + s := &batch[0] + syms.symbolBatch = batch[1:] + + s.Dynid = -1 + s.Plt = -1 + s.Got = -1 + s.Name = name + s.Version = int16(v) + syms.Allsym = append(syms.Allsym, s) + + return s +} + +// Look up the symbol with the given name and version, creating the +// symbol if it is not found. +func (syms *Symbols) Lookup(name string, v int) *Symbol { + m := syms.hash[v] + s := m[name] + if s != nil { + return s + } + s = syms.newsym(name, v) + s.Extname = s.Name + m[name] = s + return s +} + +// Look up the symbol with the given name and version, returning nil +// if it is not found. +func (syms *Symbols) ROLookup(name string, v int) *Symbol { + return syms.hash[v][name] +} + +// Allocate a new version (i.e. symbol namespace). +// +// TODO(mwhudson): This would feel more natural if it returned the new +// version (or if we dropped Symbols.Version entirely and just +// returned len(syms.hash)) +func (syms *Symbols) IncVersion() { + syms.Version++ + syms.hash = append(syms.hash, make(map[string]*Symbol)) +}