flag.StringVar(&benchfile, "bench", "", "append benchmark times to `file`")
flag.BoolVar(&smallFrames, "smallframes", false, "reduce the size limit for stack allocated objects")
flag.BoolVar(&Ctxt.UseBASEntries, "dwarfbasentries", Ctxt.UseBASEntries, "use base address selection entries in DWARF")
- flag.BoolVar(&Ctxt.Flag_newobj, "newobj", false, "use new object file format")
flag.StringVar(&jsonLogOpt, "json", "", "version,destination for JSON compiler/optimizer logging")
objabi.Flagparse(usage)
// Record flags that affect the build result. (And don't
// record flags that don't, since that would cause spurious
// changes in the binary.)
- recordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes", "newobj")
+ recordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes")
if smallFrames {
maxStackVarSize = 128 * 1024
}
types.FmtLeft = int(FmtLeft)
types.FmtUnsigned = int(FmtUnsigned)
- types.FErr = FErr
+ types.FErr = int(FErr)
types.Ctxt = Ctxt
initUniverse()
return found, ehdrFlags, nil
}
-func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string, flags uint32) ([]*sym.Symbol, uint32, error) {
- newSym := func(name string, version int) *sym.Symbol {
- return l.Create(name, syms)
- }
- lookup := func(name string, version int) *sym.Symbol {
- return l.LookupOrCreate(name, version, syms)
- }
- return load(arch, syms.IncVersion(), newSym, lookup, f, pkg, length, pn, flags)
-}
-
-func LoadOld(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string, flags uint32) ([]*sym.Symbol, uint32, error) {
- return load(arch, syms.IncVersion(), syms.Newsym, syms.Lookup, f, pkg, length, pn, flags)
-}
-
-type lookupFunc func(string, int) *sym.Symbol
-
-// load loads the ELF file pn from f.
+// Load loads the ELF file pn from f.
// Symbols are written into syms, and a slice of the text symbols is returned.
//
// On ARM systems, Load will attempt to determine what ELF header flags to
// parameter initEhdrFlags contains the current header flags for the output
// object, and the returned ehdrFlags contains what this Load function computes.
// TODO: find a better place for this logic.
-func load(arch *sys.Arch, localSymVersion int, newSym, lookup lookupFunc, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []*sym.Symbol, ehdrFlags uint32, err error) {
+func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []*sym.Symbol, ehdrFlags uint32, err error) {
+ localSymVersion := syms.IncVersion()
++ newSym := func(name string, version int) *sym.Symbol {
++ return l.Create(name, syms)
++ }
+ lookup := func(name string, version int) *sym.Symbol {
+ return l.LookupOrCreate(name, version, syms)
+ }
errorf := func(str string, args ...interface{}) ([]*sym.Symbol, uint32, error) {
return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
}
for i := 1; i < elfobj.nsymtab; i++ {
var elfsym ElfSym
- if err := readelfsym(lookup, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
+ if err := readelfsym(newSym, lookup, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
return errorf("%s: malformed elf file: %v", pn, err)
}
symbols[i] = elfsym.sym
rp.Sym = nil
} else {
var elfsym ElfSym
- if err := readelfsym(lookup, arch, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
+ if err := readelfsym(newSym, lookup, arch, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
return errorf("malformed elf file: %v", err)
}
elfsym.sym = symbols[info>>32]
return nil
}
- func readelfsym(lookup func(string, int) *sym.Symbol, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
-func readelfsym(newSym, lookup lookupFunc, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
++func readelfsym(newSym, lookup func(string, int) *sym.Symbol, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
if i >= elfobj.nsymtab || i < 0 {
err = fmt.Errorf("invalid elf symbol index")
return err
// local names and hidden global names are unique
// and should only be referenced by their index, not name, so we
// don't bother to add them into the hash table
- s = lookup(elfsym.name, localSymVersion)
+ // FIXME: pass empty string here for name? This would
+ // reduce mem use, but also (possibly) make it harder
+ // to debug problems.
+ s = newSym(elfsym.name, localSymVersion)
s.Attr |= sym.AttrVisibilityHidden
}
Syms []*sym.Symbol // indexed symbols. XXX we still make sym.Symbol for now.
+ anonVersion int // most recently assigned ext static sym pseudo-version
+
Reachable bitmap // bitmap of reachable symbols, indexed by global index
// Used to implement field tracking; created during deadcode if
// This is more like Syms.ROLookup than Lookup -- it doesn't create
// new symbol.
func (l *Loader) Lookup(name string, ver int) Sym {
- if ver >= sym.SymVerStatic {
+ if ver >= sym.SymVerStatic || ver < 0 {
return l.extStaticSyms[nameVer{name, ver}]
}
return l.symsByName[ver][name]
l.Syms[oldI] = nil
}
- // For now, add all symbols to ctxt.Syms.
+ // Add symbols to the ctxt.Syms lookup table. This explicitly
+ // skips things created via loader.Create (marked with versions
+ // less than zero), since if we tried to add these we'd wind up
+ // with collisions. Along the way, update the version from the
+ // negative anon version to something larger than sym.SymVerStatic
+ // (needed so that sym.symbol.IsFileLocal() works properly).
+ anonVerReplacement := syms.IncVersion()
for _, s := range l.Syms {
- if s != nil && s.Name != "" {
+ if s == nil {
+ continue
+ }
+ if s.Name != "" && s.Version >= 0 {
syms.Add(s)
}
+ if s.Version < 0 {
+ s.Version = int16(anonVerReplacement)
+ }
}
-
}
// addNewSym adds a new sym.Symbol to the i-th index in the list of symbols.
return s
}
+ // Create creates a symbol with the specified name, returning a
+ // sym.Symbol object for it. This method is intended for static/hidden
+ // symbols discovered while loading host objects. We can see more than
+ // one instance of a given static symbol with the same name/version,
+ // so we can't add them to the lookup tables "as is". Instead assign
+ // them fictitious (unique) versions, starting at -1 and decreasing by
+ // one for each newly created symbol, and record them in the
+ // extStaticSyms hash.
+ func (l *Loader) Create(name string, syms *sym.Symbols) *sym.Symbol {
+ i := l.max + 1
+ l.max++
+ if l.extStart == 0 {
+ l.extStart = i
+ }
+
+ // Assign a new unique negative version -- this is to mark the
+ // symbol so that it can be skipped when ExtractSymbols is adding
+ // ext syms to the sym.Symbols hash.
+ l.anonVersion--
+ ver := l.anonVersion
+ l.extSyms = append(l.extSyms, nameVer{name, ver})
+ l.growSyms(int(i))
+ s := syms.Newsym(name, ver)
+ l.Syms[i] = s
+ l.extStaticSyms[nameVer{name, ver}] = i
+
+ return s
+ }
+
func loadObjFull(l *Loader, r *oReader) {
lib := r.unit.Lib
istart := l.startIndex(r)
rs = 0
sz = 0
}
- if rs != 0 && l.SymType(rs) == sym.SABIALIAS {
+ if rs != 0 && l.Syms[rs] != nil && l.Syms[rs].Type == sym.SABIALIAS {
rsrelocs := l.Relocs(rs)
rs = rsrelocs.At(0).Sym
}